1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.eclipse.org/org/documents/epl-v10.php 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.ide.eclipse.adt.internal.launch; 18 19 import com.android.ddmuilib.ImageLoader; 20 import com.android.ide.eclipse.adt.AdtPlugin; 21 import com.android.ide.eclipse.adt.internal.launch.AndroidLaunchConfiguration.TargetMode; 22 import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs; 23 import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; 24 import com.android.ide.eclipse.adt.internal.sdk.AdtConsoleSdkLog; 25 import com.android.ide.eclipse.adt.internal.sdk.Sdk; 26 import com.android.prefs.AndroidLocation.AndroidLocationException; 27 import com.android.sdklib.IAndroidTarget; 28 import com.android.sdklib.NullSdkLog; 29 import com.android.sdklib.internal.avd.AvdInfo; 30 import com.android.sdklib.internal.avd.AvdManager; 31 import com.android.sdkuilib.internal.widgets.AvdSelector; 32 import com.android.sdkuilib.internal.widgets.AvdSelector.DisplayMode; 33 34 import org.eclipse.core.resources.IProject; 35 import org.eclipse.core.runtime.CoreException; 36 import org.eclipse.debug.core.ILaunchConfiguration; 37 import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; 38 import org.eclipse.debug.ui.AbstractLaunchConfigurationTab; 39 import org.eclipse.jdt.core.IJavaProject; 40 import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; 41 import org.eclipse.jface.preference.IPreferenceStore; 42 import org.eclipse.swt.SWT; 43 import org.eclipse.swt.events.ModifyEvent; 44 import org.eclipse.swt.events.ModifyListener; 45 import org.eclipse.swt.events.SelectionAdapter; 46 import org.eclipse.swt.events.SelectionEvent; 47 import org.eclipse.swt.graphics.Font; 48 import org.eclipse.swt.graphics.Image; 49 import org.eclipse.swt.layout.GridData; 50 import org.eclipse.swt.layout.GridLayout; 51 import org.eclipse.swt.widgets.Button; 52 import org.eclipse.swt.widgets.Combo; 53 import org.eclipse.swt.widgets.Composite; 54 import org.eclipse.swt.widgets.Group; 55 import org.eclipse.swt.widgets.Label; 56 import org.eclipse.swt.widgets.Text; 57 58 /** 59 * Launch configuration tab to control the parameters of the Emulator 60 */ 61 public class EmulatorConfigTab extends AbstractLaunchConfigurationTab { 62 63 private final static String[][] NETWORK_SPEEDS = new String[][] { 64 { "Full", "full" }, //$NON-NLS-2$ 65 { "GSM", "gsm" }, //$NON-NLS-2$ 66 { "HSCSD", "hscsd" }, //$NON-NLS-2$ 67 { "GPRS", "gprs" }, //$NON-NLS-2$ 68 { "EDGE", "edge" }, //$NON-NLS-2$ 69 { "UMTS", "umts" }, //$NON-NLS-2$ 70 { "HSPDA", "hsdpa" }, //$NON-NLS-2$ 71 }; 72 73 private final static String[][] NETWORK_LATENCIES = new String[][] { 74 { "None", "none" }, //$NON-NLS-2$ 75 { "GPRS", "gprs" }, //$NON-NLS-2$ 76 { "EDGE", "edge" }, //$NON-NLS-2$ 77 { "UMTS", "umts" }, //$NON-NLS-2$ 78 }; 79 80 private Button mAutoTargetButton; 81 private Button mManualTargetButton; 82 83 private AvdSelector mPreferredAvdSelector; 84 85 private Combo mSpeedCombo; 86 87 private Combo mDelayCombo; 88 89 private Group mEmulatorOptionsGroup; 90 91 private Text mEmulatorCLOptions; 92 93 private Button mWipeDataButton; 94 95 private Button mNoBootAnimButton; 96 97 private Label mPreferredAvdLabel; 98 99 private IAndroidTarget mProjectTarget; 100 101 /** 102 * Returns the emulator ready speed option value. 103 * @param value The index of the combo selection. 104 */ 105 public static String getSpeed(int value) { 106 try { 107 return NETWORK_SPEEDS[value][1]; 108 } catch (ArrayIndexOutOfBoundsException e) { 109 return NETWORK_SPEEDS[LaunchConfigDelegate.DEFAULT_SPEED][1]; 110 } 111 } 112 113 /** 114 * Returns the emulator ready network latency value. 115 * @param value The index of the combo selection. 116 */ 117 public static String getDelay(int value) { 118 try { 119 return NETWORK_LATENCIES[value][1]; 120 } catch (ArrayIndexOutOfBoundsException e) { 121 return NETWORK_LATENCIES[LaunchConfigDelegate.DEFAULT_DELAY][1]; 122 } 123 } 124 125 /** 126 * 127 */ 128 public EmulatorConfigTab() { 129 } 130 131 /* (non-Javadoc) 132 * @see org.eclipse.debug.ui.ILaunchConfigurationTab#createControl(org.eclipse.swt.widgets.Composite) 133 */ 134 public void createControl(Composite parent) { 135 Font font = parent.getFont(); 136 137 // reload the AVDs to make sure we are up to date 138 try { 139 Sdk.getCurrent().getAvdManager().reloadAvds(NullSdkLog.getLogger()); 140 } catch (AndroidLocationException e1) { 141 // this happens if the AVD Manager failed to find the folder in which the AVDs are 142 // stored. There isn't much we can do at this point. 143 } 144 145 Composite topComp = new Composite(parent, SWT.NONE); 146 setControl(topComp); 147 GridLayout topLayout = new GridLayout(); 148 topLayout.numColumns = 1; 149 topLayout.verticalSpacing = 0; 150 topComp.setLayout(topLayout); 151 topComp.setFont(font); 152 153 GridData gd; 154 GridLayout layout; 155 156 // radio button for the target mode 157 Group targetModeGroup = new Group(topComp, SWT.NONE); 158 targetModeGroup.setText("Deployment Target Selection Mode"); 159 gd = new GridData(GridData.FILL_HORIZONTAL); 160 targetModeGroup.setLayoutData(gd); 161 layout = new GridLayout(); 162 layout.numColumns = 1; 163 targetModeGroup.setLayout(layout); 164 targetModeGroup.setFont(font); 165 166 mManualTargetButton = new Button(targetModeGroup, SWT.RADIO); 167 mManualTargetButton.setText("Manual"); 168 // Since there are only 2 radio buttons, we can put a listener on only one (they 169 // are both called on select and unselect event. 170 171 // add the radio button 172 mAutoTargetButton = new Button(targetModeGroup, SWT.RADIO); 173 mAutoTargetButton.setText("Automatic"); 174 mAutoTargetButton.setSelection(true); 175 mAutoTargetButton.addSelectionListener(new SelectionAdapter() { 176 // called when selection changes 177 @Override 178 public void widgetSelected(SelectionEvent e) { 179 updateLaunchConfigurationDialog(); 180 181 boolean auto = mAutoTargetButton.getSelection(); 182 mPreferredAvdSelector.setEnabled(auto); 183 mPreferredAvdLabel.setEnabled(auto); 184 } 185 }); 186 187 Composite offsetComp = new Composite(targetModeGroup, SWT.NONE); 188 offsetComp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); 189 layout = new GridLayout(1, false); 190 layout.marginRight = layout.marginHeight = 0; 191 layout.marginLeft = 30; 192 offsetComp.setLayout(layout); 193 194 mPreferredAvdLabel = new Label(offsetComp, SWT.NONE); 195 mPreferredAvdLabel.setText("Select a preferred Android Virtual Device for deployment:"); 196 197 // create the selector with no manager, we'll reset the manager every time this is 198 // displayed to ensure we have the latest one (dialog is reused but SDK could have 199 // been changed in between. 200 mPreferredAvdSelector = new AvdSelector(offsetComp, 201 Sdk.getCurrent().getSdkLocation(), 202 null /* avd manager */, 203 DisplayMode.SIMPLE_CHECK, 204 new AdtConsoleSdkLog()); 205 mPreferredAvdSelector.setTableHeightHint(100); 206 mPreferredAvdSelector.setSelectionListener(new SelectionAdapter() { 207 @Override 208 public void widgetSelected(SelectionEvent e) { 209 updateLaunchConfigurationDialog(); 210 } 211 }); 212 213 // emulator size 214 mEmulatorOptionsGroup = new Group(topComp, SWT.NONE); 215 mEmulatorOptionsGroup.setText("Emulator launch parameters:"); 216 mEmulatorOptionsGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); 217 layout = new GridLayout(); 218 layout.numColumns = 2; 219 mEmulatorOptionsGroup.setLayout(layout); 220 mEmulatorOptionsGroup.setFont(font); 221 222 // network options 223 new Label(mEmulatorOptionsGroup, SWT.NONE).setText("Network Speed:"); 224 225 mSpeedCombo = new Combo(mEmulatorOptionsGroup, SWT.READ_ONLY); 226 for (String[] speed : NETWORK_SPEEDS) { 227 mSpeedCombo.add(speed[0]); 228 } 229 mSpeedCombo.addSelectionListener(new SelectionAdapter() { 230 // called when selection changes 231 @Override 232 public void widgetSelected(SelectionEvent e) { 233 updateLaunchConfigurationDialog(); 234 } 235 }); 236 mSpeedCombo.pack(); 237 238 new Label(mEmulatorOptionsGroup, SWT.NONE).setText("Network Latency:"); 239 240 mDelayCombo = new Combo(mEmulatorOptionsGroup, SWT.READ_ONLY); 241 242 for (String[] delay : NETWORK_LATENCIES) { 243 mDelayCombo.add(delay[0]); 244 } 245 mDelayCombo.addSelectionListener(new SelectionAdapter() { 246 // called when selection changes 247 @Override 248 public void widgetSelected(SelectionEvent e) { 249 updateLaunchConfigurationDialog(); 250 } 251 }); 252 mDelayCombo.pack(); 253 254 // wipe data option 255 mWipeDataButton = new Button(mEmulatorOptionsGroup, SWT.CHECK); 256 mWipeDataButton.setText("Wipe User Data"); 257 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."); 258 gd = new GridData(GridData.FILL_HORIZONTAL); 259 gd.horizontalSpan = 2; 260 mWipeDataButton.setLayoutData(gd); 261 mWipeDataButton.addSelectionListener(new SelectionAdapter() { 262 @Override 263 public void widgetSelected(SelectionEvent e) { 264 updateLaunchConfigurationDialog(); 265 } 266 }); 267 268 // no boot anim option 269 mNoBootAnimButton = new Button(mEmulatorOptionsGroup, SWT.CHECK); 270 mNoBootAnimButton.setText("Disable Boot Animation"); 271 mNoBootAnimButton.setToolTipText("Check this if you want to disable the boot animation. This can help the emulator start faster on slow machines."); 272 gd = new GridData(GridData.FILL_HORIZONTAL); 273 gd.horizontalSpan = 2; 274 mNoBootAnimButton.setLayoutData(gd); 275 mNoBootAnimButton.addSelectionListener(new SelectionAdapter() { 276 @Override 277 public void widgetSelected(SelectionEvent e) { 278 updateLaunchConfigurationDialog(); 279 } 280 }); 281 282 // custom command line option for emulator 283 Label l = new Label(mEmulatorOptionsGroup, SWT.NONE); 284 l.setText("Additional Emulator Command Line Options"); 285 gd = new GridData(GridData.FILL_HORIZONTAL); 286 gd.horizontalSpan = 2; 287 l.setLayoutData(gd); 288 289 mEmulatorCLOptions = new Text(mEmulatorOptionsGroup, SWT.BORDER); 290 gd = new GridData(GridData.FILL_HORIZONTAL); 291 gd.horizontalSpan = 2; 292 mEmulatorCLOptions.setLayoutData(gd); 293 mEmulatorCLOptions.addModifyListener(new ModifyListener() { 294 public void modifyText(ModifyEvent e) { 295 updateLaunchConfigurationDialog(); 296 } 297 }); 298 } 299 300 /* (non-Javadoc) 301 * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getName() 302 */ 303 public String getName() { 304 return "Target"; 305 } 306 307 @Override 308 public Image getImage() { 309 return ImageLoader.getDdmUiLibLoader().loadImage("emulator.png", null); //$NON-NLS-1$ 310 } 311 312 private void updateAvdList(AvdManager avdManager) { 313 if (avdManager == null) { 314 avdManager = Sdk.getCurrent().getAvdManager(); 315 } 316 317 mPreferredAvdSelector.setManager(avdManager); 318 mPreferredAvdSelector.setFilter(mProjectTarget); 319 mPreferredAvdSelector.refresh(false); 320 } 321 322 /* (non-Javadoc) 323 * @see org.eclipse.debug.ui.ILaunchConfigurationTab#initializeFrom(org.eclipse.debug.core.ILaunchConfiguration) 324 */ 325 public void initializeFrom(ILaunchConfiguration configuration) { 326 AvdManager avdManager = Sdk.getCurrent().getAvdManager(); 327 328 TargetMode mode = LaunchConfigDelegate.DEFAULT_TARGET_MODE; // true == automatic 329 try { 330 mode = TargetMode.getMode(configuration.getAttribute( 331 LaunchConfigDelegate.ATTR_TARGET_MODE, mode.getValue())); 332 } catch (CoreException e) { 333 // let's not do anything here, we'll use the default value 334 } 335 mAutoTargetButton.setSelection(mode.getValue()); 336 mManualTargetButton.setSelection(!mode.getValue()); 337 338 // look for the project name to get its target. 339 String stringValue = ""; 340 try { 341 stringValue = configuration.getAttribute( 342 IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, stringValue); 343 } catch (CoreException ce) { 344 // let's not do anything here, we'll use the default value 345 } 346 347 IProject project = null; 348 349 // get the list of existing Android projects from the workspace. 350 IJavaProject[] projects = BaseProjectHelper.getAndroidProjects(null /*filter*/); 351 if (projects != null) { 352 // look for the project whose name we read from the configuration. 353 for (IJavaProject p : projects) { 354 if (p.getElementName().equals(stringValue)) { 355 project = p.getProject(); 356 break; 357 } 358 } 359 } 360 361 // update the AVD list 362 if (project != null) { 363 mProjectTarget = Sdk.getCurrent().getTarget(project); 364 } 365 366 updateAvdList(avdManager); 367 368 stringValue = ""; 369 try { 370 stringValue = configuration.getAttribute(LaunchConfigDelegate.ATTR_AVD_NAME, 371 stringValue); 372 } catch (CoreException e) { 373 // let's not do anything here, we'll use the default value 374 } 375 376 if (stringValue != null && stringValue.length() > 0 && avdManager != null) { 377 AvdInfo targetAvd = avdManager.getAvd(stringValue, true /*validAvdOnly*/); 378 mPreferredAvdSelector.setSelection(targetAvd); 379 } else { 380 mPreferredAvdSelector.setSelection(null); 381 } 382 383 boolean value = LaunchConfigDelegate.DEFAULT_WIPE_DATA; 384 try { 385 value = configuration.getAttribute(LaunchConfigDelegate.ATTR_WIPE_DATA, value); 386 } catch (CoreException e) { 387 // let's not do anything here, we'll use the default value 388 } 389 mWipeDataButton.setSelection(value); 390 391 value = LaunchConfigDelegate.DEFAULT_NO_BOOT_ANIM; 392 try { 393 value = configuration.getAttribute(LaunchConfigDelegate.ATTR_NO_BOOT_ANIM, value); 394 } catch (CoreException e) { 395 // let's not do anything here, we'll use the default value 396 } 397 mNoBootAnimButton.setSelection(value); 398 399 int index = -1; 400 401 index = LaunchConfigDelegate.DEFAULT_SPEED; 402 try { 403 index = configuration.getAttribute(LaunchConfigDelegate.ATTR_SPEED, 404 index); 405 } catch (CoreException e) { 406 // let's not do anything here, we'll use the default value 407 } 408 if (index == -1) { 409 mSpeedCombo.clearSelection(); 410 } else { 411 mSpeedCombo.select(index); 412 } 413 414 index = LaunchConfigDelegate.DEFAULT_DELAY; 415 try { 416 index = configuration.getAttribute(LaunchConfigDelegate.ATTR_DELAY, 417 index); 418 } catch (CoreException e) { 419 // let's not do anything here, we'll put a proper value in 420 // performApply anyway 421 } 422 if (index == -1) { 423 mDelayCombo.clearSelection(); 424 } else { 425 mDelayCombo.select(index); 426 } 427 428 String commandLine = null; 429 try { 430 commandLine = configuration.getAttribute( 431 LaunchConfigDelegate.ATTR_COMMANDLINE, ""); //$NON-NLS-1$ 432 } catch (CoreException e) { 433 // let's not do anything here, we'll use the default value 434 } 435 if (commandLine != null) { 436 mEmulatorCLOptions.setText(commandLine); 437 } 438 } 439 440 /* (non-Javadoc) 441 * @see org.eclipse.debug.ui.ILaunchConfigurationTab#performApply(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy) 442 */ 443 public void performApply(ILaunchConfigurationWorkingCopy configuration) { 444 configuration.setAttribute(LaunchConfigDelegate.ATTR_TARGET_MODE, 445 mAutoTargetButton.getSelection()); 446 AvdInfo avd = mPreferredAvdSelector.getSelected(); 447 if (avd != null) { 448 configuration.setAttribute(LaunchConfigDelegate.ATTR_AVD_NAME, avd.getName()); 449 } else { 450 configuration.setAttribute(LaunchConfigDelegate.ATTR_AVD_NAME, (String)null); 451 } 452 configuration.setAttribute(LaunchConfigDelegate.ATTR_SPEED, 453 mSpeedCombo.getSelectionIndex()); 454 configuration.setAttribute(LaunchConfigDelegate.ATTR_DELAY, 455 mDelayCombo.getSelectionIndex()); 456 configuration.setAttribute(LaunchConfigDelegate.ATTR_COMMANDLINE, 457 mEmulatorCLOptions.getText()); 458 configuration.setAttribute(LaunchConfigDelegate.ATTR_WIPE_DATA, 459 mWipeDataButton.getSelection()); 460 configuration.setAttribute(LaunchConfigDelegate.ATTR_NO_BOOT_ANIM, 461 mNoBootAnimButton.getSelection()); 462 } 463 464 /* (non-Javadoc) 465 * @see org.eclipse.debug.ui.ILaunchConfigurationTab#setDefaults(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy) 466 */ 467 public void setDefaults(ILaunchConfigurationWorkingCopy configuration) { 468 configuration.setAttribute(LaunchConfigDelegate.ATTR_TARGET_MODE, 469 LaunchConfigDelegate.DEFAULT_TARGET_MODE.getValue()); 470 configuration.setAttribute(LaunchConfigDelegate.ATTR_SPEED, 471 LaunchConfigDelegate.DEFAULT_SPEED); 472 configuration.setAttribute(LaunchConfigDelegate.ATTR_DELAY, 473 LaunchConfigDelegate.DEFAULT_DELAY); 474 configuration.setAttribute(LaunchConfigDelegate.ATTR_WIPE_DATA, 475 LaunchConfigDelegate.DEFAULT_WIPE_DATA); 476 configuration.setAttribute(LaunchConfigDelegate.ATTR_NO_BOOT_ANIM, 477 LaunchConfigDelegate.DEFAULT_NO_BOOT_ANIM); 478 479 IPreferenceStore store = AdtPlugin.getDefault().getPreferenceStore(); 480 String emuOptions = store.getString(AdtPrefs.PREFS_EMU_OPTIONS); 481 configuration.setAttribute(LaunchConfigDelegate.ATTR_COMMANDLINE, emuOptions); 482 } 483 } 484