Added GLE support for devices

Change-Id: I4e82e93563529540d31af8809aba79f40610fa2e
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigEditDialog.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigEditDialog.java
deleted file mode 100644
index bd45400..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigEditDialog.java
+++ /dev/null
@@ -1,356 +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.editors.layout.configuration;
-
-import com.android.ide.common.resources.configuration.FolderConfiguration;
-import com.android.ide.common.resources.configuration.LanguageQualifier;
-import com.android.ide.common.resources.configuration.NightModeQualifier;
-import com.android.ide.common.resources.configuration.RegionQualifier;
-import com.android.ide.common.resources.configuration.ResourceQualifier;
-import com.android.ide.common.resources.configuration.UiModeQualifier;
-import com.android.ide.common.resources.configuration.VersionQualifier;
-import com.android.ide.eclipse.adt.internal.editors.IconFactory;
-import com.android.ide.eclipse.adt.internal.sdk.LayoutDevice;
-import com.android.ide.eclipse.adt.internal.ui.ConfigurationSelector;
-import com.android.ide.eclipse.adt.internal.ui.ConfigurationSelector.ConfigurationState;
-import com.android.ide.eclipse.adt.internal.ui.ConfigurationSelector.IQualifierFilter;
-import com.android.ide.eclipse.adt.internal.ui.ConfigurationSelector.SelectorMode;
-import com.android.sdkuilib.ui.GridDialog;
-
-import org.eclipse.jface.dialogs.Dialog;
-import org.eclipse.jface.dialogs.IDialogConstants;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.ModifyEvent;
-import org.eclipse.swt.events.ModifyListener;
-import org.eclipse.swt.events.VerifyEvent;
-import org.eclipse.swt.events.VerifyListener;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Group;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.Text;
-
-import java.text.DecimalFormat;
-import java.text.DecimalFormatSymbols;
-import java.text.ParseException;
-import java.util.regex.Pattern;
-
-/**
- * Dialog to edit both a {@link LayoutDevice}, and a {@link FolderConfiguration} at the same time.
- */
-public class ConfigEditDialog extends GridDialog {
-
-    private static final Pattern FLOAT_PATTERN;
-    static {
-        // get the decimal separator char
-        DecimalFormatSymbols dfs = new DecimalFormatSymbols();
-
-        // make a pattern that's basically ##.# where .# is optional and where . can be . or ,
-        // depending on the locale
-        FLOAT_PATTERN = Pattern.compile(
-            "\\d*(" +                                                       //$NON-NLS-1$
-            Pattern.quote(new String(new char[] { dfs.getDecimalSeparator() })) +
-            "\\d?)?");                                                      //$NON-NLS-1$
-    }
-
-    private final FolderConfiguration mConfig = new FolderConfiguration();
-
-    private ConfigurationSelector mConfigSelector;
-    private Composite mStatusComposite;
-    private Label mStatusLabel;
-    private Label mStatusImage;
-
-    private Image mError;
-
-    private String mDeviceName;
-    private String mConfigName;
-    private float mXDpi = Float.NaN;
-    private float mYDpi = Float.NaN;
-
-    private final DecimalFormat mDecimalFormat = new DecimalFormat();
-
-
-    public ConfigEditDialog(Shell parentShell, FolderConfiguration config) {
-        super(parentShell, 1, false);
-        mConfig.set(config);
-    }
-
-    public void setDeviceName(String name) {
-        mDeviceName = name;
-    }
-
-    public String getDeviceName() {
-        return mDeviceName;
-    }
-
-    public void setXDpi(float xdpi) {
-        mXDpi = xdpi;
-    }
-
-    public float getXDpi() {
-        return mXDpi;
-    }
-
-    public void setYDpi(float ydpi) {
-        mYDpi = ydpi;
-    }
-
-    public float getYDpi() {
-        return mYDpi;
-    }
-
-    public void setConfigName(String name) {
-        mConfigName = name;
-    }
-
-    public String getConfigName() {
-        return mConfigName;
-    }
-
-    public void setConfig(FolderConfiguration config) {
-        mConfig.set(config);
-    }
-
-    public void getConfig(FolderConfiguration config) {
-        config.set(mConfig);
-        config.updateScreenWidthAndHeight();
-    }
-
-    @Override
-    public void createDialogContent(Composite parent) {
-        mError = IconFactory.getInstance().getIcon("error"); //$NON-NLS-1$
-
-        Group deviceGroup = new Group(parent, SWT.NONE);
-        deviceGroup.setText("Device");
-        deviceGroup.setLayoutData(new GridData(GridData.FILL_BOTH));
-        deviceGroup.setLayout(new GridLayout(2, false));
-
-        Label l = new Label(deviceGroup, SWT.None);
-        l.setText("Name");
-
-        final Text deviceNameText = new Text(deviceGroup, SWT.BORDER);
-        deviceNameText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
-        if (mDeviceName != null) {
-            deviceNameText.setText(mDeviceName);
-        }
-        deviceNameText.addModifyListener(new ModifyListener() {
-            @Override
-            public void modifyText(ModifyEvent e) {
-                mDeviceName = deviceNameText.getText().trim();
-                validateOk();
-            }
-        });
-
-
-        VerifyListener floatVerifier = new VerifyListener() {
-            @Override
-            public void verifyText(VerifyEvent event) {
-                // combine the current content and the new text
-                String text = ((Text)event.widget).getText();
-                text = text.substring(0, event.start) + event.text + text.substring(event.end);
-
-                // now make sure it's a match for the regex
-                event.doit = FLOAT_PATTERN.matcher(text).matches();
-            }
-        };
-
-        l = new Label(deviceGroup, SWT.None);
-        l.setText("x dpi");
-
-        final Text deviceXDpiText = new Text(deviceGroup, SWT.BORDER);
-        deviceXDpiText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
-        if (Float.isNaN(mXDpi) == false) {
-            deviceXDpiText.setText(String.format("%.1f", mXDpi)); //$NON-NLS-1$
-        }
-        deviceXDpiText.addVerifyListener(floatVerifier);
-        deviceXDpiText.addModifyListener(new ModifyListener() {
-            @Override
-            public void modifyText(ModifyEvent e) {
-                String value = deviceXDpiText.getText();
-                if (value.length() == 0) {
-                    mXDpi = Float.NaN;
-                } else {
-                    try {
-                        mXDpi = mDecimalFormat.parse(value).floatValue();
-                    } catch (ParseException exception) {
-                        mXDpi = Float.NaN;
-                    }
-                }
-            }
-        });
-
-        l = new Label(deviceGroup, SWT.None);
-        l.setText("y dpi");
-
-        final Text deviceYDpiText = new Text(deviceGroup, SWT.BORDER);
-        deviceYDpiText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
-        if (Float.isNaN(mYDpi) == false) {
-            deviceYDpiText.setText(String.format("%.1f", mYDpi)); //$NON-NLS-1$
-        }
-        deviceYDpiText.addVerifyListener(floatVerifier);
-        deviceYDpiText.addModifyListener(new ModifyListener() {
-            @Override
-            public void modifyText(ModifyEvent e) {
-                String value = deviceYDpiText.getText();
-                if (value.length() == 0) {
-                    mYDpi = Float.NaN;
-                } else {
-                    try {
-                        mYDpi = mDecimalFormat.parse(value).floatValue();
-                    } catch (ParseException exception) {
-                        mYDpi = Float.NaN;
-                    }
-                }
-            }
-        });
-
-        Group configGroup = new Group(parent, SWT.NONE);
-        configGroup.setText("Configuration");
-        configGroup.setLayoutData(new GridData(GridData.FILL_BOTH));
-        configGroup.setLayout(new GridLayout(2, false));
-
-        l = new Label(configGroup, SWT.None);
-        l.setText("Name");
-
-        final Text configNameText = new Text(configGroup, SWT.BORDER);
-        configNameText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
-        if (mConfigName != null) {
-            configNameText.setText(mConfigName);
-        }
-        configNameText.addModifyListener(new ModifyListener() {
-            @Override
-            public void modifyText(ModifyEvent e) {
-                mConfigName = configNameText.getText().trim();
-                validateOk();
-            }
-        });
-
-        mConfigSelector = new ConfigurationSelector(configGroup, SelectorMode.DEVICE_ONLY);
-        // configure the selector to be in "device mode" and not accept language/region/version
-        // since those are selected from a different combo
-        // FIXME: add version combo.
-        mConfigSelector.setQualifierFilter(new IQualifierFilter() {
-            @Override
-            public boolean accept(ResourceQualifier qualifier) {
-                if (qualifier instanceof LanguageQualifier ||
-                        qualifier instanceof RegionQualifier ||
-                        qualifier instanceof UiModeQualifier ||
-                        qualifier instanceof NightModeQualifier ||
-                        qualifier instanceof VersionQualifier) {
-                    return false;
-                }
-
-                return true;
-            }
-        });
-        mConfigSelector.setConfiguration(mConfig);
-        GridData gd;
-        mConfigSelector.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
-        gd.horizontalSpan = 2;
-        gd.widthHint = ConfigurationSelector.WIDTH_HINT;
-        gd.heightHint = ConfigurationSelector.HEIGHT_HINT;
-
-        // add a listener to check on the validity of the FolderConfiguration as
-        // they are built.
-        mConfigSelector.setOnChangeListener(new Runnable() {
-            @Override
-            public void run() {
-                if (mConfigSelector.getState() == ConfigurationState.OK) {
-                    mConfigSelector.getConfiguration(mConfig);
-                }
-
-                validateOk();
-            }
-        });
-
-        mStatusComposite = new Composite(parent, SWT.NONE);
-        mStatusComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
-        GridLayout gl = new GridLayout(2, false);
-        mStatusComposite.setLayout(gl);
-        gl.marginHeight = gl.marginWidth = 0;
-
-        mStatusImage = new Label(mStatusComposite, SWT.NONE);
-        mStatusLabel = new Label(mStatusComposite, SWT.NONE);
-        mStatusLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
-        resetStatus();
-    }
-
-    @Override
-    protected Control createContents(Composite parent) {
-        Control c = super.createContents(parent);
-        validateOk();
-        return c;
-    }
-
-    /**
-     * resets the status label to show the file that will be created.
-     */
-    private void resetStatus() {
-        String displayString = Dialog.shortenText(
-                String.format("Config: %1$s", mConfig.toString()),
-                mStatusLabel);
-        mStatusLabel.setText(displayString);
-    }
-
-    private void setError(String text) {
-        String displayString = Dialog.shortenText(text, mStatusLabel);
-        mStatusLabel.setText(displayString);
-        mStatusImage.setImage(mError);
-        getButton(IDialogConstants.OK_ID).setEnabled(false);
-    }
-
-    private void validateOk() {
-        // check the device name
-        if (mDeviceName == null || mDeviceName.length() == 0) {
-            setError("Device name must not be empty");
-            return;
-        }
-
-        // check the config name
-        if (mConfigName == null || mConfigName.length() == 0) {
-            setError("Configuration name must not be empty");
-            return;
-        }
-
-        // and check the config itself
-        ConfigurationState state = mConfigSelector.getState();
-
-        switch (state) {
-            case INVALID_CONFIG:
-                ResourceQualifier invalidQualifier = mConfigSelector.getInvalidQualifier();
-                setError(String.format(
-                        "Invalid Configuration: %1$s has no filter set.",
-                        invalidQualifier.getName()));
-                return;
-            case REGION_WITHOUT_LANGUAGE:
-                setError("The Region qualifier requires the Language qualifier.");
-                return;
-        }
-
-        // no error
-        mStatusImage.setImage(null);
-        resetStatus();
-        getButton(IDialogConstants.OK_ID).setEnabled(true);
-
-        // need to relayout, because of the change in size in mErrorImage.
-        mStatusComposite.layout();
-    }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigManagerDialog.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigManagerDialog.java
deleted file mode 100644
index 2adefa7..0000000
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigManagerDialog.java
+++ /dev/null
@@ -1,566 +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.editors.layout.configuration;
-
-import com.android.ddmuilib.TableHelper;
-import com.android.ide.common.resources.configuration.FolderConfiguration;
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.internal.sdk.LayoutDevice;
-import com.android.ide.eclipse.adt.internal.sdk.LayoutDevice.DeviceConfig;
-import com.android.ide.eclipse.adt.internal.sdk.LayoutDeviceManager;
-import com.android.ide.eclipse.adt.internal.sdk.Sdk;
-import com.android.sdkuilib.ui.GridDialog;
-
-import org.eclipse.jface.dialogs.IDialogConstants;
-import org.eclipse.jface.viewers.ILabelProviderListener;
-import org.eclipse.jface.viewers.ISelectionChangedListener;
-import org.eclipse.jface.viewers.ITableLabelProvider;
-import org.eclipse.jface.viewers.ITreeContentProvider;
-import org.eclipse.jface.viewers.SelectionChangedEvent;
-import org.eclipse.jface.viewers.TreePath;
-import org.eclipse.jface.viewers.TreeSelection;
-import org.eclipse.jface.viewers.TreeViewer;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.jface.window.Window;
-import org.eclipse.swt.SWT;
-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.Label;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.Tree;
-
-import java.util.List;
-
-/**
- * Dialog to view the layout devices with action button to create/edit/delete/copy layout devices
- * and configs.
- *
- */
-public class ConfigManagerDialog extends GridDialog {
-
-    private final static String COL_NAME = AdtPlugin.PLUGIN_ID + ".configmanager.name"; //$NON-NLS-1$
-    private final static String COL_CONFIG = AdtPlugin.PLUGIN_ID + ".configmanager.config"; //$NON-NLS-1$
-
-    /**
-     * enum to represent the different origin of the layout devices.
-     */
-    private static enum DeviceType {
-        DEFAULT("Default"),
-        ADDON("Add-on"),
-        CUSTOM("Custom");
-
-        private final String mDisplay;
-
-        DeviceType(String display) {
-            mDisplay = display;
-        }
-
-        String getDisplayString() {
-            return mDisplay;
-        }
-    }
-
-    /**
-     * simple class representing the tree selection with the proper types.
-     */
-    private static class DeviceSelection {
-        public DeviceSelection(DeviceType type, LayoutDevice device,
-                DeviceConfig config) {
-            this.type = type;
-            this.device = device;
-            this.config = config;
-        }
-
-        final DeviceType type;
-        final LayoutDevice device;
-        final DeviceConfig config;
-    }
-
-    private final LayoutDeviceManager mManager;
-
-    private TreeViewer mTreeViewer;
-    private Button mNewButton;
-    private Button mEditButton;
-    private Button mCopyButton;
-    private Button mDeleteButton;
-
-    /**
-     * Content provider of the {@link TreeViewer}. The expected input is
-     * {@link LayoutDeviceManager}.
-     *
-     */
-    private final static class DeviceContentProvider implements ITreeContentProvider {
-        private final static DeviceType[] sCategory = new DeviceType[] {
-            DeviceType.DEFAULT, DeviceType.ADDON, DeviceType.CUSTOM
-        };
-
-        private LayoutDeviceManager mLayoutDeviceManager;
-
-        public DeviceContentProvider() {
-        }
-
-        @Override
-        public Object[] getElements(Object inputElement) {
-            return sCategory;
-        }
-
-        @Override
-        public Object[] getChildren(Object parentElement) {
-            if (parentElement instanceof DeviceType) {
-                if (DeviceType.DEFAULT.equals(parentElement)) {
-                    return mLayoutDeviceManager.getDefaultLayoutDevices().toArray();
-                } else if (DeviceType.ADDON.equals(parentElement)) {
-                    return mLayoutDeviceManager.getAddOnLayoutDevice().toArray();
-                } else if (DeviceType.CUSTOM.equals(parentElement)) {
-                    return mLayoutDeviceManager.getUserLayoutDevices().toArray();
-                }
-            } else if (parentElement instanceof LayoutDevice) {
-                LayoutDevice device = (LayoutDevice)parentElement;
-                return device.getConfigs().toArray();
-            }
-
-            return null;
-        }
-
-        @Override
-        public Object getParent(Object element) {
-            // parent cannot be computed. this is fine.
-            return null;
-        }
-
-        @Override
-        public boolean hasChildren(Object element) {
-            if (element instanceof DeviceType) {
-                if (DeviceType.DEFAULT.equals(element)) {
-                    return mLayoutDeviceManager.getDefaultLayoutDevices().size() > 0;
-                } else if (DeviceType.ADDON.equals(element)) {
-                    return mLayoutDeviceManager.getAddOnLayoutDevice().size() > 0;
-                } else if (DeviceType.CUSTOM.equals(element)) {
-                    return mLayoutDeviceManager.getUserLayoutDevices().size() > 0;
-                }
-            } else if (element instanceof LayoutDevice) {
-                LayoutDevice device = (LayoutDevice)element;
-                return device.getConfigs().size() > 0;
-            }
-
-            return false;
-        }
-
-
-        @Override
-        public void dispose() {
-            // nothing to dispose
-        }
-
-        @Override
-        public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
-            if (newInput instanceof LayoutDeviceManager) {
-                mLayoutDeviceManager = (LayoutDeviceManager)newInput;
-                return;
-            }
-
-            // when the dialog closes we get null input
-            if (newInput != null) {
-                throw new IllegalArgumentException(
-                        "ConfigContentProvider requires input to be LayoutDeviceManager");
-            }
-        }
-    }
-
-    /**
-     * Label provider for the {@link TreeViewer}.
-     * Supported elements are {@link DeviceType}, {@link LayoutDevice}, and {@link DeviceConfig}.
-     *
-     */
-    private final static class DeviceLabelProvider implements ITableLabelProvider {
-
-        @Override
-        public String getColumnText(Object element, int columnIndex) {
-            if (element instanceof DeviceType) {
-                if (columnIndex == 0) {
-                    return ((DeviceType)element).getDisplayString();
-                }
-            } else if (element instanceof LayoutDevice) {
-                if (columnIndex == 0) {
-                    return ((LayoutDevice)element).getName();
-                }
-            } else if (element instanceof DeviceConfig) {
-                if (columnIndex == 0) {
-                    return ((DeviceConfig)element).getName();
-                } else {
-                    return ((DeviceConfig)element).getConfig().toString();
-                }
-            }
-            return null;
-        }
-
-        @Override
-        public Image getColumnImage(Object element, int columnIndex) {
-            // no image
-            return null;
-        }
-
-        @Override
-        public void addListener(ILabelProviderListener listener) {
-            // no listener
-        }
-
-        @Override
-        public void removeListener(ILabelProviderListener listener) {
-            // no listener
-        }
-
-        @Override
-        public void dispose() {
-            // nothing to dispose
-        }
-
-        @Override
-        public boolean isLabelProperty(Object element, String property) {
-            return false;
-        }
-    }
-
-    protected ConfigManagerDialog(Shell parentShell) {
-        super(parentShell, 2, false);
-        mManager = Sdk.getCurrent().getLayoutDeviceManager();
-    }
-
-    @Override
-    protected int getShellStyle() {
-        return super.getShellStyle() | SWT.RESIZE;
-    }
-
-    @Override
-    protected void configureShell(Shell newShell) {
-        super.configureShell(newShell);
-        newShell.setText("Device Configurations");
-    }
-
-    @Override
-    public void createDialogContent(final Composite parent) {
-        GridData gd;
-        GridLayout gl;
-
-        Tree tree = new Tree(parent, SWT.SINGLE | SWT.FULL_SELECTION);
-        tree.setLayoutData(gd = new GridData(GridData.FILL_BOTH));
-        gd.widthHint = 700;
-
-        tree.setHeaderVisible(true);
-        tree.setLinesVisible(true);
-        TableHelper.createTreeColumn(tree, "Name", SWT.LEFT, 150, COL_NAME,
-                AdtPlugin.getDefault().getPreferenceStore());
-        TableHelper.createTreeColumn(tree, "Configuration", SWT.LEFT, 500, COL_CONFIG,
-                AdtPlugin.getDefault().getPreferenceStore());
-
-        mTreeViewer = new TreeViewer(tree);
-        mTreeViewer.setContentProvider(new DeviceContentProvider());
-        mTreeViewer.setLabelProvider(new DeviceLabelProvider());
-        mTreeViewer.setAutoExpandLevel(TreeViewer.ALL_LEVELS);
-        mTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
-            @Override
-            public void selectionChanged(SelectionChangedEvent event) {
-                setEnabled(getSelection());
-            }
-        });
-
-        Composite buttons = new Composite(parent, SWT.NONE);
-        buttons.setLayoutData(new GridData(GridData.FILL_VERTICAL));
-        buttons.setLayout(gl = new GridLayout());
-        gl.marginHeight = gl.marginWidth = 0;
-
-        mNewButton = new Button(buttons, SWT.PUSH | SWT.FLAT);
-        mNewButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
-        mNewButton.setText("New...");
-        mNewButton.addSelectionListener(new SelectionAdapter() {
-            @Override
-            public void widgetSelected(SelectionEvent e) {
-                DeviceSelection selection = getSelection();
-
-                ConfigEditDialog dlg = new ConfigEditDialog(parent.getShell(), null);
-                if (selection.device != null) {
-                    dlg.setDeviceName(selection.device.getName());
-                    dlg.setXDpi(selection.device.getXDpi());
-                    dlg.setYDpi(selection.device.getYDpi());
-                }
-                if (selection.config != null) {
-                    dlg.setConfigName(selection.config.getName());
-                    dlg.setConfig(selection.config.getConfig());
-                }
-
-                if (dlg.open() == Window.OK) {
-                    String deviceName = dlg.getDeviceName();
-                    String configName = dlg.getConfigName();
-                    FolderConfiguration config = new FolderConfiguration();
-                    dlg.getConfig(config);
-
-                    // first if there was no original device, we create one.
-                    // Because the new button is disabled when something else than "custom" is
-                    // selected, we always add to the user devices without checking.
-                    LayoutDevice d;
-                    if (selection.device == null) {
-                        // FIXME: this doesn't check if the device name is taken.
-                        d = mManager.addUserDevice(deviceName, dlg.getXDpi(), dlg.getYDpi());
-                    } else {
-                        // search for it.
-                        d = mManager.getUserLayoutDevice(deviceName);
-                    }
-
-                    if (d != null) {
-                        // then if there was no config, we add it, otherwise we edit it
-                        // (same method that adds/replace a config).
-                        // FIXME this doesn't check if the name was already taken.
-                        mManager.addUserConfiguration(d, configName, config);
-
-                        mTreeViewer.refresh();
-                        select(d, configName);
-                    }
-                }
-            }
-        });
-
-        mEditButton = new Button(buttons, SWT.PUSH | SWT.FLAT);
-        mEditButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
-        mEditButton.setText("Edit...");
-        mEditButton.addSelectionListener(new SelectionAdapter() {
-            @Override
-            public void widgetSelected(SelectionEvent e) {
-                DeviceSelection selection = getSelection();
-                ConfigEditDialog dlg = new ConfigEditDialog(parent.getShell(), null);
-                dlg.setDeviceName(selection.device.getName());
-                dlg.setXDpi(selection.device.getXDpi());
-                dlg.setYDpi(selection.device.getYDpi());
-                dlg.setConfigName(selection.config.getName());
-                dlg.setConfig(selection.config.getConfig());
-
-                if (dlg.open() == Window.OK) {
-                    String deviceName = dlg.getDeviceName();
-                    String configName = dlg.getConfigName();
-                    FolderConfiguration config = new FolderConfiguration();
-                    dlg.getConfig(config);
-
-                    // replace the device if needed.
-                    // FIXME: this doesn't check if the replacement name doesn't exist already.
-                    LayoutDevice d = mManager.replaceUserDevice(selection.device, deviceName,
-                            dlg.getXDpi(), dlg.getYDpi());
-
-                    // and add/replace the config
-                    mManager.replaceUserConfiguration(d, selection.config.getName(), configName,
-                            config);
-
-                    mTreeViewer.refresh();
-                    select(d, configName);
-                }
-            }
-        });
-
-        mCopyButton = new Button(buttons, SWT.PUSH | SWT.FLAT);
-        mCopyButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
-        mCopyButton.setText("Copy");
-        mCopyButton.addSelectionListener(new SelectionAdapter() {
-            @Override
-            public void widgetSelected(SelectionEvent e) {
-                DeviceSelection selection = getSelection();
-
-                // is the source a default/add-on device, or are we copying a full device?
-                // if so the target device is a new device.
-                LayoutDevice targetDevice = selection.device;
-                if (selection.type == DeviceType.DEFAULT || selection.type == DeviceType.ADDON ||
-                        selection.config == null) {
-                    // create a new device
-                    targetDevice = mManager.addUserDevice(
-                            selection.device.getName() + " Copy", // new name
-                            selection.device.getXDpi(),
-                            selection.device.getYDpi());
-                }
-
-                String newConfigName = null; // name of the single new config. used for the select.
-
-                // are we copying the full device?
-                if (selection.config == null) {
-                    // get the config from the origin device
-                    List<DeviceConfig> configs = selection.device.getConfigs();
-
-                    // and copy them in the target device
-                    for (DeviceConfig config : configs) {
-                        // we need to make a copy of the config object, or it could be modified
-                        // in default/addon by editing the version in the new device.
-                        FolderConfiguration copy = new FolderConfiguration();
-                        copy.set(config.getConfig());
-
-                        // the name can stay the same since we are copying a full device
-                        // and the target device has its own new name.
-                        mManager.addUserConfiguration(targetDevice, config.getName(), copy);
-                    }
-                } else {
-                    // only copy the config. target device is not the same as the selection, don't
-                    // change the config name as we already changed the name of the device.
-                    newConfigName = (selection.device != targetDevice) ?
-                            selection.config.getName() : selection.config.getName() + " Copy";
-
-                    // copy of the config
-                    FolderConfiguration copy = new FolderConfiguration();
-                    copy.set(selection.config.getConfig());
-
-                    // and create the config
-                    mManager.addUserConfiguration(targetDevice, newConfigName, copy);
-                }
-
-                mTreeViewer.refresh();
-
-                select(targetDevice, newConfigName);
-            }
-        });
-
-        mDeleteButton = new Button(buttons, SWT.PUSH | SWT.FLAT);
-        mDeleteButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
-        mDeleteButton.setText("Delete");
-        mDeleteButton.addSelectionListener(new SelectionAdapter() {
-            @Override
-            public void widgetSelected(SelectionEvent e) {
-                DeviceSelection selection = getSelection();
-
-                if (selection.config != null) {
-                    mManager.removeUserConfiguration(selection.device, selection.config.getName());
-                } else if (selection.device != null) {
-                    mManager.removeUserDevice(selection.device);
-                }
-
-                mTreeViewer.refresh();
-
-                // either select the device (if we removed a entry, or the top custom node if
-                // we removed a device)
-                select(selection.config != null ? selection.device : null, null);
-            }
-        });
-
-        Label separator = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL);
-        separator.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
-        gd.horizontalSpan = 2;
-
-        mTreeViewer.setInput(mManager);
-        setEnabled(null); // no selection at the start
-    }
-
-    @Override
-    protected void createButtonsForButtonBar(Composite parent) {
-        // we only want an OK button.
-        createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
-    }
-
-    /**
-     * Returns a {@link DeviceSelection} object representing the selected path in the
-     * {@link TreeViewer}
-     */
-    private DeviceSelection getSelection() {
-        // get the selection paths
-        TreeSelection selection = (TreeSelection)mTreeViewer.getSelection();
-        TreePath[] paths =selection.getPaths();
-
-        if (paths.length == 0) {
-            return null;
-        }
-
-        TreePath pathSelection = paths[0];
-
-        DeviceType type = (DeviceType)pathSelection.getFirstSegment();
-        LayoutDevice device = null;
-        DeviceConfig config = null;
-        switch (pathSelection.getSegmentCount()) {
-            case 2: // layout device is selected
-                device = (LayoutDevice)pathSelection.getLastSegment();
-                break;
-            case 3: // config is selected
-                device = (LayoutDevice)pathSelection.getSegment(1);
-                config = (DeviceConfig)pathSelection.getLastSegment();
-        }
-
-        return new DeviceSelection(type, device, config);
-    }
-
-    /**
-     * Enables/disables the action button based on the {@link DeviceSelection}.
-     * @param selection the selection
-     */
-    protected void setEnabled(DeviceSelection selection) {
-        if (selection == null) {
-            mNewButton.setEnabled(false);
-            mEditButton.setEnabled(false);
-            mCopyButton.setEnabled(false);
-            mDeleteButton.setEnabled(false);
-        } else {
-            switch (selection.type) {
-                case DEFAULT:
-                case ADDON:
-                    // only allow copy if device is not null
-                    mNewButton.setEnabled(false);
-                    mEditButton.setEnabled(false);
-                    mDeleteButton.setEnabled(false);
-                    mCopyButton.setEnabled(selection.device != null);
-                    break;
-                case CUSTOM:
-                    mNewButton.setEnabled(true); // always true to create new devices.
-                    mEditButton.setEnabled(selection.config != null); // only edit config for now
-
-                    boolean enabled = selection.device != null; // need at least selected device
-                    mDeleteButton.setEnabled(enabled);          // for delete and copy buttons
-                    mCopyButton.setEnabled(enabled);
-                    break;
-            }
-        }
-    }
-
-    /**
-     * Selects a device and optionally a config. Because this is meant to show newly created/edited
-     * device/config, it'll only do so for {@link DeviceType#CUSTOM} devices.
-     * @param device the device to select
-     * @param configName the config to select (optional)
-     */
-    private void select(LayoutDevice device, String configName) {
-        Object[] path;
-        if (device == null) {
-            // select the "custom" node
-            path = new Object[] { DeviceType.CUSTOM };
-        } else if (configName == null) {
-            // this is the easy case. no config to select
-            path = new Object[] { DeviceType.CUSTOM, device };
-        } else {
-            // this is more complex. we have the configName, but the tree contains DeviceConfig
-            // Look for the entry.
-            DeviceConfig match = null;
-            for (DeviceConfig config : device.getConfigs()) {
-                if (config.getName().equals(configName)) {
-                    match = config;
-                    break;
-                }
-            }
-
-            if (match != null) {
-                path = new Object[] { DeviceType.CUSTOM, device, match };
-            } else {
-                path = new Object[] { DeviceType.CUSTOM, device };
-            }
-        }
-
-        mTreeViewer.setSelection(new TreeSelection(new TreePath(path)), true /*reveal*/);
-    }
-}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java
index 2e1434f..b4e052f 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java
@@ -33,6 +33,7 @@
 import com.android.ide.common.resources.ResourceFolder;
 import com.android.ide.common.resources.ResourceRepository;
 import com.android.ide.common.resources.configuration.DensityQualifier;
