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
// 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) {
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;
// 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());
}
}
}
-
<?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>
+
# 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))
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());
--- /dev/null
+# 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)
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;
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());
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());
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;
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(
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(
<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
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.
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;
private String mDefaultSkin;
private IOptionalLibrary[] mLibraries;
private int mVendorId = NO_USB_ID;
+ private boolean mAbiCompatibilityMode;
/**
* Creates a new add-on
* @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;
}
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()];
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;
}
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:
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. */
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.
import java.io.File;
import java.util.Collections;
import java.util.Map;
+import java.util.ArrayList;
/**
* Represents a platform target in the SDK.
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;
}
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);
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() {
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) ?
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. */
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));
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.
}
}
+ 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));
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.
*
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;
* @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);
}
/**
* @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;
}
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.
*/
/**
* 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);
}
/**
* @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).
* 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");
}
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;
}
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
+ 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;
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();
// 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;
}
}
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.
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) {
AvdInfo newAvdInfo = new AvdInfo(name,
avdFolder.getAbsolutePath(),
target.hashString(),
- target, values);
+ target, abiType, values);
AvdInfo oldAvdInfo = getAvd(name, false /*validAvdOnly*/);
* 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();
// 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
// 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);
}
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) {
avdPath,
targetHash,
target,
+ abiType,
properties,
status);
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));
avd.getPath(),
avd.getTargetHash(),
avd.getTarget(),
+ avd.getAbiType(),
properties,
status);
/**
* 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);
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;
// 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);
}
# 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
\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
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
\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
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
<?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>
+
private Text mAvdName;
private Combo mTargetCombo;
+ private Combo mAbiTypeCombo;
+ private String mAbiType;
+
private Button mSdCardSizeRadio;
private Text mSdCardSize;
private Combo mSdCardSizeCombo;
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:");
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;
}
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);
}
/**
+ * 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.
*/
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
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()) {
avdFolder,
avdName,
target,
+ mAbiType,
skinName,
sdName,
mProperties,
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) {
// 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);
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);
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%
}
});
}
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, "?");
}
}
}
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();