OSDN Git Service

AVD and ADT eclipse plugin to support processor-specific platform images and emulators.
authorJohnnie Birch <johnnie.l.birch.jr@intel.com>
Fri, 4 Feb 2011 02:56:59 +0000 (18:56 -0800)
committerJohnnie Birch <johnnie.l.birch.jr@intel.com>
Tue, 1 Mar 2011 19:08:33 +0000 (11:08 -0800)
This is a first (and largest) patch in a series of patches over the next month to extend the
AVD and ADT eclipse plugin to support processor-specific platform images and emulators.  This
patch is intended to co-exist with patches to create x86 emulator environments and overall
SDK support.

There is an overall expectation that the sdk building process will be updated to meet the
following expectations...  It is not in the scope of these UI patches to change the overall
sdk building structure.

expectation #1:
tools/emulator[.exe]     -- ARM
tools/emulator-x86[.exe] -- x86
tools/emulator-foo[.exe] -- an arbitrary additional architecture (extensible)

expectation #2:
platforms/android-XXX/images/arm - location of kernel/images for ARM
platforms/android-XXX/images/x86 - location of kernel/images for x86
platforms/android-XXX/images/foo - location of kernel/images for arbitrary architecture

expectation #3
In the event that add-ons are in the SDK,
add-ons/addon_XXX/images/arm     - location of kernel/images for ARM
add-ons/addon_XXX/images/x86     - location of kernel/images for x86
add-ons/addon_XXX/images/foo     - location of kernel/images for arbitrary architecture

NOTE:  For "earlier"/legacy api levels, it is assumed that it is ARM only and the images will
be in platforms/android-XXX/images and add-ons/addon_XXX/images

When an API level is chosen in AVD, it scans the appropriate API directories and determines
if the image directory is "legacy" or if it has subdirectories.  In the latter case, it
populates the list of potential processors using these directory names (and some
prettyprinting for well known architectures)

tested using "android" command line to start AVD on linux and windows
tested using Eclipse plugin AVD integration on linux and windows
REMINDER: You need to change the directory layout of images and add the right
          emulator-XXX[.exe] to test it

If one uses the "android" command line to create an AVD from the command line, the
processor type is assumed to be arm today.  A future patch will be needed to add
command line processor type selectivity

Change-Id: Ifd7c39bf93c6e926f62407bfed024d2789efb41a

22 files changed:
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AndroidLaunchController.java
sdkmanager/app/.classpath
sdkmanager/app/Android.mk
sdkmanager/app/src/com/android/sdkmanager/Main.java
sdkmanager/app/tests/Android.mk [new file with mode: 0644]
sdkmanager/app/tests/com/android/sdkmanager/AvdManagerTest.java
sdkmanager/app/tests/com/android/sdkmanager/MainTest.java
sdkmanager/libs/sdklib/.classpath
sdkmanager/libs/sdklib/src/com/android/sdklib/AddOnTarget.java
sdkmanager/libs/sdklib/src/com/android/sdklib/IAndroidTarget.java
sdkmanager/libs/sdklib/src/com/android/sdklib/PlatformTarget.java
sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java
sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java
sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java
sdkmanager/libs/sdklib/tests/Android.mk
sdkmanager/libs/sdklib/tests/com/android/sdklib/internal/repository/MockAddonPackage.java
sdkmanager/libs/sdklib/tests/com/android/sdklib/internal/repository/MockPlatformPackage.java
sdkmanager/libs/sdkuilib/.classpath
sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdCreationDialog.java
sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdDetailsDialog.java
sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/widgets/AvdSelector.java

index eb89db1..db5b3d8 100644 (file)
@@ -1148,7 +1148,7 @@ public class AdtPlugin extends AbstractUIPlugin implements ILogger {
         // not meant to be exhaustive.
         String[] filesToCheck = new String[] {
                 osSdkLocation + getOsRelativeAdb(),
-                osSdkLocation + getOsRelativeEmulator()
+                osSdkLocation + getOsRelativeEmulator() + SdkConstants.FN_EMULATOR_EXTENSION
         };
         for (String file : filesToCheck) {
             if (checkFile(file) == false) {
index 6ee74ed..930e8de 100644 (file)
@@ -44,6 +44,7 @@ import com.android.prefs.AndroidLocation.AndroidLocationException;
 import com.android.sdklib.AndroidVersion;
 import com.android.sdklib.IAndroidTarget;
 import com.android.sdklib.NullSdkLog;
+import com.android.sdklib.SdkConstants;
 import com.android.sdklib.internal.avd.AvdManager;
 import com.android.sdklib.internal.avd.AvdManager.AvdInfo;
 import com.android.sdklib.xml.ManifestData;
@@ -1187,7 +1188,10 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
         // build the command line based on the available parameters.
         ArrayList<String> list = new ArrayList<String>();
 
-        list.add(AdtPlugin.getOsAbsoluteEmulator());
+        String path = avdToLaunch.getEmulatorPath(AdtPlugin.getOsSdkFolder());
+
+        list.add(path);
+
         list.add(FLAG_AVD);
         list.add(avdToLaunch.getName());
 
@@ -1661,4 +1665,3 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
         }
     }
 }
-
index 39d2807..50576bb 100644 (file)
@@ -1,13 +1,14 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-       <classpathentry kind="src" path="src"/>
-       <classpathentry kind="src" path="tests"/>
-       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
-       <classpathentry combineaccessrules="false" kind="src" path="/SdkLib"/>
-       <classpathentry combineaccessrules="false" kind="src" path="/AndroidPrefs"/>
-       <classpathentry combineaccessrules="false" kind="src" path="/SdkUiLib"/>
-       <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
-       <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/ANDROID_SWT"/>
-       <classpathentry combineaccessrules="false" kind="src" path="/common"/>
-       <classpathentry kind="output" path="bin"/>
+    <classpathentry excluding="**/Android.mk" kind="src" path="src"/>
+    <classpathentry excluding="**/Android.mk" kind="src" path="tests"/>
+    <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+    <classpathentry combineaccessrules="false" kind="src" path="/SdkLib"/>
+    <classpathentry combineaccessrules="false" kind="src" path="/AndroidPrefs"/>
+    <classpathentry combineaccessrules="false" kind="src" path="/SdkUiLib"/>
+    <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
+    <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/ANDROID_SWT"/>
+    <classpathentry combineaccessrules="false" kind="src" path="/common"/>
+    <classpathentry kind="output" path="bin"/>
 </classpath>