+import com.android.ide.common.resources.configuration.DeviceConfigHelper;
 import com.android.ide.common.resources.configuration.FolderConfiguration;
 import com.android.ide.common.resources.configuration.LanguageQualifier;
 import com.android.ide.common.resources.configuration.NightModeQualifier;
@@ -53,9 +54,6 @@
 import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources;
 import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
 import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
-import com.android.ide.eclipse.adt.internal.sdk.LayoutDevice;
-import com.android.ide.eclipse.adt.internal.sdk.LayoutDevice.DeviceConfig;
-import com.android.ide.eclipse.adt.internal.sdk.LayoutDeviceManager;
 import com.android.ide.eclipse.adt.internal.sdk.Sdk;
 import com.android.resources.Density;
 import com.android.resources.NightMode;
@@ -66,6 +64,10 @@
 import com.android.resources.UiMode;
 import com.android.sdklib.AndroidVersion;
 import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.devices.Device;
+import com.android.sdklib.devices.State;
+import com.android.sdklib.internal.avd.AvdInfo;
+import com.android.sdklib.internal.avd.AvdManager;
 import com.android.sdklib.repository.PkgProps;
 import com.android.sdklib.util.SparseIntArray;
 import com.android.util.Pair;
@@ -118,6 +120,7 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.SortedSet;
+import java.util.TreeMap;
 
 /**
  * A composite that displays the current configuration displayed in a Graphical Layout Editor.
@@ -189,7 +192,7 @@
     /** updates are disabled if > 0 */
     private int mDisableUpdates = 0;
 
