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 @Override 135 public void createControl(Composite parent) { 136 Font font = parent.getFont(); 137 138 // reload the AVDs to make sure we are up to date 139 try { 140 Sdk.getCurrent().getAvdManager().reloadAvds(NullSdkLog.getLogger()); 141 } catch (AndroidLocationException e1) { 142 // this happens if the AVD Manager failed to find the folder in which the AVDs are 143 // stored. There isn't much we can do at this point. 144 } 145 146 Composite topComp = new Composite(parent, SWT.NONE); 147 setControl(topComp); 148 GridLayout topLayout = new GridLayout(); 149 topLayout.numColumns = 1; 150 topLayout.verticalSpacing = 0; 151 topComp.setLayout(topLayout); 152 topComp.setFont(font); 153 154 GridData gd; 155 GridLayout layout; 156 157 // radio button for the target mode 158 Group targetModeGroup = new Group(topComp, SWT.NONE); 159 targetModeGroup.setText("Deployment Target Selection Mode"); 160 gd = new GridData(GridData.FILL_HORIZONTAL); 161 targetModeGroup.setLayoutData(gd); 162 layout = new GridLayout(); 163 layout.numColumns = 1; 164 targetModeGroup.setLayout(layout); 165 targetModeGroup.setFont(font); 166 167 mManualTargetButton = new Button(targetModeGroup, SWT.RADIO); 168 mManualTargetButton.setText("Manual"); 169 // Since there are only 2 radio buttons, we can put a listener on only one (they 170 // are both called on select and unselect event. 171 172 // add the radio button 173 mAutoTargetButton = new Button(targetModeGroup, SWT.RADIO); 174 mAutoTargetButton.setText("Automatic"); 175 mAutoTargetButton.setSelection(true); 176 mAutoTargetButton.addSelectionListener(new SelectionAdapter() { 177 // called when selection changes 178 @Override 179 public void widgetSelected(SelectionEvent e) { 180 updateLaunchConfigurationDialog(); 181 182 boolean auto = mAutoTargetButton.getSelection(); 183 mPreferredAvdSelector.setEnabled(auto); 184 mPreferredAvdLabel.setEnabled(auto); 185 } 186 }); 187 188 Composite offsetComp = new Composite(targetModeGroup, SWT.NONE); 189 offsetComp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); 190 layout = new GridLayout(1, false); 191 layout.marginRight = layout.marginHeight = 0; 192 layout.marginLeft = 30; 193 offsetComp.setLayout(layout); 194 195 mPreferredAvdLabel = new Label(offsetComp, SWT.NONE); 196 mPreferredAvdLabel.setText("Select a preferred Android Virtual Device for deployment:"); 197 198 // create the selector with no manager, we'll reset the manager every time this is 199 // displayed to ensure we have the latest one (dialog is reused but SDK could have 200 // been changed in between. 201 mPreferredAvdSelector = new AvdSelector(offsetComp, 202 Sdk.getCurrent().getSdkLocation(), 203 null /* avd manager */, 204 DisplayMode.SIMPLE_CHECK, 205 new AdtConsoleSdkLog()); 206 mPreferredAvdSelector.setTableHeightHint(100); 207 mPreferredAvdSelector.setSelectionListener(new SelectionAdapter() { 208 @Override 209 public void widgetSelected(SelectionEvent e) { 210 updateLaunchConfigurationDialog(); 211 } 212 }); 213 214 // emulator size 215 mEmulatorOptionsGroup = new Group(topComp, SWT.NONE); 216 mEmulatorOptionsGroup.setText("Emulator launch parameters:"); 217 mEmulatorOptionsGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); 218 layout = new GridLayout(); 219 layout.numColumns = 2; 220 mEmulatorOptionsGroup.setLayout(layout); 221 mEmulatorOptionsGroup.setFont(font); 222 223 // network options 224 new Label(mEmulatorOptionsGroup, SWT.NONE).setText("Network Speed:"); 225 226 mSpeedCombo = new Combo(mEmulatorOptionsGroup, SWT.READ_ONLY); 227 for (String[] speed : NETWORK_SPEEDS) { 228 mSpeedCombo.add(speed[0]); 229 } 230 mSpeedCombo.addSelectionListener(new SelectionAdapter() { 231 // called when selection changes 232 @Override 233 public void widgetSelected(SelectionEvent e) { 234 updateLaunchConfigurationDialog(); 235 } 236 }); 237 mSpeedCombo.pack(); 238 239 new Label(mEmulatorOptionsGroup, SWT.NONE).setText("Network Latency:"); 240 241 mDelayCombo = new Combo(mEmulatorOptionsGroup, SWT.READ_ONLY); 242 243 for (String[] delay : NETWORK_LATENCIES) { 244 mDelayCombo.add(delay[0]); 245 } 246 mDelayCombo.addSelectionListener(new SelectionAdapter() { 247 // called when selection changes 248 @Override 249 public void widgetSelected(SelectionEvent e) { 250 updateLaunchConfigurationDialog(); 251 } 252 }); 253 mDelayCombo.pack(); 254 255 // wipe data option 256 mWipeDataButton = new Button(mEmulatorOptionsGroup, SWT.CHECK); 257 mWipeDataButton.setText("Wipe User Data"); 258 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."); 259 gd = new GridData(GridData.FILL_HORIZONTAL); 260 gd.horizontalSpan = 2; 261 mWipeDataButton.setLayoutData(gd); 262 mWipeDataButton.addSelectionListener(new SelectionAdapter() { 263 @Override 264 public void widgetSelected(SelectionEvent e) { 265 updateLaunchConfigurationDialog(); 266 } 267 }); 268 269 // no boot anim option 270 mNoBootAnimButton = new Button(mEmulatorOptionsGroup, SWT.CHECK); 271 mNoBootAnimButton.setText("Disable Boot Animation"); 272 mNoBootAnimButton.setToolTipText("Check this if you want to disable the boot animation. This can help the emulator start faster on slow machines."); 273 gd = new GridData(GridData.FILL_HORIZONTAL); 274 gd.horizontalSpan = 2; 275 mNoBootAnimButton.setLayoutData(gd); 276 mNoBootAnimButton.addSelectionListener(new SelectionAdapter() { 277 @Override 278 public void widgetSelected(SelectionEvent e) { 279 updateLaunchConfigurationDialog(); 280 } 281 }); 282 283 // custom command line option for emulator 284 Label l = new Label(mEmulatorOptionsGroup, SWT.NONE); 285 l.setText("Additional Emulator Command Line Options"); 286 gd = new GridData(GridData.FILL_HORIZONTAL); 287 gd.horizontalSpan = 2; 288 l.setLayoutData(gd); 289 290 mEmulatorCLOptions = new Text(mEmulatorOptionsGroup, SWT.BORDER); 291 gd = new GridData(GridData.FILL_HORIZONTAL); 292 gd.horizontalSpan = 2; 293 mEmulatorCLOptions.setLayoutData(gd); 294 mEmulatorCLOptions.addModifyListener(new ModifyListener() { 295 @Override 296 public void modifyText(ModifyEvent e) { 297 updateLaunchConfigurationDialog(); 298 } 299 }); 300 } 301 302 /* (non-Javadoc) 303 * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getName() 304 */ 305 @Override 306 public String getName() { 307 return "Target"; 308 } 309 310 @Override 311 public Image getImage() { 312 return ImageLoader.getDdmUiLibLoader().loadImage("emulator.png", null); //$NON-NLS-1$ 313 } 314 315 private void updateAvdList(AvdManager avdManager) { 316 if (avdManager == null) { 317 avdManager = Sdk.getCurrent().getAvdManager(); 318 } 319 320 mPreferredAvdSelector.setManager(avdManager); 321 mPreferredAvdSelector.setFilter(mProjectTarget); 322 mPreferredAvdSelector.refresh(false); 323 } 324 325 /* (non-Javadoc) 326 * @see org.eclipse.debug.ui.ILaunchConfigurationTab#initializeFrom(org.eclipse.debug.core.ILaunchConfiguration) 327 */ 328 @Override 329 public void initializeFrom(ILaunchConfiguration configuration) { 330 AvdManager avdManager = Sdk.getCurrent().getAvdManager(); 331 332 TargetMode mode = LaunchConfigDelegate.DEFAULT_TARGET_MODE; // true == automatic 333 try { 334 mode = TargetMode.getMode(configuration.getAttribute( 335 LaunchConfigDelegate.ATTR_TARGET_MODE, mode.getValue())); 336 } catch (CoreException e) { 337 // let's not do anything here, we'll use the default value 338 } 339 mAutoTargetButton.setSelection(mode.getValue()); 340 mManualTargetButton.setSelection(!mode.getValue()); 341 342 // look for the project name to get its target. 343 String stringValue = ""; 344 try { 345 stringValue = configuration.getAttribute( 346 IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, stringValue); 347 } catch (CoreException ce) { 348 // let's not do anything here, we'll use the default value 349 } 350 351 IProject project = null; 352 353 // get the list of existing Android projects from the workspace. 354 IJavaProject[] projects = BaseProjectHelper.getAndroidProjects(null /*filter*/); 355 if (projects != null) { 356 // look for the project whose name we read from the configuration. 357 for (IJavaProject p : projects) { 358 if (p.getElementName().equals(stringValue)) { 359 project = p.getProject(); 360 break; 361 } 362 } 363 } 364 365 // update the AVD list 366 if (project != null) { 367 mProjectTarget = Sdk.getCurrent().getTarget(project); 368 } 369 370 updateAvdList(avdManager); 371 372 stringValue = ""; 373 try { 374 stringValue = configuration.getAttribute(LaunchConfigDelegate.ATTR_AVD_NAME, 375 stringValue); 376 } catch (CoreException e) { 377 // let's not do anything here, we'll use the default value 378 } 379 380 if (stringValue != null && stringValue.length() > 0 && avdManager != null) { 381 AvdInfo targetAvd = avdManager.getAvd(stringValue, true /*validAvdOnly*/); 382 mPreferredAvdSelector.setSelection(targetAvd); 383 } else { 384 mPreferredAvdSelector.setSelection(null); 385 } 386 387 boolean value = LaunchConfigDelegate.DEFAULT_WIPE_DATA; 388 try { 389 value = configuration.getAttribute(LaunchConfigDelegate.ATTR_WIPE_DATA, value); 390 } catch (CoreException e) { 391 // let's not do anything here, we'll use the default value 392 } 393 mWipeDataButton.setSelection(value); 394 395 value = LaunchConfigDelegate.DEFAULT_NO_BOOT_ANIM; 396 try { 397 value = configuration.getAttribute(LaunchConfigDelegate.ATTR_NO_BOOT_ANIM, value); 398 } catch (CoreException e) { 399 // let's not do anything here, we'll use the default value 400 } 401 mNoBootAnimButton.setSelection(value); 402 403 int index = -1; 404 405 index = LaunchConfigDelegate.DEFAULT_SPEED; 406 try { 407 index = configuration.getAttribute(LaunchConfigDelegate.ATTR_SPEED, 408 index); 409 } catch (CoreException e) { 410 // let's not do anything here, we'll use the default value 411 } 412 if (index == -1) { 413 mSpeedCombo.clearSelection(); 414 } else { 415 mSpeedCombo.select(index); 416 } 417 418 index = LaunchConfigDelegate.DEFAULT_DELAY; 419 try { 420 index = configuration.getAttribute(LaunchConfigDelegate.ATTR_DELAY, 421 index); 422 } catch (CoreException e) { 423 // let's not do anything here, we'll put a proper value in 424 // performApply anyway 425 } 426 if (index == -1) { 427 mDelayCombo.clearSelection(); 428 } else { 429 mDelayCombo.select(index); 430 } 431 432 String commandLine = null; 433 try { 434 commandLine = configuration.getAttribute( 435 LaunchConfigDelegate.ATTR_COMMANDLINE, ""); //$NON-NLS-1$ 436 } catch (CoreException e) { 437 // let's not do anything here, we'll use the default value 438 } 439 if (commandLine != null) { 440 mEmulatorCLOptions.setText(commandLine); 441 } 442 } 443 444 /* (non-Javadoc) 445 * @see org.eclipse.debug.ui.ILaunchConfigurationTab#performApply(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy) 446 */ 447 @Override 448 public void performApply(ILaunchConfigurationWorkingCopy configuration) { 449 configuration.setAttribute(LaunchConfigDelegate.ATTR_TARGET_MODE, 450 mAutoTargetButton.getSelection()); 451 AvdInfo avd = mPreferredAvdSelector.getSelected(); 452 if (avd != null) { 453 configuration.setAttribute(LaunchConfigDelegate.ATTR_AVD_NAME, avd.getName()); 454 } else { 455 configuration.setAttribute(LaunchConfigDelegate.ATTR_AVD_NAME, (String)null); 456 } 457 configuration.setAttribute(LaunchConfigDelegate.ATTR_SPEED, 458 mSpeedCombo.getSelectionIndex()); 459 configuration.setAttribute(LaunchConfigDelegate.ATTR_DELAY, 460 mDelayCombo.getSelectionIndex()); 461 configuration.setAttribute(LaunchConfigDelegate.ATTR_COMMANDLINE, 462 mEmulatorCLOptions.getText()); 463 configuration.setAttribute(LaunchConfigDelegate.ATTR_WIPE_DATA, 464 mWipeDataButton.getSelection()); 465 configuration.setAttribute(LaunchConfigDelegate.ATTR_NO_BOOT_ANIM, 466 mNoBootAnimButton.getSelection()); 467 } 468 469 /* (non-Javadoc) 470 * @see org.eclipse.debug.ui.ILaunchConfigurationTab#setDefaults(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy) 471 */ 472 @Override 473 public void setDefaults(ILaunchConfigurationWorkingCopy configuration) { 474 configuration.setAttribute(LaunchConfigDelegate.ATTR_TARGET_MODE, 475 LaunchConfigDelegate.DEFAULT_TARGET_MODE.getValue()); 476 configuration.setAttribute(LaunchConfigDelegate.ATTR_SPEED, 477 LaunchConfigDelegate.DEFAULT_SPEED); 478 configuration.setAttribute(LaunchConfigDelegate.ATTR_DELAY, 479 LaunchConfigDelegate.DEFAULT_DELAY); 480 configuration.setAttribute(LaunchConfigDelegate.ATTR_WIPE_DATA, 481 LaunchConfigDelegate.DEFAULT_WIPE_DATA); 482 configuration.setAttribute(LaunchConfigDelegate.ATTR_NO_BOOT_ANIM, 483 LaunchConfigDelegate.DEFAULT_NO_BOOT_ANIM); 484 485 IPreferenceStore store = AdtPlugin.getDefault().getPreferenceStore(); 486 String emuOptions = store.getString(AdtPrefs.PREFS_EMU_OPTIONS); 487 configuration.setAttribute(LaunchConfigDelegate.ATTR_COMMANDLINE, emuOptions); 488 } 489 } 490