/*
 * 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;
    }
}