-    private List<LayoutDevice> mDeviceList;
+    private List<Device> mDeviceList = new ArrayList<Device>();
     private final List<IAndroidTarget> mTargetList = new ArrayList<IAndroidTarget>();
 
     private final List<String> mThemeList = new ArrayList<String>();
@@ -284,8 +287,8 @@
      * rendering to its original configuration.
      */
     private class ConfigState {
-        LayoutDevice device;
-        String configName;
+        Device device;
+        String stateName;
         ResourceQualifier[] locale;
         String theme;
         // TODO: Need to know if it's the project theme or the framework theme!
@@ -302,14 +305,14 @@
             if (device != null) {
                 sb.append(device.getName());
                 sb.append(SEP);
-                if (configName == null) {
-                    DeviceConfig config = getSelectedDeviceConfig();
-                    if (config != null) {
-                        configName = config.getName();
+                if (stateName == null) {
+                    State state= getSelectedDeviceState();
+                    if (state != null) {
+                        stateName = state.getName();
                     }
                 }
-                if (configName != null) {
-                    sb.append(configName);
+                if (stateName != null) {
+                    sb.append(stateName);
                 }
                 sb.append(SEP);
                 if (isLocaleSpecificLayout() && locale != null) {
@@ -357,17 +360,17 @@
         boolean setData(String data) {
             String[] values = data.split(SEP);
             if (values.length >= 6 && values.length <= 8) {
-                for (LayoutDevice d : mDeviceList) {
+                for (Device d : mDeviceList) {
                     if (d.getName().equals(values[0])) {
                         device = d;
                         FolderConfiguration config = null;
                         if (!values[1].isEmpty() && !values[1].equals("null")) { //$NON-NLS-1$
-                            configName = values[1];
-                            config = device.getFolderConfigByName(configName);
-                        } else if (device.getConfigs().size() > 0) {
-                            DeviceConfig first = device.getConfigs().get(0);
-                            configName = first.getName();
-                            config = first.getConfig();
+                            stateName = values[1];
+                            config = DeviceConfigHelper.getFolderConfig(device, stateName);
+                        } else if (device.getAllStates().size() > 0) {
+                            State first = device.getAllStates().get(0);
+                            stateName = first.getName();
+                            config = DeviceConfigHelper.getFolderConfig(first);
                         }
                         if (config != null) {
                             // Load locale. Note that this can get overwritten by the
@@ -507,7 +510,7 @@
 
         mOrientationCombo = new ToolItem(toolBar, SWT.DROP_DOWN);
         mOrientationCombo.setImage(icons.getIcon(ICON_PORTRAIT));
-        mOrientationCombo.setToolTipText("Flip Orientation");
+        mOrientationCombo.setToolTipText("Go to next state");
 
         @SuppressWarnings("unused")
         ToolItem separator4 = new ToolItem(toolBar, SWT.SEPARATOR);
@@ -752,7 +755,7 @@
                     if (loadedConfigData) {
                         // first make sure we have the config to adapt
                         selectDevice(mState.device);
-                        selectConfig(mState.configName);
+                        selectState(mState.stateName);
 
                         adaptConfigSelection(false /*needBestMatch*/);
 
@@ -1145,12 +1148,12 @@
 
     private static class ConfigMatch {
         final FolderConfiguration testConfig;
-        final LayoutDevice device;
+        final Device device;
         final String name;
         final ConfigBundle bundle;
 
-        public ConfigMatch(FolderConfiguration testConfig,
-                LayoutDevice device, String name, ConfigBundle bundle) {
+        public ConfigMatch(FolderConfiguration testConfig, Device device, String name,
+                ConfigBundle bundle) {
             this.testConfig = testConfig;
             this.device = device;
             this.name = name;
@@ -1171,10 +1174,11 @@
      * the current config. This must only be true if the current config is compatible.
      */
     private void findAndSetCompatibleConfig(boolean favorCurrentConfig) {
-        // list of compatible device/config/locale
+        // list of compatible device/state/locale
         List<ConfigMatch> anyMatches = new ArrayList<ConfigMatch>();
 
-        // list of actual best match (ie the file is a best match for the device/config)
+        // list of actual best match (ie the file is a best match for the
+        // device/state)
         List<ConfigMatch> bestMatches = new ArrayList<ConfigMatch>();
 
         // get a locale that match the host locale roughly (may not be exact match on the region.)
@@ -1219,27 +1223,30 @@
 
         addRenderTargetToBundles(configBundles);
 
-        for (LayoutDevice device : mDeviceList) {
-            for (DeviceConfig config : device.getConfigs()) {
+        for (Device device : mDeviceList) {
+            for (State state : device.getAllStates()) {
 
-                // loop on the list of config bundles to create full configurations.
+                // loop on the list of config bundles to create full
+                // configurations.
+                FolderConfiguration stateConfig = DeviceConfigHelper.getFolderConfig(state);
                 for (ConfigBundle bundle : configBundles) {
                     // create a new config with device config
                     FolderConfiguration testConfig = new FolderConfiguration();
-                    testConfig.set(config.getConfig());
+                    testConfig.set(stateConfig);
 
                     // add on top of it, the extra qualifiers from the bundle
                     testConfig.add(bundle.config);
 
                     if (mEditedConfig.isMatchFor(testConfig)) {
-                        // this is a basic match. record it in case we don't find a match
+                        // this is a basic match. record it in case we don't
+                        // find a match
                         // where the edited file is a best config.
-                        anyMatches.add(new ConfigMatch(testConfig, device, config.getName(),
-                                bundle));
+                        anyMatches
+                                .add(new ConfigMatch(testConfig, device, state.getName(), bundle));
 
                         if (isCurrentFileBestMatchFor(testConfig)) {
                             // this is what we want.
-                            bestMatches.add(new ConfigMatch(testConfig, device, config.getName(),
+                            bestMatches.add(new ConfigMatch(testConfig, device, state.getName(),
                                     bundle));
                         }
                     }
@@ -1267,7 +1274,7 @@
                 // select the best device anyway.
                 ConfigMatch match = selectConfigMatch(anyMatches);
                 selectDevice(mState.device = match.device);
-                selectConfig(match.name);
+                selectState(match.name);
                 selectLocale(mLocaleList.get(match.bundle.localeIndex));
 
                 mState.uiMode = UiMode.getByIndex(match.bundle.dockModeIndex);
@@ -1285,13 +1292,13 @@
 
             } else {
                 // TODO: there is no device/config able to display the layout, create one.
-                // For the base config values, we'll take the first device and config,
+                // For the base config values, we'll take the first device and state,
                 // and replace whatever qualifier required by the layout file.
             }
         } else {
             ConfigMatch match = selectConfigMatch(bestMatches);
             selectDevice(mState.device = match.device);
-            selectConfig(match.name);
+            selectState(match.name);
             selectLocale(mLocaleList.get(match.bundle.localeIndex));
             mState.uiMode = UiMode.getByIndex(match.bundle.dockModeIndex);
             mState.night = NightMode.getByIndex(match.bundle.nightModeIndex);
@@ -1493,10 +1500,9 @@
         // check the device config (ie sans locale)
         boolean needConfigChange = true; // if still true, we need to find another config.
         boolean currentConfigIsCompatible = false;
-        DeviceConfig selectedConfig = getSelectedDeviceConfig();
-        if (selectedConfig != null) {
-            String configName = selectedConfig.getName();
-            FolderConfiguration currentConfig = mState.device.getFolderConfigByName(configName);
+        State selectedState = getSelectedDeviceState();
+        if (selectedState != null) {
+            FolderConfiguration currentConfig = DeviceConfigHelper.getFolderConfig(selectedState);
             if (currentConfig != null && mEditedConfig.isMatchFor(currentConfig)) {
                 currentConfigIsCompatible = true; // current config is compatible
                 if (needBestMatch == false || isCurrentFileBestMatchFor(currentConfig)) {
@@ -1506,15 +1512,15 @@
         }
 
         if (needConfigChange) {
-            // if the current config/locale isn't a correct match, then
-            // look for another config/locale in the same device.
+            // if the current state/locale isn't a correct match, then
+            // look for another state/locale in the same device.
             FolderConfiguration testConfig = new FolderConfiguration();
 
             // first look in the current device.
             String matchName = null;
             int localeIndex = -1;
-            mainloop: for (DeviceConfig config : mState.device.getConfigs()) {
-                testConfig.set(config.getConfig());
+            mainloop: for (State state : mState.device.getAllStates()) {
+                testConfig.set(DeviceConfigHelper.getFolderConfig(state));
 
                 // loop on the locales.
                 for (int i = 0 ; i < mLocaleList.size() ; i++) {
@@ -1526,7 +1532,7 @@
 
                     if (mEditedConfig.isMatchFor(testConfig) &&
                             isCurrentFileBestMatchFor(testConfig)) {
-                        matchName = config.getName();
+                        matchName = state.getName();
                         localeIndex = i;
                         break mainloop;
                     }
@@ -1534,11 +1540,12 @@
             }
 
             if (matchName != null) {
-                selectConfig(matchName);
+                selectState(matchName);
                 selectLocale(mLocaleList.get(localeIndex));
             } else {
-                // no match in current device with any config/locale
-                // attempt to find another device that can display this particular config.
+                // no match in current device with any state/locale
+                // attempt to find another device that can display this
+                // particular state.
                 findAndSetCompatibleConfig(currentConfigIsCompatible);
             }
         }
@@ -1590,9 +1597,9 @@
 
     private void saveState() {
         if (mDisableUpdates == 0) {
-            DeviceConfig deviceConfig = getSelectedDeviceConfig();
-            String configName = deviceConfig != null ? deviceConfig.getName() : null;
-            mState.configName = configName;
+            State state = getSelectedDeviceState();
+            String stateName = state != null ? state.getName() : null;
+            mState.stateName = stateName;
 
             // since the locales are relative to the project, only keeping the index is enough
             mState.locale = getSelectedLocale();
@@ -1721,7 +1728,10 @@
         }
     }
 
-    private String getDeviceLabel(LayoutDevice device, boolean brief) {
+    private String getDeviceLabel(Device device, boolean brief) {
+        if(device == null) {
+            return "";
+        }
         String name = device.getName();
 
         if (brief) {
@@ -1747,40 +1757,71 @@
         Listener menuListener = new Listener() {
             @Override
             public void handleEvent(Event event) {
+                Device current = getSelectedDevice();
                 Menu menu = new Menu(ConfigurationComposite.this.getShell(), SWT.POP_UP);
 
-                LayoutDevice current = getSelectedDevice();
-                if (mDeviceList != null && mDeviceList.size() > 0) {
-                    for (final LayoutDevice device : mDeviceList) {
-                        String title = getDeviceLabel(device, false);
-                        MenuItem item = new MenuItem(menu, SWT.CHECK);
-                        item.setText(title);
+                AvdManager avdManager = Sdk.getCurrent().getAvdManager();
+                AvdInfo[] avds = avdManager.getValidAvds();
+                boolean separatorNeeded = false;
+                for (AvdInfo avd : avds) {
+                    for (final Device d : mDeviceList) {
+                        if (d.getManufacturer().equals(avd.getDeviceManufacturer())
+                                && d.getName().equals(avd.getDeviceName())) {
+                            separatorNeeded = true;
+                            MenuItem item = new MenuItem(menu, SWT.CHECK);
+                            item.setText(avd.getName());
+                            item.setSelection(current == d);
 
-                        boolean selected = current == device;
-                        if (selected) {
-                            item.setSelection(true);
+                            item.addSelectionListener(new SelectionAdapter() {
+
+                                @Override
+                                public void widgetSelected(SelectionEvent e) {
+                                    selectDevice(d);
+                                    onDeviceChange(true /*recomputeLayout*/);
+                                }
+                            });
                         }
-
-                        item.addSelectionListener(new SelectionAdapter() {
-                            @Override
-                            public void widgetSelected(SelectionEvent e) {
-                                selectDevice(device);
-                                onDeviceChange(true /*recomputeLayout*/);
-                            }
-                        });
                     }
+                }
 
+                if (separatorNeeded) {
                     @SuppressWarnings("unused")
                     MenuItem separator = new MenuItem(menu, SWT.SEPARATOR);
+                }
 
-                    MenuItem item = new MenuItem(menu, SWT.PUSH);
-                    item.setText("Add Custom...");
-                    item.addSelectionListener(new SelectionAdapter() {
-                        @Override
-                        public void widgetSelected(SelectionEvent e) {
-                            onCustomDeviceConfig();
+                // Group the devices by manufacturer, then put them in the menu
+                if (!mDeviceList.isEmpty()) {
+                    Map<String, List<Device>> manufacturers = new TreeMap<String, List<Device>>();
+                    for (Device device : mDeviceList) {
+                        List<Device> devices;
+                        if(manufacturers.containsKey(device.getManufacturer())) {
+                            devices = manufacturers.get(device.getManufacturer());
+                        } else {
+                            devices = new ArrayList<Device>();
+                            manufacturers.put(device.getManufacturer(), devices);
                         }
-                    });
+                        devices.add(device);
+                    }
+                    for (List<Device> devices : manufacturers.values()) {
+                        MenuItem item = new MenuItem(menu, SWT.CASCADE);
+                        item.setText(devices.get(0).getManufacturer());
+                        Menu manufacturerMenu = new Menu(menu);
+                        item.setMenu(manufacturerMenu);
+                        for (final Device d : devices) {
+                            MenuItem deviceItem = new MenuItem(manufacturerMenu, SWT.CHECK);
+                            deviceItem.setText(d.getName());
+                            deviceItem.setSelection(current == d);
+
+                            deviceItem.addSelectionListener(new SelectionAdapter() {
+
+                                @Override
+                                public void widgetSelected(SelectionEvent e) {
+                                    selectDevice(d);
+                                    onDeviceChange(true /*recomputeLayout*/);
+                                }
+                            });
+                        }
+                    }
 
                 }
 
@@ -1849,31 +1890,31 @@
                  if (event.detail == SWT.ARROW) {
                      OrientationMenuAction.showMenu(ConfigurationComposite.this, combo);
                  } else {
-                     flipOrientation();
+                     gotoNextState();
                  }
             }
         };
         combo.addListener(SWT.Selection, menuListener);
     }
 
-    /** Flip the current orientation to the next available device orientation, if any */
-    private void flipOrientation() {
-        DeviceConfig config = getSelectedDeviceConfig();
-        DeviceConfig flipped = getNextDeviceConfig(getSelectedDeviceConfig());
-        if (flipped != config) {
-            selectDeviceConfig(flipped);
+    /** Move to the next device state, changing the icon if it changes orientation */
+    private void gotoNextState() {
+        State state = getSelectedDeviceState();
+        State flipped = getNextDeviceState(state);
+        if (flipped != state) {
+            selectDeviceState(flipped);
             onDeviceConfigChange();
         }
     }
 
-    /** Get the next cyclical orientation after the given orientation */
+    /** Get the next cyclical state after the given state */
     @Nullable
-    DeviceConfig getNextDeviceConfig(DeviceConfig config) {
-        LayoutDevice device = getSelectedDevice();
-        List<DeviceConfig> configs = device.getConfigs();
-        for (int i = 0; i < configs.size(); i++) {
-            if (configs.get(i) == config) {
-                return configs.get((i + 1) % configs.size());
+    State getNextDeviceState(State state) {
+        Device device = getSelectedDevice();
+        List<State> states = device.getAllStates();
+        for (int i = 0; i < states.size(); i++) {
+            if (states.get(i) == state) {
+                return states.get((i + 1) % states.size());
             }
         }
 
@@ -2304,13 +2345,13 @@
         IProject project = mEditedFile.getProject();
         ManifestInfo manifest = ManifestInfo.get(project);
 
-        // Look up the screen size for the current configuration
+        // Look up the screen size for the current state
         ScreenSize screenSize = null;
         if (mState.device != null) {
-            List<DeviceConfig> configs = mState.device.getConfigs();
-            for (DeviceConfig config : configs) {
+            List<State> states = mState.device.getAllStates();
+            for (State state : states) {
                 ScreenSizeQualifier qualifier =
-                    config.getConfig().getScreenSizeQualifier();
+                    DeviceConfigHelper.getFolderConfig(state).getScreenSizeQualifier();
                 screenSize = qualifier.getValue();
                 break;
             }
@@ -2378,7 +2419,12 @@
      */
     public float getXDpi() {
         if (mState.device != null) {
-            float dpi = mState.device.getXDpi();
+
+            State currState = mState.device.getState(mState.stateName);
+            if (currState == null) {
+                currState = mState.device.getDefaultState();
+            }
+            float dpi = (float) currState.getHardware().getScreen().getXdpi();
             if (Float.isNaN(dpi) == false) {
                 return dpi;
             }
@@ -2393,7 +2439,12 @@
      */
     public float getYDpi() {
         if (mState.device != null) {
-            float dpi = mState.device.getYDpi();
+
+            State currState = mState.device.getState(mState.stateName);
+            if (currState == null) {
+                currState = mState.device.getDefaultState();
+            }
+            float dpi = (float) currState.getHardware().getScreen().getYdpi();
             if (Float.isNaN(dpi) == false) {
                 return dpi;
             }
@@ -2459,7 +2510,7 @@
      * @return the device name, or null
      */
     public String getDevice() {
-        LayoutDevice device = getSelectedDevice();
+        Device device = getSelectedDevice();
         if (device != null) {
             return device.getName();
         }
@@ -2530,24 +2581,22 @@
     }
 
     /**
-     * Loads the list of {@link LayoutDevice} and inits the UI with it.
+     * Loads the list of {@link Device}s and inits the UI with it.
      */
     private void initDevices() {
-        mDeviceList = null;
-
         Sdk sdk = Sdk.getCurrent();
         if (sdk != null) {
-            LayoutDeviceManager manager = sdk.getLayoutDeviceManager();
-            mDeviceList = manager.getCombinedList();
+            mDeviceList = sdk.getDevices();
+        } else {
+            mDeviceList = new ArrayList<Device>();
         }
 
-
         // fill with the devices
-        if (mDeviceList != null && mDeviceList.size() > 0) {
-            LayoutDevice first = mDeviceList.get(0);
+        if (!mDeviceList.isEmpty()) {
+            Device first = mDeviceList.get(0);
             selectDevice(first);
-            List<DeviceConfig> configs = first.getConfigs();
-            selectDeviceConfig(configs.get(0));
+            List<State> states = first.getAllStates();
+            selectDeviceState(states.get(0));
         } else {
             selectDevice(null);
         }
@@ -2580,11 +2629,11 @@
     }
 
     @NonNull
-    ScreenOrientation getOrientation(DeviceConfig config) {
-        ScreenOrientationQualifier qualifier = config.getConfig().getScreenOrientationQualifier();
+    ScreenOrientation getOrientation(State state) {
+        FolderConfiguration config = DeviceConfigHelper.getFolderConfig(state);
         ScreenOrientation orientation = null;
-        if (qualifier != null) {
-            orientation = qualifier.getValue();
+        if (config != null && config.getScreenOrientationQualifier() != null) {
+            orientation = config.getScreenOrientationQualifier().getValue();
         }
 
         if (orientation == null) {
@@ -2594,24 +2643,24 @@
         return orientation;
     }
 
-    void selectDeviceConfig(@Nullable DeviceConfig config) {
-        mOrientationCombo.setData(config);
+    void selectDeviceState(@Nullable State state) {
+        mOrientationCombo.setData(state);
 
-        DeviceConfig nextConfig = getNextDeviceConfig(config);
-        mOrientationCombo.setImage(getOrientationIcon(getOrientation(nextConfig),
-                nextConfig != config));
+        State nextState = getNextDeviceState(state);
+        mOrientationCombo.setImage(getOrientationIcon(getOrientation(state),
+                nextState != state));
     }
 
-    DeviceConfig getSelectedDeviceConfig() {
-        return (DeviceConfig) mOrientationCombo.getData();
+    State getSelectedDeviceState() {
+        return (State) mOrientationCombo.getData();
     }
 
     /**
-     * Selects a given {@link LayoutDevice} in the device combo, if it is found.
+     * Selects a given {@link Device} in the device combo, if it is found.
      * @param device the device to select
      * @return true if the device was found.
      */
-    private boolean selectDevice(@Nullable LayoutDevice device) {
+    private boolean selectDevice(@Nullable Device device) {
         mDeviceCombo.setData(device);
         if (device != null) {
             mDeviceCombo.setText(getDeviceLabel(device, true));
@@ -2623,21 +2672,22 @@
         return false;
     }
 
-    LayoutDevice getSelectedDevice() {
-        return (LayoutDevice) mDeviceCombo.getData();
+    @Nullable
+    Device getSelectedDevice() {
+        return (Device) mDeviceCombo.getData();
     }
 
     /**
-     * Selects a config by name.
-     * @param name the name of the config to select.
+     * Selects a state by name.
+     * @param name the name of the state to select.
      */
-    private void selectConfig(String name) {
-        LayoutDevice device = getSelectedDevice();
-        DeviceConfig config = null;
+    private void selectState(String name) {
+        Device device = getSelectedDevice();
+        State state = null;
         if (device != null) {
-            config = device.getDeviceConfigByName(name);
+            state = device.getState(name);
         }
-        selectDeviceConfig(config);
+        selectDeviceState(state);
     }
 
     /**
@@ -2653,17 +2703,16 @@
 
         String newConfigName = null;
 
-        DeviceConfig prevConfig = getSelectedDeviceConfig();
-        LayoutDevice device = getSelectedDevice();
-        if (mState.device != null && prevConfig != null && device != null) {
+        State prevState = getSelectedDeviceState();
+        Device device = getSelectedDevice();
+        if (mState.device != null && prevState != null && device != null) {
             // get the previous config, so that we can look for a close match
-            FolderConfiguration oldConfig = mState.device.getFolderConfigByName(
-                    prevConfig.getName());
-            newConfigName = getClosestMatch(oldConfig, device.getConfigs());
+            FolderConfiguration oldConfig = DeviceConfigHelper.getFolderConfig(prevState);
+            newConfigName = getClosestMatch(oldConfig, device.getAllStates());
         }
         mState.device = device;
 
-        selectConfig(newConfigName);
+        selectState(newConfigName);
 
         computeCurrentConfig();
 
@@ -2673,80 +2722,37 @@
     }
 
     /**
-     * Handles a user request for the {@link ConfigManagerDialog}.
-     */
-    private void onCustomDeviceConfig() {
-        ConfigManagerDialog dialog = new ConfigManagerDialog(getShell());
-        dialog.open();
-
-        // save the user devices
-        Sdk.getCurrent().getLayoutDeviceManager().save();
-
-        // Update the UI with no triggered event
-        mDisableUpdates++;
-
-        try {
-            LayoutDevice oldCurrent = mState.device;
-
-            // but first, update the device combo
-            initDevices();
-
-            // attempts to reselect the current device.
-            if (selectDevice(oldCurrent)) {
-                // current device still exists.
-                // reselect the config
-                selectConfig(mState.configName);
-
-                // reset the UI as if it was just a replacement file, since we can keep
-                // the current device (and possibly config).
-                adaptConfigSelection(false /*needBestMatch*/);
-
-            } else {
-                // find a new device/config to match the current file.
-                findAndSetCompatibleConfig(false /*favorCurrentConfig*/);
-            }
-        } finally {
-            mDisableUpdates--;
-        }
-
-        // recompute the current config
-        computeCurrentConfig();
-
-        // force a redraw
-        onDeviceChange(true /*recomputeLayout*/);
-    }
-
-    /**
-     * Attempts to find a close config among a list
+     * Attempts to find a close state among a list
      * @param oldConfig the reference config.
-     * @param configs the list of config to search through
-     * @return the name of the closest config match, or possibly null if no configs are compatible
-     * (this can only happen if the configs don't have a single qualifier that is the same).
+     * @param states the list of states to search through
+     * @return the name of the closest state match, or possibly null if no states are compatible
+     * (this can only happen if the states don't have a single qualifier that is the same).
      */
-    private String getClosestMatch(FolderConfiguration oldConfig, List<DeviceConfig> configs) {
+    private String getClosestMatch(FolderConfiguration oldConfig, List<State> states) {
 
-        // create 2 lists as we're going to go through one and put the candidates in the other.
-        ArrayList<DeviceConfig> list1 = new ArrayList<DeviceConfig>();
-        ArrayList<DeviceConfig> list2 = new ArrayList<DeviceConfig>();
+        // create 2 lists as we're going to go through one and put the
+        // candidates in the other.
+        ArrayList<State> list1 = new ArrayList<State>();
+        ArrayList<State> list2 = new ArrayList<State>();
 
-        list1.addAll(configs);
+        list1.addAll(states);
 
         final int count = FolderConfiguration.getQualifierCount();
         for (int i = 0 ; i < count ; i++) {
-            // compute the new candidate list by only taking configs that have
-            // the same i-th qualifier as the old config
-            for (DeviceConfig c : list1) {
+            // compute the new candidate list by only taking states that have
+            // the same i-th qualifier as the old state
+            for (State s : list1) {
                 ResourceQualifier oldQualifier = oldConfig.getQualifier(i);
 
-                FolderConfiguration folderConfig = c.getConfig();
+                FolderConfiguration folderConfig = DeviceConfigHelper.getFolderConfig(s);
                 ResourceQualifier newQualifier = folderConfig.getQualifier(i);
 
                 if (oldQualifier == null) {
                     if (newQualifier == null) {
-                        list2.add(c);
+                        list2.add(s);
                     }
                 } else if (oldQualifier.equals(newQualifier)) {
-                    list2.add(c);
+                    list2.add(s);
                 }
             }
 
@@ -2756,9 +2762,9 @@
                 return list2.get(0).getName();
             }
 
-            // if the list is empty, then all the new configs failed. It is considered ok, and
+            // if the list is empty, then all the new states failed. It is considered ok, and
             // we move to the next qualifier anyway. This way, if a qualifier is different for
-            // all new configs it is simply ignored.
+            // all new states it is simply ignored.
             if (list2.size() != 0) {
                 // move the candidates back into list1.
                 list1.clear();
@@ -2768,7 +2774,7 @@
         }
 
         // the only way to reach this point is if there's an exact match.
-        // (if there are more than one, then there's a duplicate config and it doesn't matter,
+        // (if there are more than one, then there's a duplicate state and it doesn't matter,
         // we take the first one).
         if (list1.size() > 0) {
             return list1.get(0).getName();
@@ -2861,9 +2867,9 @@
         saveState();
 
         if (mState.device != null) {
-            // get the device config from the device/config combos.
-            FolderConfiguration config = mState.device.getFolderConfigByName(
-                    getSelectedDeviceConfig().getName());
+            // get the device config from the device/state combos.
+            FolderConfiguration config =
+                DeviceConfigHelper.getFolderConfig(getSelectedDeviceState());
 
             // replace the config with the one from the device
             mCurrentConfig.set(config);
@@ -2877,6 +2883,18 @@
                         (RegionQualifier)localeQualifiers[LOCALE_REGION]);
             }
 
+            // Replace the UiMode with the selected one, if one is selected
+            UiMode uiMode = getSelectedUiMode();
+            if (uiMode != null) {
+                mCurrentConfig.setUiModeQualifier(new UiModeQualifier(uiMode));
+            }
+
+            // Replace the NightMode with the selected one, if one is selected
+            NightMode night = getSelectedNightMode();
+            if (night != null) {
+                mCurrentConfig.setNightModeQualifier(new NightModeQualifier(night));
+            }
+
             // replace the API level by the selection of the combo
             IAndroidTarget target = getRenderingTarget();
             if (target == null) {
@@ -3209,7 +3227,7 @@
 
         final Object source = e.getSource();
         if (source == mOrientationCombo) {
-            flipOrientation();
+            gotoNextState();
         }
     }
 
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/OrientationMenuAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/OrientationMenuAction.java
index c2f32c5..27446b2 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/OrientationMenuAction.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/OrientationMenuAction.java
@@ -22,6 +22,10 @@
 import com.android.resources.NightMode;
 import com.android.resources.ScreenOrientation;
 import com.android.resources.UiMode;
+import com.android.sdklib.devices.Device;
+import com.android.sdklib.devices.DeviceManager;
+import com.android.sdklib.devices.State;
+
 
 import org.eclipse.jface.action.Action;
 import org.eclipse.jface.action.ActionContributionItem;
@@ -59,19 +63,19 @@
         MenuManager manager = new MenuManager();
 
         // Show toggles for all the available configurations
-        DeviceConfig current = configuration.getSelectedDeviceConfig();
-        LayoutDevice device = configuration.getSelectedDevice();
+        State current = configuration.getSelectedDeviceState();
+        Device device = configuration.getSelectedDevice();
         if (device != null) {
-            List<DeviceConfig> configs = device.getConfigs();
+            List<State> states = device.getAllStates();
 
-            if (configs.size() > 1 && current != null) {
-                DeviceConfig flip = configuration.getNextDeviceConfig(current);
+            if (states.size() > 1 && current != null) {
+                State flip = configuration.getNextDeviceState(current);
                 manager.add(new DeviceConfigAction(configuration,
                         String.format("Switch to %1$s", flip.getName()), flip, false, true));
                 manager.add(new Separator());
             }
 
-            for (DeviceConfig config : configs) {
+            for (State config : states) {
                 manager.add(new DeviceConfigAction(configuration, config.getName(),
                         config, config == current, false));
             }
@@ -150,23 +154,23 @@
 
     private static class DeviceConfigAction extends Action {
         private final ConfigurationComposite mConfiguration;
-        private final DeviceConfig mConfig;
+        private final State mState;
 
         private DeviceConfigAction(ConfigurationComposite configuration, String title,
-                DeviceConfig config, boolean checked, boolean flip) {
+                State state, boolean checked, boolean flip) {
             super(title, IAction.AS_RADIO_BUTTON);
             mConfiguration = configuration;
-            mConfig = config;
+            mState = state;
             if (checked) {
                 setChecked(true);
             }
-            ScreenOrientation orientation = configuration.getOrientation(config);
+            ScreenOrientation orientation = configuration.getOrientation(state);
             setImageDescriptor(configuration.getOrientationImage(orientation, flip));
         }
 
         @Override
         public void run() {
-            mConfiguration.selectDeviceConfig(mConfig);
+            mConfiguration.selectDeviceState(mState);
             mConfiguration.onDeviceConfigChange();
         }
     }
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java
index 3fed2e0..79c9d62 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java
@@ -44,6 +44,8 @@
 import com.android.sdklib.ISdkLog;
 import com.android.sdklib.SdkConstants;
 import com.android.sdklib.SdkManager;
+import com.android.sdklib.devices.Device;
+import com.android.sdklib.devices.DeviceManager;
 import com.android.sdklib.internal.avd.AvdManager;
 import com.android.sdklib.internal.project.ProjectProperties;
 import com.android.sdklib.internal.project.ProjectProperties.PropertyType;
@@ -129,6 +131,7 @@
     private final SdkManager mManager;
     private final DexWrapper mDexWrapper;
     private final AvdManager mAvdManager;
+    private final DeviceManager mDeviceManager;
 
     /** Map associating an {@link IAndroidTarget} to an {@link AndroidTargetData} */
     private final HashMap<IAndroidTarget, AndroidTargetData> mTargetDataMap =
@@ -145,8 +148,6 @@
 
     private final String mDocBaseUrl;
 
-    private final LayoutDeviceManager mLayoutDeviceManager = new LayoutDeviceManager();
-
     /**
      * Classes implementing this interface will receive notification when targets are changed.
      */
@@ -662,8 +663,13 @@
         }
     }
 
-    public LayoutDeviceManager getLayoutDeviceManager() {
-        return mLayoutDeviceManager;
+    public DeviceManager getDeviceManager() {
+        return mDeviceManager;
+    }
+
+    /** Returns the devices provided by the SDK, including user created devices */
+    public List<Device> getDevices() {
+        return mDeviceManager.getDevices(getSdkLocation());
     }
 
     /**
@@ -744,10 +750,7 @@
         mDocBaseUrl = getDocumentationBaseUrl(mManager.getLocation() +
                 SdkConstants.OS_SDK_DOCS_FOLDER);
 
-        // load the built-in and user layout devices
-        mLayoutDeviceManager.loadDefaultAndUserDevices(mManager.getLocation());
-        // and the ones from the add-on
-        loadLayoutDevices();
+        mDeviceManager = new DeviceManager(AdtPlugin.getDefault());
 
         // update whatever ProjectState is already present with new IAndroidTarget objects.
         synchronized (LOCK) {
@@ -826,24 +829,6 @@
     }
 
     /**
-     * Parses the SDK add-ons to look for files called {@link SdkConstants#FN_DEVICES_XML} to
-     * load {@link LayoutDevice} from them.
-     */
-    private void loadLayoutDevices() {
-        IAndroidTarget[] targets = mManager.getTargets();
-        for (IAndroidTarget target : targets) {
-            if (target.isPlatform() == false) {
-                File deviceXml = new File(target.getLocation(), SdkConstants.FN_DEVICES_XML);
-                if (deviceXml.isFile()) {
-                    mLayoutDeviceManager.parseAddOnLayoutDevice(deviceXml);
-                }
-            }
-        }
-
-        mLayoutDeviceManager.sealAddonLayoutDevices();
-    }
-
-    /**
      * Delegate listener for project changes.
      */
     private IProjectListener mProjectListener = new IProjectListener() {
diff --git a/eclipse/plugins/com.android.ide.eclipse.base/.classpath b/eclipse/plugins/com.android.ide.eclipse.base/.classpath
index 9b4ea2f..5f09fc7 100644
--- a/eclipse/plugins/com.android.ide.eclipse.base/.classpath
+++ b/eclipse/plugins/com.android.ide.eclipse.base/.classpath
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
+	<classpathentry exported="true" kind="lib" path="libs/dvlib.jar"/>
 	<classpathentry exported="true" kind="lib" path="libs/androidprefs.jar"/>
 	<classpathentry exported="true" kind="lib" path="libs/common.jar"/>
 	<classpathentry exported="true" kind="lib" path="libs/commons-codec-1.4.jar"/>
diff --git a/eclipse/plugins/com.android.ide.eclipse.base/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.base/META-INF/MANIFEST.MF
index b03048a..b16d89d 100644
--- a/eclipse/plugins/com.android.ide.eclipse.base/META-INF/MANIFEST.MF
+++ b/eclipse/plugins/com.android.ide.eclipse.base/META-INF/MANIFEST.MF
@@ -19,15 +19,18 @@
  libs/httpcore-4.1.jar,
  libs/httpmime-4.1.1.jar,
  libs/sdklib.jar,
- libs/sdkstats.jar
+ libs/sdkstats.jar,
+ libs/dvlib.jar
 Export-Package: com.android,
  com.android.annotations,
+ com.android.dvlib,
  com.android.ide.eclipse.base,
  com.android.io,
  com.android.prefs,
  com.android.resources,
  com.android.sdklib,
  com.android.sdklib.build,
+ com.android.sdklib.devices,
  com.android.sdklib.internal.avd,
  com.android.sdklib.internal.build,
  com.android.sdklib.internal.project,
diff --git a/eclipse/plugins/com.android.ide.eclipse.base/build.properties b/eclipse/plugins/com.android.ide.eclipse.base/build.properties
index 6dcdd76..15e907d 100644
--- a/eclipse/plugins/com.android.ide.eclipse.base/build.properties
+++ b/eclipse/plugins/com.android.ide.eclipse.base/build.properties
@@ -12,6 +12,7 @@
                libs/httpcore-4.1.jar,\
                libs/httpmime-4.1.1.jar,\
                libs/sdklib.jar,\
-               libs/sdkstats.jar
+               libs/sdkstats.jar,\
+               libs/dvlib.jar
 jars.compile.order = .
 source.. = src/
diff --git a/eclipse/scripts/create_all_symlinks.sh b/eclipse/scripts/create_all_symlinks.sh
index dbc2cb8..6cf1fb2 100755
--- a/eclipse/scripts/create_all_symlinks.sh
+++ b/eclipse/scripts/create_all_symlinks.sh
@@ -108,7 +108,7 @@
 ### BASE ###
 
 BASE_PLUGIN_DEST="sdk/eclipse/plugins/com.android.ide.eclipse.base/libs"
-BASE_PLUGIN_LIBS="common sdkstats androidprefs sdklib"
+BASE_PLUGIN_LIBS="common sdkstats androidprefs sdklib dvlib"
 BASE_PLUGIN_PREBUILTS="\
     prebuilts/tools/common/commons-compress/commons-compress-1.0.jar \
     prebuilts/tools/common/guava-tools/guava-10.0.1.jar \
diff --git a/ide_common/src/com/android/ide/common/resources/configuration/DeviceConfigHelper.java b/ide_common/src/com/android/ide/common/resources/configuration/DeviceConfigHelper.java
index 7ed955f..27eaa01 100644
--- a/ide_common/src/com/android/ide/common/resources/configuration/DeviceConfigHelper.java
+++ b/ide_common/src/com/android/ide/common/resources/configuration/DeviceConfigHelper.java
@@ -17,6 +17,8 @@
 package com.android.ide.common.resources.configuration;
 
 import com.android.annotations.Nullable;
+import com.android.resources.NightMode;
+import com.android.resources.UiMode;
 import com.android.sdklib.devices.Device;
 import com.android.sdklib.devices.Hardware;
 import com.android.sdklib.devices.Screen;
@@ -64,6 +66,15 @@
 
         config.updateScreenWidthAndHeight();
 
+        // Setup some default qualifiers
+        config.setUiModeQualifier(new UiModeQualifier(UiMode.NORMAL));
+        config.setNightModeQualifier(new NightModeQualifier(NightMode.NOTNIGHT));
+        config.setCountryCodeQualifier(new CountryCodeQualifier());
+        config.setLanguageQualifier(new LanguageQualifier());
+        config.setNetworkCodeQualifier(new NetworkCodeQualifier());
+        config.setRegionQualifier(new RegionQualifier());
+        config.setVersionQualifier(new VersionQualifier());
+
         return config;
     }
 
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/DeviceWriter.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/DeviceWriter.java
index 3ecc55e..453a4e5 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/DeviceWriter.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/devices/DeviceWriter.java
@@ -90,6 +90,7 @@
 
         Transformer tf = TransformerFactory.newInstance().newTransformer();
         tf.setOutputProperty(OutputKeys.INDENT, "yes");
+        tf.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
         DOMSource source = new DOMSource(doc);
         StreamResult result = new StreamResult(out);
         tf.transform(source, result);
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdInfo.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdInfo.java
index 463037e..54e2fa7 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdInfo.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdInfo.java
@@ -140,6 +140,24 @@
         return SdkConstants.CPU_ARCH_ARM;
     }
 
+    public String getDeviceManufacturer() {
+        String deviceManufacturer = mProperties.get(AvdManager.AVD_INI_DEVICE_MANUFACTURER);
+        if (deviceManufacturer != null && !deviceManufacturer.isEmpty()) {
+            return deviceManufacturer;
+        }
+
+        return "";
+    }
+
+    public String getDeviceName() {
+        String deviceName = mProperties.get(AvdManager.AVD_INI_DEVICE_NAME);
+        if (deviceName != null && !deviceName.isEmpty()) {
+            return deviceName;
+        }
+
+        return "";
+    }
+
     /** Convenience function to return a more user friendly name of the abi type. */
     public static String getPrettyAbiType(String raw) {
         String s = null;
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java
index 768a835..16bbb38 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java
@@ -86,6 +86,15 @@
      */
     public final static String AVD_INI_CPU_MODEL = "hw.cpu.model"; //$NON-NLS-1$
 
+    /**
+     * AVD/config.ini key name representing the manufacturer of the device this avd was based on.
+     */
+    public static final String AVD_INI_DEVICE_MANUFACTURER = "hw.device.manufacturer"; //$NON-NLS-1$
+
+    /**
+     * AVD/config.ini key name representing the name of the device this avd was based on.
+     */
+    public static final String AVD_INI_DEVICE_NAME = "hw.device.name"; //$NON-NLS-1$
 
     /**
      * AVD/config.ini key name representing the SDK-relative path of the skin folder, if any,
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java
index 23835e1..0cf52cf 100644
--- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java
@@ -573,6 +573,7 @@
         mStatusLabel.setText(" \n "); //$NON-NLS-1$
 
         reloadTargetCombo();
+        reloadDeviceCombo();
     }
 
     /**
@@ -763,9 +764,25 @@
 
         mAvdName.setText(mEditAvdInfo.getName());
 
+        Map<String, String> props = mEditAvdInfo.getProperties();
+
+        if (props != null) {
+            // Try to match it to a device
+
+            // The device has to be set before everything else because
+            // selecting a device will modify other options
+            for (int i = 0; i < mDeviceList.size(); i++){
+                Device d = mDeviceList.get(i);
+                if(d.getManufacturer().equals(props.get(AvdManager.AVD_INI_DEVICE_MANUFACTURER))
+                        && d.getName().equals(props.get(AvdManager.AVD_INI_DEVICE_NAME))) {
+                    mDeviceCombo.select(i);
+                    break;
+                }
+            }
+        }
+
         IAndroidTarget target = mEditAvdInfo.getTarget();
         if (target != null && !mCurrentTargets.isEmpty()) {
-            mDeviceCombo.setEnabled(true);
             // Try to select the target in the target combo.
             // This will fail if the AVD needs to be repaired.
             //
@@ -776,6 +793,7 @@
                 if (target.equals(mCurrentTargets.get(mTargetCombo.getItem(i)))) {
                     mTargetCombo.select(i);
                     reloadAbiTypeCombo();
+                    reloadDeviceCombo();
                     reloadSkinCombo();
                     break;
                 }
@@ -797,8 +815,8 @@
             }
         }
 
-        Map<String, String> props = mEditAvdInfo.getProperties();
         if (props != null) {
+
             // First try the skin name and if it doesn't work fallback on the skin path
             nextSkin: for (int s = 0; s < 2; s++) {
                 String skin = props.get(s == 0 ? AvdManager.AVD_INI_SKIN_NAME
@@ -885,15 +903,16 @@
         mProperties.remove(AvdManager.AVD_INI_SNAPSHOT_PRESENT);
         mProperties.remove(AvdManager.AVD_INI_IMAGES_1);
         mProperties.remove(AvdManager.AVD_INI_IMAGES_2);
+        mProperties.remove(AvdManager.AVD_INI_DEVICE_MANUFACTURER);
+        mProperties.remove(AvdManager.AVD_INI_DEVICE_NAME);
 
         mHardwareViewer.refresh();
     }
 
     // Sets all of the other options based on the device currently selected in mDeviceCombo
     private void prefillWithDeviceConfig() {
-        int index = mDeviceCombo.getSelectionIndex();
-        if (index >= 0 && index < mDeviceList.size()){
-            Device d = mDeviceList.get(index);
+        Device d = getSelectedDevice();
+        if (d != null) {
             Hardware hw = d.getDefaultHardware();
 
             // Try setting the CPU/ABI
@@ -1042,10 +1061,22 @@
 
 
     private void reloadDeviceCombo() {
+        Device selectedDevice = getSelectedDevice();
+
+        mDeviceCombo.removeAll();
         for (Device d : mDeviceList) {
             mDeviceCombo.add(d.getManufacturer() + " " + d.getName());
         }
-        mDeviceCombo.setEnabled(true);
+
+        // Try to select the previously selected device if it still exists
+        if (selectedDevice != null) {
+            int index = mDeviceList.indexOf(selectedDevice);
+            if (index >= 0) {
+                mDeviceCombo.select(index);
+            }
+        }
+
+        mDeviceCombo.setEnabled(mTargetCombo.getSelectionIndex() >= 0);
     }
 
     private void reloadSkinCombo() {
@@ -1392,6 +1423,15 @@
             return false;
         }
 
+        targetIndex = mDeviceCombo.getSelectionIndex();
+        if (targetIndex >= 0 && targetIndex < mDeviceList.size()) {
+            Device d = mDeviceList.get(targetIndex);
+            // Set the properties so it gets saved to the avd's ini
+            mProperties.put(AvdManager.AVD_INI_DEVICE_MANUFACTURER, d.getManufacturer());
+            mProperties.put(AvdManager.AVD_INI_DEVICE_NAME, d.getName());
+        }
+
+
         // resolve the target.
         String targetName = mTargetCombo.getItem(targetIndex);
         IAndroidTarget target = mCurrentTargets.get(targetName);
@@ -1492,6 +1532,10 @@
 
         success = avdInfo != null;
 
+        // Remove the device name and manufacturer properties so they don't show up in the hardware list
+        mProperties.remove(AvdManager.AVD_INI_DEVICE_MANUFACTURER);
+        mProperties.remove(AvdManager.AVD_INI_DEVICE_NAME);
+
         if (log instanceof MessageBoxLog) {
             ((MessageBoxLog) log).displayResult(success);
         }
@@ -1524,6 +1568,15 @@
         return new ISystemImage[0];
     }
 
+    private Device getSelectedDevice() {
+        int targetIndex = mDeviceCombo.getSelectionIndex();
+        if (targetIndex >= 0 && mDeviceList.size() > targetIndex){
+            return mDeviceList.get(targetIndex);
+        } else {
+            return null;
+        }
+    }
+
     // End of hiding from SWT Designer
     //$hide<<$
 }