+
index 24ba61f..87e830d 100644 (file)
@@ -1,5 +1,6 @@
 # Copyright 2007 The Android Open Source Project
 #
 SDKMANAGERAPP_LOCAL_DIR := $(call my-dir)
-include $(SDKMANAGERAPP_LOCAL_DIR)/etc/Android.mk
-include $(SDKMANAGERAPP_LOCAL_DIR)/src/Android.mk
+
+# Build all sub-directories
+include $(call all-makefiles-under,$(SDKMANAGERAPP_LOCAL_DIR))
index 027897d..8cb88ae 100644 (file)
@@ -980,16 +980,20 @@ public class Main {
                 oldAvdInfo = avdManager.getAvd(avdName, false /*validAvdOnly*/);
             }
 
+            // NOTE: need to update with command line processor selectivity
+
+            String preferredAbi = SdkConstants.ABI_ARMEABI;
             @SuppressWarnings("unused") // newAvdInfo is never read, yet useful for debugging
             AvdInfo newAvdInfo = avdManager.createAvd(avdFolder,
-                    avdName,
-                    target,
-                    skin,
-                    mSdkCommandLine.getParamSdCard(),
-                    hardwareConfig,
-                    removePrevious,
-                    mSdkCommandLine.getFlagSnapshot(),
-                    mSdkLog);
+                        avdName,
+                        target,
+                        preferredAbi,
+                        skin,
+                        mSdkCommandLine.getParamSdCard(),
+                        hardwareConfig,
+                        removePrevious,
+                        mSdkCommandLine.getFlagSnapshot(),
+                        mSdkLog);
 
         } catch (AndroidLocationException e) {
             errorAndExit(e.getMessage());
diff --git a/sdkmanager/app/tests/Android.mk b/sdkmanager/app/tests/Android.mk
new file mode 100644 (file)
index 0000000..dda405a
--- /dev/null
@@ -0,0 +1,28 @@
+# Copyright (C) 2011 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+#
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+
+include $(CLEAR_VARS)
+
+# Only compile source java files in this lib.
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_MODULE := app-tests
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_JAVA_LIBRARIES := sdkmanager sdklib-tests junit
+
+include $(BUILD_HOST_JAVA_LIBRARY)
index 3260024..cc8d6a4 100644 (file)
@@ -24,6 +24,7 @@ import com.android.sdklib.SdkManager;
 import com.android.sdklib.internal.avd.AvdManager;
 import com.android.sdklib.internal.project.ProjectProperties;
 import com.android.sdklib.mock.MockLog;
+import com.android.sdklib.SdkConstants;
 
 import java.io.File;
 import java.util.Map;
@@ -58,9 +59,9 @@ public class AvdManagerTest extends TestCase {
 
     public void testCreateAvdWithoutSnapshot() {
         mAvdManager.createAvd(
-                mAvdFolder, this.getName(), mTarget, null, null, null, false, false, mLog);
-
-        assertEquals("[P Created AVD '" + this.getName() + "' based on Android 0.0\n]",
+                mAvdFolder, this.getName(), mTarget, SdkConstants.ABI_ARMEABI,
+                null, null, null, false, false, mLog);
+        assertEquals("[P Created AVD '" + this.getName() + "' based on Android 0.0, ARM (armeabi) processor\n]",
                 mLog.toString());
         assertTrue("Expected config.ini in " + mAvdFolder,
                 new File(mAvdFolder, "config.ini").exists());
@@ -78,9 +79,10 @@ public class AvdManagerTest extends TestCase {
 
     public void testCreateAvdWithSnapshot() {
         mAvdManager.createAvd(
-                mAvdFolder, this.getName(), mTarget, null, null, null, false, true, mLog);
+                mAvdFolder, this.getName(), mTarget, SdkConstants.ABI_ARMEABI,
+                null, null, null, false, true, mLog);
 
-        assertEquals("[P Created AVD '" + this.getName() + "' based on Android 0.0\n]",
+        assertEquals("[P Created AVD '" + this.getName() + "' based on Android 0.0, ARM (armeabi) processor\n]",
                 mLog.toString());
         assertTrue("Expected snapshots.img in " + mAvdFolder,
                 new File(mAvdFolder, "snapshots.img").exists());
index 29516e3..e4352ff 100644 (file)
@@ -23,6 +23,7 @@ import com.android.sdklib.IAndroidTarget;
 import com.android.sdklib.SdkManager;
 import com.android.sdklib.internal.avd.AvdManager;
 import com.android.sdklib.mock.MockLog;
+import com.android.sdklib.SdkConstants;
 
 import java.io.File;
 
@@ -68,7 +69,8 @@ public class MainTest extends TestCase {
         Main main = new Main();
         main.setLogger(mLog);
         mAvdManager.createAvd(
-                mAvdFolder, this.getName(), mTarget, null, null, null, false, false, mLog);
+                mAvdFolder, this.getName(), mTarget, SdkConstants.ABI_ARMEABI,
+                null, null, null, false, false, mLog);
         mLog.clear();
         main.displayAvdList(mAvdManager);
         assertEquals(
@@ -85,7 +87,8 @@ public class MainTest extends TestCase {
         Main main = new Main();
         main.setLogger(mLog);
         mAvdManager.createAvd(
-                mAvdFolder, this.getName(), mTarget, null, null, null, false, true, mLog);
+                mAvdFolder, this.getName(), mTarget, SdkConstants.ABI_ARMEABI,
+                null, null, null, false, true, mLog);
         mLog.clear();
         main.displayAvdList(mAvdManager);
         assertEquals(
index f8b23a9..0066c60 100644 (file)
@@ -8,4 +8,4 @@
        <classpathentry kind="var" path="ANDROID_SRC/prebuilt/common/commons-compress/commons-compress-1.0.jar"/>
        <classpathentry combineaccessrules="false" kind="src" path="/common"/>
        <classpathentry kind="output" path="bin"/>
-</classpath>
+</classpath>
\ No newline at end of file
index f3da39c..866d5b6 100644 (file)
@@ -22,6 +22,7 @@ import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.ArrayList;
 
 /**
  * Represents an add-on target in the SDK.
@@ -67,6 +68,7 @@ final class AddOnTarget implements IAndroidTarget {
     private final String mLocation;
     private final PlatformTarget mBasePlatform;
     private final String mName;
+    private String[] mAbis;
     private final String mVendor;
     private final int mRevision;
     private final String mDescription;
@@ -74,6 +76,7 @@ final class AddOnTarget implements IAndroidTarget {
     private String mDefaultSkin;
     private IOptionalLibrary[] mLibraries;
     private int mVendorId = NO_USB_ID;
+    private boolean mAbiCompatibilityMode;
 
     /**
      * Creates a new add-on
@@ -82,12 +85,13 @@ final class AddOnTarget implements IAndroidTarget {
      * @param vendor the vendor name of the add-on
      * @param revision the revision of the add-on
      * @param description the add-on description
+     * @param abis list of supported abis
      * @param libMap A map containing the optional libraries. The map key is the fully-qualified
      * library name. The value is a 2 string array with the .jar filename, and the description.
      * @param basePlatform the platform the add-on is extending.
      */
     AddOnTarget(String location, String name, String vendor, int revision, String description,
-            Map<String, String[]> libMap, PlatformTarget basePlatform) {
+            String[] abis, Map<String, String[]> libMap, PlatformTarget basePlatform) {
         if (location.endsWith(File.separator) == false) {
             location = location + File.separator;
         }
@@ -99,6 +103,14 @@ final class AddOnTarget implements IAndroidTarget {
         mDescription = description;
         mBasePlatform = basePlatform;
 
+        //set compatibility mode
+        if (abis.length > 0) {
+            mAbis = abis;
+        } else {
+            mAbiCompatibilityMode = true;
+            mAbis = new String[] { SdkConstants.ABI_ARMEABI };
+        }
+
         // handle the optional libraries.
         if (libMap != null) {
             mLibraries = new IOptionalLibrary[libMap.size()];
@@ -121,6 +133,25 @@ final class AddOnTarget implements IAndroidTarget {
         return mName;
     }
 
+    /**
+    * Return the full path for images
+    * @param abiType type of the abi
+    * @return complete path where the image files are located
+    */
+    public String getImagePath(String abiType) {
+
+        if (mAbiCompatibilityMode) {
+        // Use legacy directory structure if only arm
+            return mLocation + SdkConstants.OS_IMAGES_FOLDER;
+        } else {
+            return mLocation + SdkConstants.OS_IMAGES_FOLDER + abiType + File.separator;
+          }
+    }
+
+    public String[] getAbiList() {
+        return mAbis;
+    }
+
     public String getVendor() {
         return mVendor;
     }
@@ -160,8 +191,6 @@ final class AddOnTarget implements IAndroidTarget {
 
     public String getPath(int pathId) {
         switch (pathId) {
-            case IMAGES:
-                return mLocation + SdkConstants.OS_IMAGES_FOLDER;
             case SKINS:
                 return mLocation + SdkConstants.OS_SKINS_FOLDER;
             case DOCS:
index c0dcaa7..2ca7763 100644 (file)
@@ -29,8 +29,6 @@ public interface IAndroidTarget extends Comparable<IAndroidTarget> {
     public final static int ANDROID_JAR         = 1;
     /** OS Path to the "framework.aidl" file. */
     public final static int ANDROID_AIDL        = 2;
-    /** OS Path to "images" folder which contains the emulator system images. */
-    public final static int IMAGES              = 3;
     /** OS Path to the "samples" folder which contains sample projects. */
     public final static int SAMPLES             = 4;
     /** OS Path to the "skins" folder which contains the emulator skins. */
@@ -227,6 +225,16 @@ public interface IAndroidTarget extends Comparable<IAndroidTarget> {
     int getUsbVendorId();
 
     /**
+     * Returns array of permitted processor architectures
+     */
+    public String[] getAbiList();
+
+    /**
+     * Returns string to append to images directory for current ProcessorType
+     */
+    public String getImagePath(String abiType);
+
+    /**
      * Returns whether the given target is compatible with the receiver.
      * <p/>
      * This means that a project using the receiver's target can run on the given target.
index 6aeeade..62720e7 100644 (file)
@@ -21,6 +21,7 @@ import com.android.sdklib.util.SparseArray;
 import java.io.File;
 import java.util.Collections;
 import java.util.Map;
+import java.util.ArrayList;
 
 /**
  * Represents a platform target in the SDK.
@@ -43,21 +44,25 @@ final class PlatformTarget implements IAndroidTarget {
     private final Map<String, String> mProperties;
     private final SparseArray<String> mPaths = new SparseArray<String>();
     private String[] mSkins;
+    private String[] mAbis;
+    private boolean mAbiCompatibilityMode;
 
 
     /**
      * Creates a Platform target.
      * @param sdkOsPath the root folder of the SDK
      * @param platformOSPath the root folder of the platform component
-     * @param properties the platform properties
      * @param apiLevel the API Level
      * @param codeName the codename. can be null.
      * @param versionName the version name of the platform.
      * @param revision the revision of the platform component.
+     * @param abis the list of supported abis
+     * @param properties the platform properties
      */
     @SuppressWarnings("deprecation")
-    PlatformTarget(String sdkOsPath, String platformOSPath, Map<String, String> properties,
-            int apiLevel, String codeName, String versionName, int revision) {
+    PlatformTarget(String sdkOsPath, String platformOSPath, int apiLevel,
+            String codeName, String versionName, int revision, String[] abis,
+            Map<String, String> properties) {
         if (platformOSPath.endsWith(File.separator) == false) {
             platformOSPath = platformOSPath + File.separator;
         }
@@ -79,7 +84,6 @@ final class PlatformTarget implements IAndroidTarget {
         mPaths.put(ANDROID_AIDL, mRootFolderOsPath + SdkConstants.FN_FRAMEWORK_AIDL);
         mPaths.put(ANDROID_RS, mRootFolderOsPath + SdkConstants.OS_FRAMEWORK_RS);
         mPaths.put(ANDROID_RS_CLANG, mRootFolderOsPath + SdkConstants.OS_FRAMEWORK_RS_CLANG);
-        mPaths.put(IMAGES, mRootFolderOsPath + SdkConstants.OS_IMAGES_FOLDER);
         mPaths.put(SAMPLES, mRootFolderOsPath + SdkConstants.OS_PLATFORM_SAMPLES_FOLDER);
         mPaths.put(SKINS, mRootFolderOsPath + SdkConstants.OS_SKINS_FOLDER);
         mPaths.put(TEMPLATES, mRootFolderOsPath + SdkConstants.OS_PLATFORM_TEMPLATES_FOLDER);
@@ -112,6 +116,36 @@ final class PlatformTarget implements IAndroidTarget {
                 SdkConstants.FN_DX);
         mPaths.put(DX_JAR, sdkOsPath + SdkConstants.OS_SDK_PLATFORM_TOOLS_LIB_FOLDER +
                 SdkConstants.FN_DX_JAR);
+
+        //set compatibility mode, abis length would be 0 for older APIs
+        if (abis.length > 0) {
+            mAbis = abis;
+        } else {
+            mAbiCompatibilityMode = true;
+            mAbis = new String[] { SdkConstants.ABI_ARMEABI };
+        }
+
+    }
+
+    /**
+     * Return the full path for images
+     * @param abiType type of the abi
+     * @return complete path where the image files are located
+     */
+    public String getImagePath(String abiType) {
+        if (mAbiCompatibilityMode) {
+            // Use legacy directory structure if only arm is supported
+            return mRootFolderOsPath + SdkConstants.OS_IMAGES_FOLDER;
+        } else {
+            return mRootFolderOsPath + SdkConstants.OS_IMAGES_FOLDER + abiType + File.separator;
+        }
+    }
+
+    /**
+     * Retrieve and return the list of abis
+     */
+    public String[] getAbiList() {
+        return mAbis;
     }
 
     public String getLocation() {
index 99af0db..f75d3a9 100644 (file)
@@ -132,9 +132,13 @@ public final class SdkConstants {
     public final static String FN_ADB = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ?
             "adb.exe" : "adb"; //$NON-NLS-1$ //$NON-NLS-2$
 
-    /** emulator executable (with extension for the current OS) */
-    public final static String FN_EMULATOR = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ?
-            "emulator.exe" : "emulator"; //$NON-NLS-1$ //$NON-NLS-2$
+    /** emulator executable (_WITHOUT_ extension for the current OS) */
+    public final static String FN_EMULATOR =
+            "emulator"; //$NON-NLS-1$ //$NON-NLS-2$
+
+    /** emulator executable extension for the current OS */
+    public final static String FN_EMULATOR_EXTENSION = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ?
+            ".exe" : ""; //$NON-NLS-1$ //$NON-NLS-2$
 
     /** zipalign executable (with extension for the current OS)  */
     public final static String FN_ZIPALIGN = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ?
@@ -203,6 +207,10 @@ public final class SdkConstants {
     public static final String FD_DOCS_REFERENCE = "reference";
     /** Name of the SDK images folder. */
     public final static String FD_IMAGES = "images";
+    /** Name of the processors to support. */
+    public final static String ABI_ARMEABI = "armeabi";
+    public final static String ABI_INTEL_ATOM = "x86";
+
     /** Name of the SDK skins folder. */
     public final static String FD_SKINS = "skins";
     /** Name of the SDK samples folder. */
index cb21e3f..d6662c1 100644 (file)
@@ -355,15 +355,17 @@ public class SdkManager {
                     return null;
                 }
 
+                String[] abiList = getAbiList(platformFolder.getAbsolutePath());
                 // create the target.
                 PlatformTarget target = new PlatformTarget(
                         sdkOsPath,
                         platformFolder.getAbsolutePath(),
-                        map,
                         apiNumber,
                         apiCodename,
                         apiName,
-                        revision);
+                        revision,
+                        abiList,
+                        map);
 
                 // need to parse the skins.
                 String[] skins = parseSkinFolder(target.getPath(IAndroidTarget.SKINS));
@@ -380,6 +382,30 @@ public class SdkManager {
         return null;
     }
 
+    /**
+    * Get all the abi types supported for a given target
+    * @param path Path where the images folder for a target is located
+    * @return an array of strings containing all the abi names for the target
+    */
+    private static String[] getAbiList(String path) {
+        ArrayList list = new ArrayList();
+
+        File imagesFolder = new File(path + File.separator + SdkConstants.OS_IMAGES_FOLDER);
+        File[] files = imagesFolder.listFiles();
+
+        if (files != null) {
+            // Loop through Images directory.  If subdirectories exist, set multiprocessor mode
+            for (File file : files) {
+                if (file.isDirectory()) {
+                    list.add(file.getName());
+                }
+            }
+        }
+        String[] abis = new String[list.size()];
+        list.toArray(abis);
+
+        return abis;
+    }
 
     /**
      * Loads the Add-on from the SDK.
@@ -514,8 +540,9 @@ public class SdkManager {
                 }
             }
 
+            String[] abiList = getAbiList(addonDir.getAbsolutePath());
             AddOnTarget target = new AddOnTarget(addonDir.getAbsolutePath(), name, vendor,
-                    revisionValue, description, libMap, baseTarget);
+                    revisionValue, description, abiList, libMap, baseTarget);
 
             // need to parse the skins.
             String[] skins = parseSkinFolder(target.getPath(IAndroidTarget.SKINS));
index cd29c61..116fa4a 100644 (file)
@@ -67,6 +67,13 @@ public final class AvdManager {
     public final static String AVD_INFO_TARGET = "target";     //$NON-NLS-1$
 
     /**
+     * AVD/config.ini key name representing the abi type of the specific avd
+     *
+     */
+     public final static String AVD_INI_ABI_TYPE = "abi.type"; //$NON-NLS-1$
+
+
+    /**
      * AVD/config.ini key name representing the SDK-relative path of the skin folder, if any,
      * or a 320x480 like constant for a numeric skin size.
      *
@@ -204,6 +211,7 @@ public final class AvdManager {
         private final String mPath;
         private final String mTargetHash;
         private final IAndroidTarget mTarget;
+        private final String mAbiType;
         private final Map<String, String> mProperties;
         private final AvdStatus mStatus;
 
@@ -217,11 +225,12 @@ public final class AvdManager {
          * @param path The path to the config.ini file
          * @param targetHash the target hash
          * @param target The target. Can be null, if the target was not resolved.
+         * @param abiType Name of the abi.
          * @param properties The property map. Cannot be null.
          */
         public AvdInfo(String name, String path, String targetHash, IAndroidTarget target,
-                Map<String, String> properties) {
-            this(name, path, targetHash, target, properties, AvdStatus.OK);
+                String abiType, Map<String, String> properties) {
+             this(name, path, targetHash, target, abiType, properties, AvdStatus.OK);
         }
 
         /**
@@ -234,15 +243,17 @@ public final class AvdManager {
          * @param path The path to the config.ini file
          * @param targetHash the target hash
          * @param target The target. Can be null, if the target was not resolved.
+         * @param abiType Name of the abi.
          * @param properties The property map. Can be null.
          * @param status The {@link AvdStatus} of this AVD. Cannot be null.
          */
         public AvdInfo(String name, String path, String targetHash, IAndroidTarget target,
-                Map<String, String> properties, AvdStatus status) {
+                String abiType, Map<String, String> properties, AvdStatus status) {
             mName = name;
             mPath = path;
             mTargetHash = targetHash;
             mTarget = target;
+            mAbiType = abiType;
             mProperties = properties == null ? null : Collections.unmodifiableMap(properties);
             mStatus = status;
         }
@@ -257,6 +268,45 @@ public final class AvdManager {
             return mPath;
         }
 
+        /** Returns the processor type of the AVD. */
+        public String getAbiType() {
+            return mAbiType;
+        }
+
+        /** Convenience function to return a more user friendly name of the abi type. */
+        public static String getPrettyAbiType(String raw) {
+            String s = null;
+            if (raw.equalsIgnoreCase(SdkConstants.ABI_ARMEABI)) {
+                s = "ARM (" + SdkConstants.ABI_ARMEABI + ")";
+            }
+            else if (raw.equalsIgnoreCase(SdkConstants.ABI_INTEL_ATOM)) {
+                s = "Intel Atom (" + SdkConstants.ABI_INTEL_ATOM + ")";
+            }
+            else {
+                s = raw + " (" + raw + ")";
+            }
+            return s;
+        }
+
+        /**
+        * Returns the emulator executable path
+        * @param sdkPath path of the sdk
+        * @return path of the emulator executable
+        */
+        public String getEmulatorPath(String sdkPath) {
+            String path = sdkPath + SdkConstants.OS_SDK_TOOLS_FOLDER;
+
+            // Start with base name of the emulator
+            path = path + SdkConstants.FN_EMULATOR;
+            // If not using ARM, add processor type to emulator command line
+            if (!getAbiType().equalsIgnoreCase(SdkConstants.ABI_ARMEABI)) {
+                path = path + "-" + getAbiType();
+            }
+            // Add OS appropriate emulator extension (e.g., .exe on windows)
+            path = path + SdkConstants.FN_EMULATOR_EXTENSION;
+            return path;
+        }
+
         /**
          * Returns the target hash string.
          */
@@ -588,14 +638,17 @@ public final class AvdManager {
     /**
      * Creates a new AVD, but with no snapshot.
      *
-     * See {@link #createAvd(File, String, IAndroidTarget, String, String, Map, boolean, boolean, ISdkLog)}
+     * See {@link #createAvd(File, String, IAndroidTarget,
+     *                 String, String,
+     *                 Map, boolean, boolean, ISdkLog)}
      **/
     @Deprecated
-    public AvdInfo createAvd(File avdFolder, String name, IAndroidTarget target, String skinName,
+    public AvdInfo createAvd(File avdFolder, String name, IAndroidTarget target,
+            String abiType, String skinName,
             String sdcard, Map<String, String> hardwareConfig, boolean removePrevious,
             ISdkLog log) {
-        return createAvd(avdFolder, name, target, skinName, sdcard, hardwareConfig, removePrevious,
-                false, log);
+       return createAvd(avdFolder, name, target, abiType, skinName, sdcard,
+                hardwareConfig, removePrevious, false, log);
     }
 
     /**
@@ -604,6 +657,7 @@ public final class AvdManager {
      * @param avdFolder the data folder for the AVD. It will be created as needed.
      * @param name the name of the AVD
      * @param target the target of the AVD
+     * @param abiType the abi type of the AVD
      * @param skinName the name of the skin. Can be null. Must have been verified by caller.
      * @param sdcard the parameter value for the sdCard. Can be null. This is either a path to
      *        an existing sdcard image or a sdcard size (\d+, \d+K, \dM).
@@ -615,8 +669,8 @@ public final class AvdManager {
      *         internal list) or null in case of failure.
      */
     public AvdInfo createAvd(File avdFolder, String name, IAndroidTarget target,
-            String skinName, String sdcard, Map<String,String> hardwareConfig,
-            boolean removePrevious, boolean createSnapshot, ISdkLog log) {
+           String abiType, String skinName, String sdcard, Map<String,String> hardwareConfig,
+           boolean removePrevious, boolean createSnapshot, ISdkLog log){
         if (log == null) {
             throw new IllegalArgumentException("log cannot be null");
         }
@@ -649,17 +703,20 @@ public final class AvdManager {
             iniFile = createAvdIniFile(name, avdFolder, target, removePrevious);
 
             // writes the userdata.img in it.
-            String imagePath = target.getPath(IAndroidTarget.IMAGES);
+            String imagePath = target.getImagePath(abiType);
+
             File userdataSrc = new File(imagePath, USERDATA_IMG);
 
             if (userdataSrc.exists() == false && target.isPlatform() == false) {
-                imagePath = target.getParent().getPath(IAndroidTarget.IMAGES);
+                imagePath =
+                    target.getParent().getImagePath(abiType);
                 userdataSrc = new File(imagePath, USERDATA_IMG);
             }
 
             if (userdataSrc.exists() == false) {
-                log.error(null, "Unable to find a '%1$s' file to copy into the AVD folder.",
-                        USERDATA_IMG);
+                log.error(null,
+                        "Unable to find a '%1$s' file of '%2$s' to copy into the AVD folder.",
+                        USERDATA_IMG, imagePath);
                 needCleanup = true;
                 return null;
             }
@@ -667,12 +724,20 @@ public final class AvdManager {
 
             copyImageFile(userdataSrc, userdataDest);
 
+            if (userdataDest.exists() == false) {
+                log.error(null, "Unable to create '%1$s' file in the AVD folder.",
+                        userdataDest);
+                needCleanup = true;
+                return null;
+            }
+
             // Config file.
             HashMap<String, String> values = new HashMap<String, String>();
 
-            if (setImagePathProperties(target, values, log) == false) {
-                needCleanup = true;
-                return null;
+           if (setImagePathProperties(target, abiType, values, log) == false) {
+               log.error(null, "Failed to set image path properties in the AVD folder.");
+               needCleanup = true;
+               return null;
             }
 
             // Create the snapshot file
@@ -681,7 +746,7 @@ public final class AvdManager {
                         + SdkConstants.OS_SDK_TOOLS_LIB_EMULATOR_FOLDER;
                 File snapshotBlank = new File(toolsLib, SNAPSHOTS_IMG);
                 if (snapshotBlank.exists() == false) {
-                    log.error(null, "Unable to find a '%2$s%1$s' file to copy into the AVD folder.",
+                   log.error(null, "Unable to find a '%2$s%1$s' file to copy into the AVD folder.",
                             SNAPSHOTS_IMG, toolsLib);
                     needCleanup = true;
                     return null;
@@ -691,6 +756,9 @@ public final class AvdManager {
                 values.put(AVD_INI_SNAPSHOT_PRESENT, "true");
             }
 
+            // Now the abi type
+            values.put(AVD_INI_ABI_TYPE, abiType);
+
             // Now the skin.
             if (skinName == null || skinName.length() == 0) {
                 skinName = target.getDefaultSkin();
@@ -707,6 +775,7 @@ public final class AvdManager {
                 // assume skin name is valid
                 String skinPath = getSkinRelativePath(skinName, target, log);
                 if (skinPath == null) {
+                    log.error(null, "Missing skinpath in the AVD folder.");
                     needCleanup = true;
                     return null;
                 }
@@ -771,6 +840,7 @@ public final class AvdManager {
                         }
 
                         if (createSdCard(mkSdCard.getAbsolutePath(), sdcard, path, log) == false) {
+                            log.error(null, "Failed to create sdcard in the AVD folder.");
                             needCleanup = true;
                             return null; // mksdcard output has already been displayed, no need to
                                          // output anything else.
@@ -846,6 +916,7 @@ public final class AvdManager {
                 report.append(String.format("Created AVD '%1$s' based on %2$s (%3$s)", name,
                         target.getName(), target.getVendor()));
             }
+            report.append(String.format(", %s processor", AvdInfo.getPrettyAbiType(abiType)));
 
             // display the chosen hardware config
             if (finalHardwareValues.size() > 0) {
@@ -863,7 +934,7 @@ public final class AvdManager {
             AvdInfo newAvdInfo = new AvdInfo(name,
                     avdFolder.getAbsolutePath(),
                     target.hashString(),
-                    target, values);
+                    target, abiType, values);
 
             AvdInfo oldAvdInfo = getAvd(name, false /*validAvdOnly*/);
 
@@ -942,9 +1013,9 @@ public final class AvdManager {
      * is not empty. If the image folder is empty or does not exist, <code>null</code> is returned.
      * @throws InvalidTargetPathException if the target image folder is not in the current SDK.
      */
-    private String getImageRelativePath(IAndroidTarget target)
+    private String getImageRelativePath(IAndroidTarget target, String abiType)
             throws InvalidTargetPathException {
-        String imageFullPath = target.getPath(IAndroidTarget.IMAGES);
+        String imageFullPath = target.getImagePath(abiType);
 
         // make this path relative to the SDK location
         String sdkLocation = mSdkManager.getLocation();
@@ -1166,7 +1237,7 @@ public final class AvdManager {
 
                 // update AVD info
                 AvdInfo info = new AvdInfo(avdInfo.getName(), paramFolderPath,
-                        avdInfo.getTargetHash(), avdInfo.getTarget(), avdInfo.getProperties());
+                      avdInfo.getTargetHash(), avdInfo.getTarget(), avdInfo.getAbiType(), avdInfo.getProperties());
                 replaceAvd(avdInfo, info);
 
                 // update the ini file
@@ -1186,7 +1257,8 @@ public final class AvdManager {
 
                 // update AVD info
                 AvdInfo info = new AvdInfo(newName, avdInfo.getPath(),
-                        avdInfo.getTargetHash(), avdInfo.getTarget(), avdInfo.getProperties());
+                        avdInfo.getTargetHash(), avdInfo.getTarget(),
+                        avdInfo.getAbiType(), avdInfo.getProperties());
                 replaceAvd(avdInfo, info);
             }
 
@@ -1329,6 +1401,14 @@ public final class AvdManager {
             name = matcher.group(1);
         }
 
+        // get abi type
+        String abiType = properties.get(AVD_INI_ABI_TYPE);
+        // for the avds created previously without enhancement, i.e. They are created based
+        // on previous API Levels. They are supposed to have ARM processor type
+        if (abiType == null) {
+            abiType = SdkConstants.ABI_ARMEABI;
+        }
+
         // check the image.sysdir are valid
         boolean validImageSysdir = true;
         if (properties != null) {
@@ -1374,6 +1454,7 @@ public final class AvdManager {
                 avdPath,
                 targetHash,
                 target,
+                abiType,
                 properties,
                 status);
 
@@ -1585,7 +1666,7 @@ public final class AvdManager {
         AvdStatus status;
 
         // create the path to the new system images.
-        if (setImagePathProperties(avd.getTarget(), properties, log)) {
+        if (setImagePathProperties(avd.getTarget(), avd.getAbiType(), properties, log)) {
             if (properties.containsKey(AVD_INI_IMAGES_1)) {
                 log.printf("Updated '%1$s' with value '%2$s'\n", AVD_INI_IMAGES_1,
                         properties.get(AVD_INI_IMAGES_1));
@@ -1617,6 +1698,7 @@ public final class AvdManager {
                 avd.getPath(),
                 avd.getTargetHash(),
                 avd.getTarget(),
+                avd.getAbiType(),
                 properties,
                 status);
 
@@ -1626,13 +1708,14 @@ public final class AvdManager {
     /**
      * Sets the paths to the system images in a properties map.
      * @param target the target in which to find the system images.
+     * @param abiType the abi type of the avd to find
+     *        the architecture-dependent system images.
      * @param properties the properties in which to set the paths.
      * @param log the log object to receive action logs. Cannot be null.
      * @return true if success, false if some path are missing.
      */
     private boolean setImagePathProperties(IAndroidTarget target,
-            Map<String, String> properties,
-            ISdkLog log) {
+        String abiType, Map<String, String> properties, ISdkLog log) {
         properties.remove(AVD_INI_IMAGES_1);
         properties.remove(AVD_INI_IMAGES_2);
 
@@ -1640,7 +1723,7 @@ public final class AvdManager {
             String property = AVD_INI_IMAGES_1;
 
             // First the image folders of the target itself
-            String imagePath = getImageRelativePath(target);
+            String imagePath = getImageRelativePath(target, abiType);
             if (imagePath != null) {
                 properties.put(property, imagePath);
                 property = AVD_INI_IMAGES_2;
@@ -1650,7 +1733,7 @@ public final class AvdManager {
             // If the target is an add-on we need to add the Platform image as a backup.
             IAndroidTarget parent = target.getParent();
             if (parent != null) {
-                imagePath = getImageRelativePath(parent);
+                imagePath = getImageRelativePath(parent, abiType);
                 if (imagePath != null) {
                     properties.put(property, imagePath);
                 }
index 3b26bc0..3b1ddc7 100644 (file)
@@ -19,6 +19,8 @@ include $(CLEAR_VARS)
 # Only compile source java files in this lib.
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
+LOCAL_JAVA_RESOURCE_DIRS := .
+
 LOCAL_MODULE := sdklib-tests
 LOCAL_MODULE_TAGS := optional
 
index e99463b..55ace17 100755 (executable)
@@ -18,6 +18,7 @@ package com.android.sdklib.internal.repository;
 \r
 import com.android.sdklib.AndroidVersion;\r
 import com.android.sdklib.IAndroidTarget;\r
+import com.android.sdklib.SdkConstants;\r
 \r
 import java.util.Map;\r
 \r
@@ -68,6 +69,14 @@ public class MockAddonPackage extends AddonPackage {
             return "mock addon target";\r
         }\r
 \r
+        public String[] getAbiList() {\r
+            return new String[] { SdkConstants.ABI_ARMEABI };\r
+        }\r
+\r
+        public String getImagePath(String abiType) {\r
+            return SdkConstants.OS_IMAGES_FOLDER;\r
+        }\r
+\r
         public String getLocation() {\r
             return "";\r
         }\r
index 0a58487..ad1ab16 100755 (executable)
@@ -18,6 +18,7 @@ package com.android.sdklib.internal.repository;
 \r
 import com.android.sdklib.AndroidVersion;\r
 import com.android.sdklib.IAndroidTarget;\r
+import com.android.sdklib.SdkConstants;\r
 \r
 import java.util.Map;\r
 import java.util.Properties;\r
@@ -100,6 +101,14 @@ public class MockPlatformPackage extends PlatformPackage {
             return "mock platform target";\r
         }\r
 \r
+        public String[] getAbiList() {\r
+            return new String[] { SdkConstants.ABI_ARMEABI };\r
+        }\r
+\r
+        public String getImagePath(String abiType) {\r
+            return SdkConstants.OS_IMAGES_FOLDER;\r
+        }\r
+\r
         public String getLocation() {\r
             return "";\r
         }\r
index 5a0e83d..751e043 100644 (file)
@@ -1,12 +1,13 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-       <classpathentry excluding="**/Android.mk" kind="src" path="src"/>
-       <classpathentry excluding="**/Android.mk" kind="src" path="tests"/>
-       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
-       <classpathentry exported="true" kind="con" path="org.eclipse.jdt.USER_LIBRARY/ANDROID_SWT"/>
-       <classpathentry combineaccessrules="false" kind="src" path="/SdkLib"/>
-       <classpathentry combineaccessrules="false" kind="src" path="/AndroidPrefs"/>
-       <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
-       <classpathentry combineaccessrules="false" kind="src" path="/common"/>
-       <classpathentry kind="output" path="bin"/>
+    <classpathentry excluding="**/Android.mk" kind="src" path="src"/>
+    <classpathentry excluding="**/Android.mk" kind="src" path="tests"/>
+    <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+    <classpathentry exported="true" kind="con" path="org.eclipse.jdt.USER_LIBRARY/ANDROID_SWT"/>
+    <classpathentry combineaccessrules="false" kind="src" path="/SdkLib"/>
+    <classpathentry combineaccessrules="false" kind="src" path="/AndroidPrefs"/>
+    <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
+    <classpathentry combineaccessrules="false" kind="src" path="/common"/>
+    <classpathentry kind="output" path="bin"/>
 </classpath>
+
index 3f42414..db6034a 100644 (file)
@@ -103,6 +103,9 @@ final class AvdCreationDialog extends GridDialog {
     private Text mAvdName;
     private Combo mTargetCombo;
 
+    private Combo mAbiTypeCombo;
+    private String mAbiType;
+
     private Button mSdCardSizeRadio;
     private Text mSdCardSize;
     private Combo mSdCardSizeCombo;
@@ -286,10 +289,29 @@ final class AvdCreationDialog extends GridDialog {
             public void widgetSelected(SelectionEvent e) {
                 super.widgetSelected(e);
                 reloadSkinCombo();
+                reloadAbiTypeCombo();
                 validatePage();
             }
         });
 
+        //ABI group
+        label = new Label(parent, SWT.NONE);
+        label.setText("ABI:");
+        tooltip = "The ABI to use in the virtual device";
+        label.setToolTipText(tooltip);
+
+         mAbiTypeCombo = new Combo(parent, SWT.READ_ONLY | SWT.DROP_DOWN);
+         mAbiTypeCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+         mAbiTypeCombo.setToolTipText(tooltip);
+         mAbiTypeCombo.addSelectionListener(new SelectionAdapter() {
+         @Override
+         public void widgetSelected(SelectionEvent e) {
+                     super.widgetSelected(e);
+                     validatePage();
+                 }
+         });
+         mAbiTypeCombo.setEnabled(false);
+
         // --- sd card group
         label = new Label(parent, SWT.NONE);
         label.setText("SD Card:");
@@ -670,6 +692,21 @@ final class AvdCreationDialog extends GridDialog {
             for (int i = 0;i < n; i++) {
                 if (target.equals(mCurrentTargets.get(mTargetCombo.getItem(i)))) {
                     mTargetCombo.select(i);
+                    reloadAbiTypeCombo();
+                    reloadSkinCombo();
+                    break;
+                }
+            }
+        }
+
+        // select the abi type
+        if (target.getAbiList().length > 0) {
+            mAbiTypeCombo.setEnabled(target.getAbiList().length > 1);
+            String abiType = AvdInfo.getPrettyAbiType(mEditAvdInfo.getAbiType());
+            int n = mAbiTypeCombo.getItemCount();
+            for (int i = 0; i < n; i++) {
+                if (abiType.equals(mAbiTypeCombo.getItem(i))) {
+                    mAbiTypeCombo.select(i);
                     reloadSkinCombo();
                     break;
                 }
@@ -744,6 +781,7 @@ final class AvdCreationDialog extends GridDialog {
         mProperties.putAll(props);
 
         // Cleanup known non-hardware properties
+        mProperties.remove(AvdManager.AVD_INI_ABI_TYPE);
         mProperties.remove(AvdManager.AVD_INI_SKIN_PATH);
         mProperties.remove(AvdManager.AVD_INI_SKIN_NAME);
         mProperties.remove(AvdManager.AVD_INI_SDCARD_SIZE);
@@ -884,6 +922,49 @@ final class AvdCreationDialog extends GridDialog {
     }
 
     /**
+    * Reload all the abi types in the selection list
+    */
+    private void reloadAbiTypeCombo() {
+       String selected = null;
+       boolean found = false;
+
+       int index = mTargetCombo.getSelectionIndex();
+       if (index >= 0) {
+           String targetName = mTargetCombo.getItem(index);
+           IAndroidTarget target = mCurrentTargets.get(targetName);
+           String[] arches = target.getAbiList();
+
+           mAbiTypeCombo.setEnabled(arches.length > 1);
+
+           // If user explicitly selected an ABI before, preserve that option
+           // If user did not explicitly select before (only one option before)
+           // force them to select
+           index = mAbiTypeCombo.getSelectionIndex();
+           if (index >= 0 && mAbiTypeCombo.getItemCount() > 1) {
+               selected = mAbiTypeCombo.getItem(index);
+           }
+
+           mAbiTypeCombo.removeAll();
+
+           int i;
+           for ( i = 0; i < arches.length ; i++ ) {
+               String prettyAbiType = AvdInfo.getPrettyAbiType(arches[i]);
+               mAbiTypeCombo.add(prettyAbiType);
+               if (!found) {
+                   found = prettyAbiType.equals(selected);
+                   if (found) {
+                       mAbiTypeCombo.select(i);
+                   }
+               }
+           }
+
+           if (arches.length == 1) {
+               mAbiTypeCombo.select(0);
+           }
+       }
+    }
+
+    /**
      * Validates the fields, displays errors and warnings.
      * Enables the finish button if there are no errors.
      */
@@ -907,6 +988,16 @@ final class AvdCreationDialog extends GridDialog {
             error = "A target must be selected in order to create an AVD.";
         }
 
+        // validate abi type if the selected target supports multi archs.
+        if (hasAvdName && error == null && mTargetCombo.getSelectionIndex() > 0) {
+            int index = mTargetCombo.getSelectionIndex();
+            String targetName = mTargetCombo.getItem(index);
+            IAndroidTarget target = mCurrentTargets.get(targetName);
+            if (target.getAbiList().length > 1 && mAbiTypeCombo.getSelectionIndex() < 0) {
+               error = "An abi type must be selected in order to create an AVD.";
+            }
+        }
+
         // Validate SDCard path or value
         if (error == null) {
             // get the mode. We only need to check the file since the
@@ -1122,6 +1213,19 @@ final class AvdCreationDialog extends GridDialog {
             return false;
         }
 
+        // get the abi type
+        mAbiType = SdkConstants.ABI_ARMEABI;
+        if (target.getAbiList().length > 0) {
+            int abiIndex = mAbiTypeCombo.getSelectionIndex();
+            if (abiIndex >= 0) {
+                String prettyname = mAbiTypeCombo.getItem(abiIndex);
+                //Extract the abi type
+                int firstIndex = prettyname.indexOf("(");
+                int lastIndex = prettyname.indexOf(")");
+                mAbiType = prettyname.substring(firstIndex+1, lastIndex);
+            }
+        }
+
         // get the SD card data from the UI.
         String sdName = null;
         if (mSdCardSizeRadio.getSelection()) {
@@ -1190,6 +1294,7 @@ final class AvdCreationDialog extends GridDialog {
                 avdFolder,
                 avdName,
                 target,
+                mAbiType,
                 skinName,
                 sdName,
                 mProperties,
index 409c25d..46f3eaf 100644 (file)
@@ -101,6 +101,8 @@ final class AvdDetailsDialog extends Dialog {
 
         if (mAvdInfo != null) {
             displayValue(c, "Name:", mAvdInfo.getName());
+            displayValue(c, "ABI:", AvdInfo.getPrettyAbiType(mAvdInfo.getAbiType()));
+
             displayValue(c, "Path:", mAvdInfo.getPath());
 
             if (mAvdInfo.getStatus() != AvdStatus.OK) {
@@ -135,6 +137,7 @@ final class AvdDetailsDialog extends Dialog {
                     // display other hardware
                     HashMap<String, String> copy = new HashMap<String, String>(properties);
                     // remove stuff we already displayed (or that we don't want to display)
+                    copy.remove(AvdManager.AVD_INI_ABI_TYPE);
                     copy.remove(AvdManager.AVD_INI_SKIN_NAME);
                     copy.remove(AvdManager.AVD_INI_SKIN_PATH);
                     copy.remove(AvdManager.AVD_INI_SDCARD_SIZE);
index 5e26a41..4cf35ec 100644 (file)
@@ -372,8 +372,10 @@ public final class AvdSelector {
         column2.setText("Platform");
         final TableColumn column3 = new TableColumn(mTable, SWT.NONE);
         column3.setText("API Level");
+        final TableColumn column4 = new TableColumn(mTable, SWT.NONE);
+        column4.setText("ABI");
 
-        adjustColumnsWidth(mTable, column0, column1, column2, column3);
+        adjustColumnsWidth(mTable, column0, column1, column2, column3, column4);
         setupSelectionListener(mTable);
         fillTable(mTable);
         setEnabled(true);
@@ -633,16 +635,18 @@ public final class AvdSelector {
             final TableColumn column0,
             final TableColumn column1,
             final TableColumn column2,
-            final TableColumn column3) {
+            final TableColumn column3,
+            final TableColumn column4) {
         // Add a listener to resize the column to the full width of the table
         table.addControlListener(new ControlAdapter() {
             @Override
             public void controlResized(ControlEvent e) {
                 Rectangle r = table.getClientArea();
-                column0.setWidth(r.width * 25 / 100); // 25%
-                column1.setWidth(r.width * 45 / 100); // 45%
+                column0.setWidth(r.width * 20 / 100); // 20%
+                column1.setWidth(r.width * 30 / 100); // 30%
                 column2.setWidth(r.width * 15 / 100); // 15%
                 column3.setWidth(r.width * 15 / 100); // 15%
+                column4.setWidth(r.width * 20 / 100); // 22%
             }
         });
     }
@@ -777,10 +781,12 @@ public final class AvdSelector {
                         item.setText(1, target.getFullName());
                         item.setText(2, target.getVersionName());
                         item.setText(3, target.getVersion().getApiString());
+                        item.setText(4, AvdInfo.getPrettyAbiType(avd.getAbiType()));
                     } else {
                         item.setText(1, "?");
                         item.setText(2, "?");
                         item.setText(3, "?");
+                        item.setText(4, "?");
                     }
                 }
             }
@@ -1025,10 +1031,7 @@ public final class AvdSelector {
         AvdStartDialog dialog = new AvdStartDialog(mTable.getShell(), avdInfo, mOsSdkPath,
                 mController);
         if (dialog.open() == Window.OK) {
-            String path = mOsSdkPath +
-                File.separator +
-                SdkConstants.OS_SDK_TOOLS_FOLDER +
-                SdkConstants.FN_EMULATOR;
+            String path = avdInfo.getEmulatorPath(mOsSdkPath + File.separator);
 
             final String avdName = avdInfo.getName();