Home | History | Annotate | Download | only in launch
      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