Merge "Add suppress-this to Lint View, and preserve tree expansion state"
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/DetailsPage.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/DetailsPage.java
index 1fb64b4..88e7b05 100644
--- a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/DetailsPage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/DetailsPage.java
@@ -50,6 +50,7 @@
private List<IStateDetailsProvider> mStateDetailProviders = Arrays.asList(
new ShaderSourceDetailsProvider(),
+ new ShaderUniformDetailsProvider(),
new TextureImageDetailsProvider());
public DetailsPage(GLTrace trace) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/ShaderUniformDetailsProvider.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/ShaderUniformDetailsProvider.java
new file mode 100644
index 0000000..4111b77
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/views/ShaderUniformDetailsProvider.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+package com.android.ide.eclipse.gltrace.views;
+
+import com.android.ide.eclipse.gldebugger.GLEnum;
+import com.android.ide.eclipse.gltrace.state.GLCompositeProperty;
+import com.android.ide.eclipse.gltrace.state.GLStateType;
+import com.android.ide.eclipse.gltrace.state.IGLProperty;
+import com.google.common.base.Joiner;
+
+import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Text;
+
+import java.util.Collections;
+import java.util.List;
+
+public class ShaderUniformDetailsProvider implements IStateDetailsProvider {
+ private Text mTextControl;
+ private static final Joiner JOINER = Joiner.on(", ");
+
+ @Override
+ public boolean isApplicable(IGLProperty state) {
+ return getShaderUniformProperty(state) != null;
+ }
+
+ @Override
+ public void createControl(Composite parent) {
+ mTextControl = new Text(parent, SWT.BORDER | SWT.READ_ONLY | SWT.MULTI | SWT.WRAP);
+ mTextControl.setEditable(false);
+ }
+
+ @Override
+ public void disposeControl() {
+ }
+
+ @Override
+ public Control getControl() {
+ return mTextControl;
+ }
+
+ @Override
+ public void updateControl(IGLProperty state) {
+ IGLProperty uniform = getShaderUniformProperty(state);
+ if (uniform instanceof GLCompositeProperty) {
+ GLCompositeProperty uniformProperty = (GLCompositeProperty) uniform;
+ IGLProperty nameProperty = uniformProperty.getProperty(GLStateType.UNIFORM_NAME);
+ IGLProperty typeProperty = uniformProperty.getProperty(GLStateType.UNIFORM_TYPE);
+ IGLProperty valueProperty = uniformProperty.getProperty(GLStateType.UNIFORM_VALUE);
+
+ String name = (String) nameProperty.getValue();
+ GLEnum type = (GLEnum) typeProperty.getValue();
+ Object value = valueProperty.getValue();
+ mTextControl.setText(formatUniform(name, type, value));
+ mTextControl.setEnabled(true);
+ } else {
+ mTextControl.setText(""); //$NON-NLS-1$
+ mTextControl.setEnabled(false);
+ }
+ }
+
+ private String formatUniform(String name, GLEnum type, Object value) {
+ String valueText;
+
+ switch (type) {
+ case GL_FLOAT:
+ case GL_FLOAT_VEC2:
+ case GL_FLOAT_VEC3:
+ case GL_FLOAT_VEC4:
+ case GL_INT:
+ case GL_INT_VEC2:
+ case GL_INT_VEC3:
+ case GL_INT_VEC4:
+ case GL_BOOL:
+ case GL_BOOL_VEC2:
+ case GL_BOOL_VEC3:
+ case GL_BOOL_VEC4:
+ valueText = formatVector(value);
+ break;
+ case GL_FLOAT_MAT2:
+ valueText = formatMatrix(2, value);
+ break;
+ case GL_FLOAT_MAT3:
+ valueText = formatMatrix(3, value);
+ break;
+ case GL_FLOAT_MAT4:
+ valueText = formatMatrix(4, value);
+ break;
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_CUBE:
+ default:
+ valueText = value.toString();
+ break;
+ }
+
+ return String.format("%s %s = %s", type, name, valueText); //$NON-NLS-1$
+ }
+
+ private String formatVector(Object value) {
+ if (value instanceof List<?>) {
+ List<?> list = (List<?>) value;
+ StringBuilder sb = new StringBuilder(list.size() * 4);
+ sb.append('[');
+ JOINER.appendTo(sb, list);
+ sb.append(']');
+ return sb.toString();
+ }
+
+ return value.toString();
+ }
+
+ private String formatMatrix(int dimension, Object value) {
+ if (value instanceof List<?>) {
+ List<?> list = (List<?>) value;
+ if (list.size() != dimension * dimension) {
+ // Uniforms can only be square matrices, so this scenario should
+ // not occur.
+ return formatVector(value);
+ }
+
+ StringBuilder sb = new StringBuilder(list.size() * 4);
+ sb.append('[');
+ sb.append('\n');
+ for (int i = 0; i < dimension; i++) {
+ sb.append(" "); //$NON-NLS-1$
+ JOINER.appendTo(sb, list.subList(i * dimension, (i + 1) * dimension));
+ sb.append('\n');
+ }
+ sb.append(']');
+ return sb.toString();
+ }
+
+ return value.toString();
+ }
+
+ /**
+ * Get the {@link GLStateType#PER_UNIFORM_STATE} property given a node in
+ * the state hierarchy.
+ */
+ private IGLProperty getShaderUniformProperty(IGLProperty state) {
+ if (state.getType() == GLStateType.PER_UNIFORM_STATE) {
+ return state;
+ }
+
+ state = state.getParent();
+ if (state != null && state.getType() == GLStateType.PER_UNIFORM_STATE) {
+ return state;
+ }
+
+ return null;
+ }
+
+ @Override
+ public List<IContributionItem> getToolBarItems() {
+ return Collections.emptyList();
+ }
+}
diff --git a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/Category.java b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/Category.java
index 88b3c28..75aaa0b 100644
--- a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/Category.java
+++ b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/Category.java
@@ -163,5 +163,5 @@
public static final Category TYPOGRAPHY = Category.create(USABILITY, "Typography", null, 76);
/** Issues related to messages/strings */
- public static final Category MESSAGES = Category.create(CORRECTNESS, "Messages", null, 40);
+ public static final Category MESSAGES = Category.create(CORRECTNESS, "Messages", null, 95);
}
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java
index d13108a..4f3ed9f 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java
@@ -114,41 +114,45 @@
/** dx.jar file */
public static final String FN_DX_JAR = "dx.jar"; //$NON-NLS-1$
- /** dx executable (with extension for the current OS) */
- public final static String FN_DX = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ?
- "dx.bat" : "dx"; //$NON-NLS-1$ //$NON-NLS-2$
+ /** dx executable (with extension for the current OS) */
+ public final static String FN_DX =
+ "dx" + ext(".bat", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- /** aapt executable (with extension for the current OS) */
- public final static String FN_AAPT = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ?
- "aapt.exe" : "aapt"; //$NON-NLS-1$ //$NON-NLS-2$
+ /** aapt executable (with extension for the current OS) */
+ public final static String FN_AAPT =
+ "aapt" + ext(".exe", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- /** aidl executable (with extension for the current OS) */
- public final static String FN_AIDL = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ?
- "aidl.exe" : "aidl"; //$NON-NLS-1$ //$NON-NLS-2$
+ /** aidl executable (with extension for the current OS) */
+ public final static String FN_AIDL =
+ "aidl" + ext(".exe", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- /** renderscript executable (with extension for the current OS) */
- public final static String FN_RENDERSCRIPT = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ?
- "llvm-rs-cc.exe" : "llvm-rs-cc"; //$NON-NLS-1$ //$NON-NLS-2$
+ /** renderscript executable (with extension for the current OS) */
+ public final static String FN_RENDERSCRIPT =
+ "llvm-rs-cc" + ext(".exe", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- /** adb executable (with extension for the current OS) */
- public final static String FN_ADB = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ?
- "adb.exe" : "adb"; //$NON-NLS-1$ //$NON-NLS-2$
+ /** adb executable (with extension for the current OS) */
+ public final static String FN_ADB =
+ "adb" + ext(".exe", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
/** emulator executable for the current OS */
- public final static String FN_EMULATOR = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ?
- "emulator.exe" : "emulator"; //$NON-NLS-1$ //$NON-NLS-2$
+ public final static String FN_EMULATOR =
+ "emulator" + ext(".exe", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- /** zipalign executable (with extension for the current OS) */
- public final static String FN_ZIPALIGN = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ?
- "zipalign.exe" : "zipalign"; //$NON-NLS-1$ //$NON-NLS-2$
+ /** zipalign executable (with extension for the current OS) */
+ public final static String FN_ZIPALIGN =
+ "zipalign" + ext(".exe", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- /** dexdump executable (with extension for the current OS) */
- public final static String FN_DEXDUMP = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ?
- "dexdump.exe" : "dexdump"; //$NON-NLS-1$ //$NON-NLS-2$
+ /** dexdump executable (with extension for the current OS) */
+ public final static String FN_DEXDUMP =
+ "dexdump" + ext(".exe", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- /** zipalign executable (with extension for the current OS) */
- public final static String FN_PROGUARD = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ?
- "proguard.bat" : "proguard.sh"; //$NON-NLS-1$ //$NON-NLS-2$
+ /** proguard executable (with extension for the current OS) */
+ public final static String FN_PROGUARD =
+ "proguard" + ext(".bat", ".sh"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ /** find_lock for Windows (with extension for the current OS) */
+ public final static String FN_FIND_LOCK =
+ "find_lock" + ext(".exe", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
/** properties file for SDK Updater packages */
public final static String FN_SOURCE_PROP = "source.properties"; //$NON-NLS-1$
@@ -476,4 +480,12 @@
return "Other";
}
+
+ private static String ext(String windowsExtension, String nonWindowsExtension) {
+ if (CURRENT_PLATFORM == PLATFORM_WINDOWS) {
+ return windowsExtension;
+ } else {
+ return nonWindowsExtension;
+ }
+ }
}
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/AddonPackage.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/AddonPackage.java
index 6ce1118..a784b34 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/AddonPackage.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/AddonPackage.java
@@ -26,6 +26,7 @@
import com.android.sdklib.internal.repository.Archive.Arch;
import com.android.sdklib.internal.repository.Archive.Os;
import com.android.sdklib.repository.PkgProps;
+import com.android.sdklib.repository.SdkAddonConstants;
import com.android.sdklib.repository.SdkRepoConstants;
import com.android.util.Pair;
@@ -44,8 +45,10 @@
public class AddonPackage extends Package
implements IPackageVersion, IPlatformDependency, IExactApiLevelDependency, ILayoutlibVersion {
- private final String mVendor;
- private final String mName;
+ private final String mVendorId;
+ private final String mVendorDisplay;
+ private final String mNameId;
+ private final String mDisplayName;
private final AndroidVersion mVersion;
/**
@@ -122,14 +125,74 @@
* parameters that vary according to the originating XML schema.
* @param licenses The licenses loaded from the XML originating document.
*/
- AddonPackage(SdkSource source, Node packageNode, String nsUri, Map<String,String> licenses) {
+ AddonPackage(
+ SdkSource source,
+ Node packageNode,
+ String nsUri,
+ Map<String,String> licenses) {
super(source, packageNode, nsUri, licenses);
- mVendor = XmlParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_VENDOR);
- mName = XmlParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_NAME);
- int apiLevel = XmlParserUtils.getXmlInt (packageNode, SdkRepoConstants.NODE_API_LEVEL, 0);
+
+ // --- name id/display ---
+ // addon-4.xsd introduces the name-id, name-display, vendor-id and vendor-display.
+ // These are not optional but we still need to support a fallback for older addons
+ // that only provide name and vendor. If the addon provides neither set of fields,
+ // it will simply not work as expected.
+
+ String nameId = XmlParserUtils.getXmlString(packageNode,
+ SdkRepoConstants.NODE_NAME_ID);
+ String nameDisp = XmlParserUtils.getXmlString(packageNode,
+ SdkRepoConstants.NODE_NAME_DISPLAY);
+ String name = XmlParserUtils.getXmlString(packageNode,
+ SdkRepoConstants.NODE_NAME);
+
+ // The old <name> is equivalent to the new <name-display>
+ if (nameDisp.length() == 0) {
+ nameDisp = name;
+ }
+
+ // For a missing id, we simply use a sanitized version of the display name
+ if (nameId.length() == 0) {
+ nameId = sanitizeDisplayToNameId(name.length() > 0 ? name : nameDisp);
+ }
+
+ assert nameId.length() > 0;
+ assert nameDisp.length() > 0;
+
+ mNameId = nameId.trim();
+ mDisplayName = nameDisp.trim();
+
+ // --- vendor id/display ---
+ // Same processing for vendor id vs display
+
+ String vendorId = XmlParserUtils.getXmlString(packageNode,
+ SdkAddonConstants.NODE_VENDOR_ID);
+ String vendorDisp = XmlParserUtils.getXmlString(packageNode,
+ SdkAddonConstants.NODE_VENDOR_DISPLAY);
+ String vendor = XmlParserUtils.getXmlString(packageNode,
+ SdkAddonConstants.NODE_VENDOR);
+
+ // The old <vendor> is equivalent to the new <vendor-display>
+ if (vendorDisp.length() == 0) {
+ vendorDisp = vendor;
+ }
+
+ // For a missing id, we simply use a sanitized version of the display vendor
+ if (vendorId.length() == 0) {
+ vendorId = sanitizeDisplayToNameId(vendor.length() > 0 ? vendor : vendorDisp);
+ }
+
+ assert vendorId.length() > 0;
+ assert vendorDisp.length() > 0;
+
+ mVendorId = vendorId.trim();
+ mVendorDisplay = vendorDisp.trim();
+
+ // --- other attributes
+
+ int apiLevel = XmlParserUtils.getXmlInt(packageNode, SdkAddonConstants.NODE_API_LEVEL, 0);
mVersion = new AndroidVersion(apiLevel, null /*codeName*/);
- mLibs = parseLibs(XmlParserUtils.getFirstChild(packageNode, SdkRepoConstants.NODE_LIBS));
+ mLibs = parseLibs(XmlParserUtils.getFirstChild(packageNode, SdkAddonConstants.NODE_LIBS));
mLayoutlibVersion = new LayoutlibVersionMixin(packageNode);
}
@@ -164,9 +227,58 @@
target.getLocation() //archiveOsPath
);
+ // --- name id/display ---
+ // addon-4.xsd introduces the name-id, name-display, vendor-id and vendor-display.
+ // These are not optional but we still need to support a fallback for older addons
+ // that only provide name and vendor. If the addon provides neither set of fields,
+ // it will simply not work as expected.
+
+ String nameId = getProperty(props, PkgProps.ADDON_NAME_ID, ""); //$NON-NLS-1$
+ String nameDisp = getProperty(props, PkgProps.ADDON_NAME_DISPLAY, ""); //$NON-NLS-1$
+ String name = getProperty(props, PkgProps.ADDON_NAME, target.getName());
+
+ // The old <name> is equivalent to the new <name-display>
+ if (nameDisp.length() == 0) {
+ nameDisp = name;
+ }
+
+ // For a missing id, we simply use a sanitized version of the display name
+ if (nameId.length() == 0) {
+ nameId = sanitizeDisplayToNameId(name.length() > 0 ? name : nameDisp);
+ }
+
+ assert nameId.length() > 0;
+ assert nameDisp.length() > 0;
+
+ mNameId = nameId.trim();
+ mDisplayName = nameDisp.trim();
+
+ // --- vendor id/display ---
+ // Same processing for vendor id vs display
+
+ String vendorId = getProperty(props, PkgProps.ADDON_VENDOR_ID, ""); //$NON-NLS-1$
+ String vendorDisp = getProperty(props, PkgProps.ADDON_VENDOR_DISPLAY, ""); //$NON-NLS-1$
+ String vendor = getProperty(props, PkgProps.ADDON_VENDOR, target.getVendor());
+
+ // The old <vendor> is equivalent to the new <vendor-display>
+ if (vendorDisp.length() == 0) {
+ vendorDisp = vendor;
+ }
+
+ // For a missing id, we simply use a sanitized version of the display vendor
+ if (vendorId.length() == 0) {
+ vendorId = sanitizeDisplayToNameId(vendor.length() > 0 ? vendor : vendorDisp);
+ }
+
+ assert vendorId.length() > 0;
+ assert vendorDisp.length() > 0;
+
+ mVendorId = vendorId.trim();
+ mVendorDisplay = vendorDisp.trim();
+
+ // --- other attributes
+
mVersion = target.getVersion();
- mName = target.getName();
- mVendor = target.getVendor();
mLayoutlibVersion = new LayoutlibVersionMixin(props);
IOptionalLibrary[] optLibs = target.getOptionalLibraries();
@@ -184,14 +296,27 @@
* Creates a broken addon which we know failed to load properly.
*
* @param archiveOsPath The absolute OS path of the addon folder.
- * @param props The properties parsed from the addon manifest (not the source.properties).
+ * @param sourceProps The properties parsed from the addon's source.properties. Can be null.
+ * @param addonProps The properties parsed from the addon manifest (NOT the source.properties).
* @param error The error indicating why this addon failed to be loaded.
*/
- static Package createBroken(String archiveOsPath, Map<String, String> props, String error) {
- String name = props.get(SdkManager.ADDON_NAME);
- String vendor = props.get(SdkManager.ADDON_VENDOR);
- String api = props.get(SdkManager.ADDON_API);
- String revision = props.get(SdkManager.ADDON_REVISION);
+ static Package createBroken(
+ String archiveOsPath,
+ Properties sourceProps,
+ Map<String, String> addonProps,
+ String error) {
+ String name = getProperty(sourceProps,
+ PkgProps.ADDON_NAME_DISPLAY,
+ getProperty(sourceProps,
+ PkgProps.ADDON_NAME,
+ addonProps.get(SdkManager.ADDON_NAME)));
+ String vendor = getProperty(sourceProps,
+ PkgProps.ADDON_VENDOR_DISPLAY,
+ getProperty(sourceProps,
+ PkgProps.ADDON_VENDOR,
+ addonProps.get(SdkManager.ADDON_VENDOR)));
+ String api = addonProps.get(SdkManager.ADDON_API);
+ String revision = addonProps.get(SdkManager.ADDON_REVISION);
String shortDesc = String.format("%1$s by %2$s, Android API %3$s, revision %4$s [*]",
name,
@@ -235,12 +360,10 @@
mVersion.saveProperties(props);
mLayoutlibVersion.saveProperties(props);
- if (mName != null) {
- props.setProperty(PkgProps.ADDON_NAME, mName);
- }
- if (mVendor != null) {
- props.setProperty(PkgProps.ADDON_VENDOR, mVendor);
- }
+ props.setProperty(PkgProps.ADDON_NAME_ID, mNameId);
+ props.setProperty(PkgProps.ADDON_NAME_DISPLAY, mDisplayName);
+ props.setProperty(PkgProps.ADDON_VENDOR_ID, mVendorId);
+ props.setProperty(PkgProps.ADDON_VENDOR_DISPLAY, mVendorDisplay);
}
/**
@@ -274,14 +397,24 @@
XmlParserUtils.getXmlString(libNode, SdkRepoConstants.NODE_DESCRIPTION));
}
- /** Returns the vendor, a string, for add-on packages. */
- public String getVendor() {
- return mVendor;
+ /** Returns the vendor id, a string, for add-on packages. */
+ public String getVendorId() {
+ return mVendorId;
}
- /** Returns the name, a string, for add-on packages or for libraries. */
- public String getName() {
- return mName;
+ /** Returns the vendor, a string for display purposes. */
+ public String getDisplayVendor() {
+ return mVendorDisplay;
+ }
+
+ /** Returns the name id, a string, for add-on packages or for libraries. */
+ public String getNameId() {
+ return mNameId;
+ }
+
+ /** Returns the name, a string for display purposes. */
+ public String getDisplayName() {
+ return mDisplayName;
}
/**
@@ -334,9 +467,8 @@
*/
@Override
public String getListDescription() {
- return String.format("%1$s by %2$s%3$s",
- getName(),
- getVendor(),
+ return String.format("%1$s%2$s",
+ getDisplayName(),
isObsolete() ? " (Obsolete)" : "");
}
@@ -345,9 +477,8 @@
*/
@Override
public String getShortDescription() {
- return String.format("%1$s by %2$s, Android API %3$s, revision %4$s%5$s",
- getName(),
- getVendor(),
+ return String.format("%1$s, Android API %2$s, revision %3$s%4$s",
+ getDisplayName(),
mVersion.getApiString(),
getRevision(),
isObsolete() ? " (Obsolete)" : "");
@@ -361,15 +492,16 @@
*/
@Override
public String getLongDescription() {
- String s = getDescription();
- if (s == null || s.length() == 0) {
- s = getShortDescription();
- }
+ String s = String.format("%1$s, Android API %2$s, revision %3$s%4$s\nBy %5$s",
+ getDisplayName(),
+ mVersion.getApiString(),
+ getRevision(),
+ isObsolete() ? " (Obsolete)" : "", //$NON-NLS-2$
+ getDisplayVendor());
- if (s.indexOf("revision") == -1) {
- s += String.format("\nRevision %1$d%2$s",
- getRevision(),
- isObsolete() ? " (Obsolete)" : "");
+ String d = getDescription();
+ if (d != null && d.length() > 0) {
+ s += '\n' + d;
}
s += String.format("\nRequires SDK Platform Android API %1$s",
@@ -396,11 +528,17 @@
// First find if this add-on is already installed. If so, reuse the same directory.
for (IAndroidTarget target : sdkManager.getTargets()) {
- if (!target.isPlatform() &&
- target.getVersion().equals(mVersion) &&
- target.getName().equals(getName()) &&
- target.getVendor().equals(getVendor())) {
- return new File(target.getLocation());
+ if (!target.isPlatform() && target.getVersion().equals(mVersion)) {
+ // Starting with addon-4.xsd, the addon source.properties differentiate
+ // between ids and display strings. However the addon target which relies
+ // on the manifest.ini does not so we need to cover both cases.
+ // TODO fix when we get rid of manifest.ini for addons
+ if ((target.getName().equals(getNameId()) &&
+ target.getVendor().equals(getVendorId())) ||
+ (target.getName().equals(getDisplayName()) &&
+ target.getVendor().equals(getDisplayVendor()))) {
+ return new File(target.getLocation());
+ }
}
}
@@ -421,21 +559,35 @@
private String encodeAddonName() {
String name = String.format("addon-%s-%s-%s", //$NON-NLS-1$
- getName(), getVendor(), mVersion.getApiString());
+ getNameId(), getVendorId(), mVersion.getApiString());
name = name.toLowerCase(Locale.US);
name = name.replaceAll("[^a-z0-9_-]+", "_"); //$NON-NLS-1$ //$NON-NLS-2$
name = name.replaceAll("_+", "_"); //$NON-NLS-1$ //$NON-NLS-2$
return name;
}
+ /**
+ * Computes a sanitized name-id based on an addon name-display.
+ * This is used to provide compatibility with older addons that lacks the new fields.
+ *
+ * @param displayName A name-display field or a old-style name field.
+ * @return A non-null sanitized name-id that fits in the {@code [a-zA-Z0-9_-]+} pattern.
+ */
+ private String sanitizeDisplayToNameId(String displayName) {
+ String name = displayName.toLowerCase(Locale.US);
+ name = name.replaceAll("[^a-z0-9_-]+", "_"); //$NON-NLS-1$ //$NON-NLS-2$
+ name = name.replaceAll("_+", "_"); //$NON-NLS-1$ //$NON-NLS-2$
+ return name;
+ }
+
@Override
public boolean sameItemAs(Package pkg) {
if (pkg instanceof AddonPackage) {
AddonPackage newPkg = (AddonPackage)pkg;
// check they are the same add-on.
- return getName().equals(newPkg.getName()) &&
- getVendor().equals(newPkg.getVendor()) &&
+ return getNameId().equals(newPkg.getNameId()) &&
+ getVendorId().equals(newPkg.getVendorId()) &&
getVersion().equals(newPkg.getVersion());
}
@@ -448,8 +600,8 @@
int result = super.hashCode();
result = prime * result + ((mLayoutlibVersion == null) ? 0 : mLayoutlibVersion.hashCode());
result = prime * result + Arrays.hashCode(mLibs);
- result = prime * result + ((mName == null) ? 0 : mName.hashCode());
- result = prime * result + ((mVendor == null) ? 0 : mVendor.hashCode());
+ result = prime * result + ((mDisplayName == null) ? 0 : mDisplayName.hashCode());
+ result = prime * result + ((mVendorDisplay == null) ? 0 : mVendorDisplay.hashCode());
result = prime * result + ((mVersion == null) ? 0 : mVersion.hashCode());
return result;
}
@@ -476,18 +628,18 @@
if (!Arrays.equals(mLibs, other.mLibs)) {
return false;
}
- if (mName == null) {
- if (other.mName != null) {
+ if (mNameId == null) {
+ if (other.mNameId != null) {
return false;
}
- } else if (!mName.equals(other.mName)) {
+ } else if (!mNameId.equals(other.mNameId)) {
return false;
}
- if (mVendor == null) {
- if (other.mVendor != null) {
+ if (mVendorId == null) {
+ if (other.mVendorId != null) {
return false;
}
- } else if (!mVendor.equals(other.mVendor)) {
+ } else if (!mVendorId.equals(other.mVendorId)) {
return false;
}
if (mVersion == null) {
@@ -512,8 +664,8 @@
int pos = s.indexOf("|r:"); //$NON-NLS-1$
assert pos > 0;
s = s.substring(0, pos) +
- "|ve:" + getVendor() + //$NON-NLS-1$
- "|na:" + getName() + //$NON-NLS-1$
+ "|vid:" + getVendorId() + //$NON-NLS-1$
+ "|nid:" + getNameId() + //$NON-NLS-1$
s.substring(pos);
return s;
}
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Archive.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Archive.java
index 4fa7c38..617ba42 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Archive.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Archive.java
@@ -354,6 +354,13 @@
*/
@Override
public String getLongDescription() {
+ return String.format("%1$s\n%2$s\n%3$s",
+ getShortDescription(),
+ getSizeDescription(),
+ getSha1Description());
+ }
+
+ public String getSizeDescription() {
long size = getSize();
String sizeStr;
if (size < 1024) {
@@ -368,8 +375,11 @@
Math.round(10.0 * size / (1024 * 1024 * 1024.0))/ 10.0);
}
- return String.format("%1$s\nSize: %2$s\nSHA1: %3$s",
- getShortDescription(), sizeStr, getChecksum());
+ return String.format("Size: %1$s", sizeStr);
+ }
+
+ public String getSha1Description() {
+ return String.format("SHA1: %1$s", getChecksum());
}
/**
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ArchiveInstaller.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ArchiveInstaller.java
index 9046e63..9e50430 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ArchiveInstaller.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ArchiveInstaller.java
@@ -23,6 +23,8 @@
import com.android.sdklib.io.FileOp;
import com.android.sdklib.io.IFileOp;
import com.android.sdklib.repository.RepoConstants;
+import com.android.sdklib.util.GrabProcessOutput;
+import com.android.sdklib.util.GrabProcessOutput.IProcessOutput;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipFile;
@@ -37,10 +39,13 @@
import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
+import java.util.TreeSet;
+import java.util.regex.Pattern;
/**
* Performs the work of installing a given {@link Archive}.
@@ -98,13 +103,6 @@
File archiveFile = null;
String name = pkg.getShortDescription();
- if (pkg instanceof ExtraPackage && !((ExtraPackage) pkg).isPathValid()) {
- monitor.log("Skipping %1$s: %2$s is not a valid install path.",
- name,
- ((ExtraPackage) pkg).getPath());
- return false;
- }
-
if (newArchive.isLocal()) {
// This should never happen.
monitor.log("Skipping already installed archive: %1$s for %2$s",
@@ -503,18 +501,11 @@
destFolder.getPath(), oldDestFolder.getPath());
if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_WINDOWS) {
- String msg = String.format(
- "-= Warning ! =-\n" +
- "A folder failed to be moved. On Windows this " +
- "typically means that a program is using that folder (for " +
- "example Windows Explorer or your anti-virus software.)\n" +
- "Please momentarily deactivate your anti-virus software or " +
- "close any running programs that may be accessing the " +
- "directory '%1$s'.\n" +
- "When ready, press YES to try again.",
- destFolder.getPath());
+ boolean tryAgain = true;
- if (monitor.displayPrompt("SDK Manager: failed to install", msg)) {
+ tryAgain = windowsDestDirLocked(osSdkRoot, destFolder, monitor);
+
+ if (tryAgain) {
// loop, trying to rename the temp dir into the destination
continue;
} else {
@@ -586,6 +577,93 @@
}
}
+ private boolean windowsDestDirLocked(
+ String osSdkRoot,
+ File destFolder,
+ final ITaskMonitor monitor) {
+ String msg = null;
+
+ assert SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_WINDOWS;
+
+ File findLockExe = FileOp.append(
+ osSdkRoot, SdkConstants.FD_TOOLS, SdkConstants.FD_LIB, SdkConstants.FN_FIND_LOCK);
+
+ if (mFileOp.exists(findLockExe)) {
+ try {
+ final StringBuilder result = new StringBuilder();
+ String command[] = new String[] {
+ findLockExe.getAbsolutePath(),
+ destFolder.getAbsolutePath()
+ };
+ Process process = Runtime.getRuntime().exec(command);
+ int retCode = GrabProcessOutput.grabProcessOutput(
+ process,
+ true /*waitForReaders*/,
+ new IProcessOutput() {
+ @Override
+ public void out(String line) {
+ if (line != null) {
+ result.append(line).append("\n");
+ }
+ }
+
+ @Override
+ public void err(String line) {
+ if (line != null) {
+ monitor.logError("[find_lock] Error: %1$s", line);
+ }
+ }
+ });
+
+ if (retCode == 0 && result.length() > 0) {
+ // TODO create a better dialog
+
+ String found = result.toString().trim();
+ monitor.logError("[find_lock] Directory locked by %1$s", found);
+
+ TreeSet<String> apps = new TreeSet<String>(Arrays.asList(
+ found.split(Pattern.quote(";")))); //$NON-NLS-1$
+ StringBuilder appStr = new StringBuilder();
+ for (String app : apps) {
+ appStr.append("\n - ").append(app.trim()); //$NON-NLS-1$
+ }
+
+ msg = String.format(
+ "-= Warning ! =-\n" +
+ "The following processes: %1$s\n" +
+ "are locking the following directory: \n" +
+ " %2$s\n" +
+ "Please close these applications so that the installation can continue.\n" +
+ "When ready, press YES to try again.",
+ appStr.toString(),
+ destFolder.getPath());
+ }
+
+ } catch (Exception e) {
+ monitor.error(e, "[find_lock failed]");
+ }
+
+
+ }
+
+ if (msg == null) {
+ // Old way: simply display a generic text and let user figure it out.
+ msg = String.format(
+ "-= Warning ! =-\n" +
+ "A folder failed to be moved. On Windows this " +
+ "typically means that a program is using that folder (for " +
+ "example Windows Explorer or your anti-virus software.)\n" +
+ "Please momentarily deactivate your anti-virus software or " +
+ "close any running programs that may be accessing the " +
+ "directory '%1$s'.\n" +
+ "When ready, press YES to try again.",
+ destFolder.getPath());
+ }
+
+ boolean tryAgain = monitor.displayPrompt("SDK Manager: failed to install", msg);
+ return tryAgain;
+ }
+
/**
* Tries to rename/move a folder.
* <p/>
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ExtraPackage.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ExtraPackage.java
index 4bcaa6d..a242c26 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ExtraPackage.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ExtraPackage.java
@@ -16,6 +16,7 @@
package com.android.sdklib.internal.repository;
+import com.android.annotations.Nullable;
import com.android.annotations.VisibleForTesting;
import com.android.annotations.VisibleForTesting.Visibility;
import com.android.sdklib.NullSdkLog;
@@ -42,18 +43,22 @@
implements IMinApiLevelDependency {
/**
- * The vendor folder name. It must be a non-empty single-segment path.
- * <p/>
- * The paths "add-ons", "platforms", "platform-tools", "tools" and "docs" are reserved and
- * cannot be used.
- * This limitation cannot be written in the XML Schema and must be enforced here by using
- * the method {@link #isPathValid()} *before* installing the package.
+ * The extra display name. Used in the UI to represent the package. It can be anything.
*/
- private final String mVendor;
+ private final String mDisplayName;
/**
- * The sub-folder name. It must be a non-empty single-segment path and has the same
- * rules as {@link #mVendor}.
+ * The vendor id name. It is a simple alphanumeric string [a-zA-Z0-9_-].
+ */
+ private final String mVendorId;
+
+ /**
+ * The vendor display name. Used in the UI to represent the vendor. It can be anything.
+ */
+ private final String mVendorDisplay;
+
+ /**
+ * The sub-folder name. It must be a non-empty single-segment path.
*/
private final String mPath;
@@ -85,14 +90,49 @@
* parameters that vary according to the originating XML schema.
* @param licenses The licenses loaded from the XML originating document.
*/
- ExtraPackage(SdkSource source, Node packageNode, String nsUri, Map<String,String> licenses) {
+ ExtraPackage(
+ SdkSource source,
+ Node packageNode,
+ String nsUri,
+ Map<String,String> licenses) {
super(source, packageNode, nsUri, licenses);
mPath = XmlParserUtils.getXmlString(packageNode, RepoConstants.NODE_PATH);
- mVendor = XmlParserUtils.getXmlString(packageNode, RepoConstants.NODE_VENDOR);
- mMinApiLevel = XmlParserUtils.getXmlInt(packageNode, RepoConstants.NODE_MIN_API_LEVEL,
- MIN_API_LEVEL_NOT_SPECIFIED);
+ // Read name-display, vendor-display and vendor-id, introduced in addon-4.xsd.
+ // These are not optional, they are mandatory in addon-4 but we still treat them
+ // as optional so that we can fallback on using <vendor> which was the only one
+ // defined in addon-3.xsd.
+ String name = XmlParserUtils.getXmlString(packageNode, RepoConstants.NODE_NAME_DISPLAY);
+ String vname = XmlParserUtils.getXmlString(packageNode, RepoConstants.NODE_VENDOR_DISPLAY);
+ String vid = XmlParserUtils.getXmlString(packageNode, RepoConstants.NODE_VENDOR_ID);
+
+ if (vid.length() == 0) {
+ // If vid is missing, use the old <vendor> attribute.
+ // Note that in a valid XML, vendor-id cannot be an empty string.
+ // The only reason vid can be empty is when <vendor-id> is missing, which
+ // happens in an addon-3 schema, in which case the old <vendor> needs to be used.
+ String vendor = XmlParserUtils.getXmlString(packageNode, RepoConstants.NODE_VENDOR);
+ vid = sanitizeLegacyVendor(vendor);
+ if (vname.length() == 0) {
+ vname = vendor;
+ }
+ }
+ if (vname.length() == 0) {
+ // The vendor-display name can be empty, in which case we use the vendor-id.
+ vname = vid;
+ }
+ mVendorDisplay = vname.trim();
+ mVendorId = vid.trim();
+
+ if (name.length() == 0) {
+ // If name is missing, use the <path> attribute as done in an addon-3 schema.
+ name = getPrettyName();
+ }
+ mDisplayName = name.trim();
+
+ mMinApiLevel = XmlParserUtils.getXmlInt(
+ packageNode, RepoConstants.NODE_MIN_API_LEVEL, MIN_API_LEVEL_NOT_SPECIFIED);
mProjectFiles = parseProjectFiles(
XmlParserUtils.getFirstChild(packageNode, RepoConstants.NODE_PROJECT_FILES));
@@ -146,30 +186,18 @@
String archiveOsPath) {
ExtraPackage ep = new ExtraPackage(source, props, vendor, path, revision, license,
description, descUrl, archiveOs, archiveArch, archiveOsPath);
-
- if (ep.isPathValid()) {
- return ep;
- } else {
- String shortDesc = ep.getShortDescription() + " [*]"; //$NON-NLS-1$
-
- String longDesc = String.format(
- "Broken Extra Package: %1$s\n" +
- "[*] Package cannot be used due to error: Invalid install path %2$s",
- description,
- ep.getPath());
-
- BrokenPackage ba = new BrokenPackage(props, shortDesc, longDesc,
- ep.getMinApiLevel(),
- IExactApiLevelDependency.API_LEVEL_INVALID,
- archiveOsPath);
- return ba;
- }
+ return ep;
}
+ /**
+ * Constructor used to create a mock {@link ExtraPackage}.
+ * Most of the attributes here are optional.
+ * When not defined, they will be extracted from the {@code props} properties.
+ */
@VisibleForTesting(visibility=Visibility.PRIVATE)
protected ExtraPackage(SdkSource source,
Properties props,
- String vendor,
+ String vendorId,
String path,
int revision,
String license,
@@ -188,15 +216,36 @@
archiveArch,
archiveOsPath);
- // The vendor argument is not supposed to be empty. However this attribute did not
- // exist prior to schema repo-v3 and tools r8, which means we need to cope with a
- // lack of it when reading back old local repositories. In this case we allow an
- // empty string.
- mVendor = vendor != null ? vendor : getProperty(props, PkgProps.EXTRA_VENDOR, "");
-
// The path argument comes before whatever could be in the properties
mPath = path != null ? path : getProperty(props, PkgProps.EXTRA_PATH, path);
+ String name = getProperty(props, PkgProps.EXTRA_NAME_DISPLAY, ""); //$NON-NLS-1$
+ String vname = getProperty(props, PkgProps.EXTRA_VENDOR_DISPLAY, ""); //$NON-NLS-1$
+ String vid = vendorId != null ? vendorId :
+ getProperty(props, PkgProps.EXTRA_VENDOR_ID, ""); //$NON-NLS-1$
+
+ if (vid.length() == 0) {
+ // If vid is missing, use the old <vendor> attribute.
+ // <vendor> did not exist prior to schema repo-v3 and tools r8.
+ String vendor = getProperty(props, PkgProps.EXTRA_VENDOR, ""); //$NON-NLS-1$
+ vid = sanitizeLegacyVendor(vendor);
+ if (vname.length() == 0) {
+ vname = vendor;
+ }
+ }
+ if (vname.length() == 0) {
+ // The vendor-display name can be empty, in which case we use the vendor-id.
+ vname = vid;
+ }
+ mVendorDisplay = vname.trim();
+ mVendorId = vid.trim();
+
+ if (name.length() == 0) {
+ // If name is missing, use the <path> attribute as done in an addon-3 schema.
+ name = getPrettyName();
+ }
+ mDisplayName = name.trim();
+
mOldPaths = getProperty(props, PkgProps.EXTRA_OLD_PATHS, null);
mMinApiLevel = Integer.parseInt(
@@ -226,9 +275,9 @@
super.saveProperties(props);
props.setProperty(PkgProps.EXTRA_PATH, mPath);
- if (mVendor != null) {
- props.setProperty(PkgProps.EXTRA_VENDOR, mVendor);
- }
+ props.setProperty(PkgProps.EXTRA_NAME_DISPLAY, mDisplayName);
+ props.setProperty(PkgProps.EXTRA_VENDOR_DISPLAY, mVendorDisplay);
+ props.setProperty(PkgProps.EXTRA_VENDOR_ID, mVendorId);
if (getMinApiLevel() != MIN_API_LEVEL_NOT_SPECIFIED) {
props.setProperty(PkgProps.EXTRA_MIN_API_LEVEL, Integer.toString(getMinApiLevel()));
@@ -296,32 +345,9 @@
}
/**
- * Static helper to check if a given vendor and path is acceptable for an "extra" package.
- */
- public boolean isPathValid() {
- return isSegmentValid(mVendor) && isSegmentValid(mPath);
- }
-
- private boolean isSegmentValid(String segment) {
- if (SdkConstants.FD_ADDONS.equals(segment) ||
- SdkConstants.FD_PLATFORMS.equals(segment) ||
- SdkConstants.FD_PLATFORM_TOOLS.equals(segment) ||
- SdkConstants.FD_TOOLS.equals(segment) ||
- SdkConstants.FD_DOCS.equals(segment) ||
- RepoConstants.FD_TEMP.equals(segment)) {
- return false;
- }
- return segment != null && segment.indexOf('/') == -1 && segment.indexOf('\\') == -1;
- }
-
- /**
* Returns the sanitized path folder name. It is a single-segment path.
* <p/>
* The package is installed in SDK/extras/vendor_name/path_name.
- * <p/>
- * The paths "add-ons", "platforms", "tools" and "docs" are reserved and cannot be used.
- * This limitation cannot be written in the XML Schema and must be enforced here by using
- * the method {@link #isPathValid()} *before* installing the package.
*/
public String getPath() {
// The XSD specifies the XML vendor and path should only contain [a-zA-Z0-9]+
@@ -339,20 +365,28 @@
}
/**
- * Returns the sanitized vendor folder name. It is a single-segment path.
- * <p/>
- * The package is installed in SDK/extras/vendor_name/path_name.
- * <p/>
- * An empty string is returned in case of error.
+ * Returns the vendor id.
*/
- public String getVendor() {
+ public String getVendorId() {
+ return mVendorId;
+ }
+ public String getVendorDisplay() {
+ return mVendorDisplay;
+ }
+
+ public String getDisplayName() {
+ return mDisplayName;
+ }
+
+ /** Transforms the legacy vendor name into a usable vendor id. */
+ private String sanitizeLegacyVendor(String vendorDisplay) {
// The XSD specifies the XML vendor and path should only contain [a-zA-Z0-9]+
// and cannot be empty. Let's be defensive and enforce that anyway since things
// like "____" are still valid values that we don't want to allow.
- if (mVendor != null && mVendor.length() > 0) {
- String vendor = mVendor;
+ if (vendorDisplay != null && vendorDisplay.length() > 0) {
+ String vendor = vendorDisplay.trim();
// Sanitize the vendor
vendor = vendor.replaceAll("[^a-zA-Z0-9-]+", "_"); //$NON-NLS-1$
if (vendor.equals("_")) { //$NON-NLS-1$
@@ -364,17 +398,22 @@
}
return ""; //$NON-NLS-1$
+
}
+ /**
+ * Used to produce a suitable name-display based on the current {@link #mPath}
+ * and {@link #mVendorDisplay} in addon-3 schemas.
+ */
private String getPrettyName() {
String name = mPath;
// In the past, we used to save the extras in a folder vendor-path,
// and that "vendor" would end up in the path when we reload the extra from
// disk. Detect this and compensate.
- if (mVendor != null && mVendor.length() > 0) {
- if (name.startsWith(mVendor + "-")) { //$NON-NLS-1$
- name = name.substring(mVendor.length() + 1);
+ if (mVendorDisplay != null && mVendorDisplay.length() > 0) {
+ if (name.startsWith(mVendorDisplay + "-")) { //$NON-NLS-1$
+ name = name.substring(mVendorDisplay.length() + 1);
}
}
@@ -383,11 +422,11 @@
name = name.replaceAll("[ _\t\f-]+", " ").trim(); //$NON-NLS-1$ //$NON-NLS-2$
}
if (name == null || name.length() == 0) {
- name = "Unkown Extra";
+ name = "Unknown Extra";
}
- if (mVendor != null && mVendor.length() > 0) {
- name = mVendor + " " + name; //$NON-NLS-1$
+ if (mVendorDisplay != null && mVendorDisplay.length() > 0) {
+ name = mVendorDisplay + " " + name; //$NON-NLS-1$
name = name.replaceAll("[ _\t\f-]+", " ").trim(); //$NON-NLS-1$ //$NON-NLS-2$
}
@@ -422,7 +461,7 @@
@Override
public String installId() {
return String.format("extra-%1$s-%2$s", //$NON-NLS-1$
- getVendor(),
+ getVendorId(),
getPath());
}
@@ -433,8 +472,8 @@
*/
@Override
public String getListDescription() {
- String s = String.format("%1$s package%2$s",
- getPrettyName(),
+ String s = String.format("%1$s%2$s",
+ getDisplayName(),
isObsolete() ? " (Obsolete)" : ""); //$NON-NLS-2$
return s;
@@ -445,9 +484,8 @@
*/
@Override
public String getShortDescription() {
-
- String s = String.format("%1$s package, revision %2$d%3$s",
- getPrettyName(),
+ String s = String.format("%1$s, revision %2$d%3$s",
+ getDisplayName(),
getRevision(),
isObsolete() ? " (Obsolete)" : ""); //$NON-NLS-2$
@@ -462,15 +500,15 @@
*/
@Override
public String getLongDescription() {
- String s = getDescription();
- if (s == null || s.length() == 0) {
- s = String.format("Extra %1$s package by %2$s", getPath(), getVendor());
- }
+ String s = String.format("%1$s, revision %2$d%3$s\nBy %4$s",
+ getDisplayName(),
+ getRevision(),
+ isObsolete() ? " (Obsolete)" : "", //$NON-NLS-2$
+ getVendorDisplay());
- if (s.indexOf("revision") == -1) {
- s += String.format("\nRevision %1$d%2$s",
- getRevision(),
- isObsolete() ? " (Obsolete)" : ""); //$NON-NLS-2$
+ String d = getDescription();
+ if (d != null && d.length() > 0) {
+ s += '\n' + d;
}
if (getMinToolsRevision() != MIN_TOOLS_REV_NOT_SPECIFIED) {
@@ -481,11 +519,15 @@
s += String.format("\nRequires SDK Platform Android API %1$s", getMinApiLevel());
}
- // For a local archive, also put the install path in the long description.
- // This should help users locate the extra on their drive.
File localPath = getLocalArchivePath();
if (localPath != null) {
+ // For a local archive, also put the install path in the long description.
+ // This should help users locate the extra on their drive.
s += String.format("\nLocation: %1$s", localPath.getAbsolutePath());
+ } else {
+ // For a non-installed archive, indicate where it would be installed.
+ s += String.format("\nInstall path: %1$s",
+ getInstallSubFolder(null/*sdk root*/).getPath());
}
return s;
@@ -497,7 +539,7 @@
* <p/>
* A "tool" package should always be located in SDK/tools.
*
- * @param osSdkRoot The OS path of the SDK root folder.
+ * @param osSdkRoot The OS path of the SDK root folder. Must NOT be null.
* @param sdkManager An existing SDK manager to list current platforms and addons.
* Not used in this implementation.
* @return A new {@link File} corresponding to the directory to use to install this package.
@@ -521,10 +563,22 @@
}
}
+ return getInstallSubFolder(osSdkRoot);
+ }
+
+ /**
+ * Computes the "sub-folder" install path, relative to the given SDK root.
+ * For an extra package, this is generally ".../extra/vendor-id/path".
+ *
+ * @param osSdkRoot The OS path of the SDK root folder if known.
+ * This CAN be null, in which case the path will start at /extra.
+ * @return Either /extra/vendor/path or sdk-root/extra/vendor-id/path.
+ */
+ private File getInstallSubFolder(@Nullable String osSdkRoot) {
// The /extras dir at the root of the SDK
File path = new File(osSdkRoot, SdkConstants.FD_EXTRAS);
- String vendor = getVendor();
+ String vendor = getVendorId();
if (vendor != null && vendor.length() > 0) {
path = new File(path, vendor);
}
@@ -547,8 +601,8 @@
int lenEpOldPaths = epOldPaths.length;
for (int indexEp = -1; indexEp < lenEpOldPaths; indexEp++) {
if (sameVendorAndPath(
- mVendor, mPath,
- ep.mVendor, indexEp < 0 ? ep.mPath : epOldPaths[indexEp])) {
+ mVendorId, mPath,
+ ep.mVendorId, indexEp < 0 ? ep.mPath : epOldPaths[indexEp])) {
return true;
}
}
@@ -557,8 +611,8 @@
int lenThisOldPaths = thisOldPaths.length;
for (int indexThis = -1; indexThis < lenThisOldPaths; indexThis++) {
if (sameVendorAndPath(
- mVendor, indexThis < 0 ? mPath : thisOldPaths[indexThis],
- ep.mVendor, ep.mPath)) {
+ mVendorId, indexThis < 0 ? mPath : thisOldPaths[indexThis],
+ ep.mVendorId, ep.mPath)) {
return true;
}
}
@@ -617,7 +671,7 @@
int pos = s.indexOf("|r:"); //$NON-NLS-1$
assert pos > 0;
s = s.substring(0, pos) +
- "|ve:" + getVendor() + //$NON-NLS-1$
+ "|ve:" + getVendorId() + //$NON-NLS-1$
"|pa:" + getPath() + //$NON-NLS-1$
s.substring(pos);
return s;
@@ -648,7 +702,7 @@
result = prime * result + mMinApiLevel;
result = prime * result + ((mPath == null) ? 0 : mPath.hashCode());
result = prime * result + Arrays.hashCode(mProjectFiles);
- result = prime * result + ((mVendor == null) ? 0 : mVendor.hashCode());
+ result = prime * result + ((mVendorDisplay == null) ? 0 : mVendorDisplay.hashCode());
return result;
}
@@ -677,11 +731,11 @@
if (!Arrays.equals(mProjectFiles, other.mProjectFiles)) {
return false;
}
- if (mVendor == null) {
- if (other.mVendor != null) {
+ if (mVendorDisplay == null) {
+ if (other.mVendorDisplay != null) {
return false;
}
- } else if (!mVendor.equals(other.mVendor)) {
+ } else if (!mVendorDisplay.equals(other.mVendorDisplay)) {
return false;
}
return true;
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/LocalSdkParser.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/LocalSdkParser.java
index 2e65388..13be219 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/LocalSdkParser.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/LocalSdkParser.java
@@ -235,7 +235,7 @@
dir.getName(), //path
0, //revision
null, //license
- "Tools", //description
+ null, //description
null, //descUrl
Os.getCurrentOs(), //archiveOs
Arch.getCurrentArch(), //archiveArch
@@ -308,11 +308,16 @@
if (dir.isDirectory() && !visited.contains(dir)) {
Pair<Map<String, String>, String> infos =
SdkManager.parseAddonProperties(dir, sdkManager.getTargets(), log);
+ Properties sourceProps =
+ parseProperties(new File(dir, SdkConstants.FN_SOURCE_PROP));
- Map<String, String> props = infos.getFirst();
+ Map<String, String> addonProps = infos.getFirst();
String error = infos.getSecond();
try {
- Package pkg = AddonPackage.createBroken(dir.getAbsolutePath(), props, error);
+ Package pkg = AddonPackage.createBroken(dir.getAbsolutePath(),
+ sourceProps,
+ addonProps,
+ error);
packages.add(pkg);
visited.add(dir);
} catch (Exception e) {
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Package.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Package.java
index b09e2ee..a86171c 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Package.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Package.java
@@ -142,8 +142,8 @@
mLicense = getProperty(props, PkgProps.PKG_LICENSE, license);
mDescription = getProperty(props, PkgProps.PKG_DESC, description);
mDescUrl = getProperty(props, PkgProps.PKG_DESC_URL, descUrl);
- mReleaseNote = getProperty(props, PkgProps.PKG_RELEASE_NOTE, "");
- mReleaseUrl = getProperty(props, PkgProps.PKG_RELEASE_URL, "");
+ mReleaseNote = getProperty(props, PkgProps.PKG_RELEASE_NOTE, ""); //$NON-NLS-1$
+ mReleaseUrl = getProperty(props, PkgProps.PKG_RELEASE_URL, ""); //$NON-NLS-1$
mObsolete = getProperty(props, PkgProps.PKG_OBSOLETE, null);
// If source is null and we can find a source URL in the properties, generate
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/SdkRepoSource.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/SdkRepoSource.java
index d35e365..00392de 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/SdkRepoSource.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/SdkRepoSource.java
@@ -63,12 +63,25 @@
return false;
}
+ private static String[] sDefaults = null; // lazily allocated in getDefaultXmlFileUrls
+
@Override
protected String[] getDefaultXmlFileUrls() {
- return new String[] {
- SdkRepoConstants.URL_DEFAULT_FILENAME2,
- SdkRepoConstants.URL_DEFAULT_FILENAME
- };
+ if (sDefaults == null) {
+ sDefaults = new String[SdkRepoConstants.NS_LATEST_VERSION
+ - SdkRepoConstants.NS_SERVER_MIN_VERSION
+ + 2];
+ int k = 0;
+ for (int i = SdkRepoConstants.NS_LATEST_VERSION;
+ i >= SdkRepoConstants.NS_SERVER_MIN_VERSION;
+ i--) {
+ sDefaults[k++] = String.format(SdkRepoConstants.URL_FILENAME_PATTERN, i);
+ }
+ sDefaults[k++] = SdkRepoConstants.URL_DEFAULT_FILENAME;
+ assert k == sDefaults.length;
+ }
+
+ return sDefaults;
}
@Override
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/SdkSource.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/SdkSource.java
index f757bfb..7933602 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/SdkSource.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/SdkSource.java
@@ -826,7 +826,7 @@
if (SdkAddonConstants.NODE_ADD_ON.equals(name)) {
p = new AddonPackage(this, child, nsUri, licenses);
- } else if (RepoConstants.NODE_EXTRA.equals(name)) {
+ } else if (SdkAddonConstants.NODE_EXTRA.equals(name)) {
p = new ExtraPackage(this, child, nsUri, licenses);
} else if (!isAddonSource()) {
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/-sdk-repository-6.xsd b/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/-sdk-repository-6.xsd
new file mode 100755
index 0000000..149f8c5
--- /dev/null
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/-sdk-repository-6.xsd
@@ -0,0 +1,557 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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.
+-->
+<xsd:schema
+ targetNamespace="http://schemas.android.com/sdk/android/repository/6"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:sdk="http://schemas.android.com/sdk/android/repository/6"
+ elementFormDefault="qualified"
+ attributeFormDefault="unqualified"
+ version="1">
+
+ <!-- The repository contains a collection of downloadable items known as
+ "packages". Each package has a type and various attributes and contains
+ a list of file "archives" that can be downloaded for specific OSes.
+
+ An Android SDK repository is a web site that contains a "repository.xml"
+ file that conforms to this XML Schema.
+
+ History:
+ - v1 is used by the SDK Updater in Tools r3 and r4.
+
+ - v2 is used by the SDK Updater in Tools r5:
+ - It introduces a new <sample> repository type. Previously samples
+ were included in the <platform> packages. Instead this package is used
+ and and the samples are installed in $SDK/samples.
+ - All repository types have a new <obsolete> node. It works as a marker
+ to indicate the package is obsolete and should not be selected by default.
+ The UI also hides these out by default.
+
+ - v3 is used by the SDK Updater in Tools r8:
+ - It introduces a new <platform-tool> repository type. Previously platform-specific
+ tools were included in the <platform> packages. Instead this package is used
+ and platform-specific tools are installed in $SDK/platform-tools
+ - There's a new element <min-platform-tools-rev> in <tool>. The tool package now
+ requires that at least some minimal version of <platform-tool> be installed.
+ - It removes the <addon> repository type, which is now in its own XML Schema.
+
+ - v4 is used by the SDK Updater in Tools r12:
+ - <extra> element now has a <project-files> element that contains 1 or
+ or more <path>, each indicating the relative path of a file that this package
+ can contribute to installed projects.
+ - <platform> element now has a mandatory <layoutlib> that indicates the API
+ and revision of that layout library for this particular platform.
+
+ - v5 is used by the SDK Updater in Tools R14:
+ - <extra> now has an <old-paths> element, a ;-separated list of old paths that
+ should be detected and migrated to the new <path> for that package.
+ - <platform> has a new optional <abi-included> that describes the ABI of the
+ system image included in the platform, if any.
+ - New <system-image> package type, to store system images outside of <platform>s.
+ - New <source> package type.
+
+ - v6 removed 'extra' packages. They are served only by the addon XML.
+ -->
+
+ <xsd:element name="sdk-repository" type="sdk:repositoryType" />
+
+ <xsd:complexType name="repositoryType">
+ <xsd:annotation>
+ <xsd:documentation>
+ The repository contains a collection of downloadable packages.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:choice minOccurs="0" maxOccurs="unbounded">
+ <xsd:element name="platform" type="sdk:platformType" />
+ <xsd:element name="system-image" type="sdk:systemImageType" />
+ <xsd:element name="source" type="sdk:sourceType" />
+ <xsd:element name="tool" type="sdk:toolType" />
+ <xsd:element name="platform-tool" type="sdk:platformToolType" />
+ <xsd:element name="doc" type="sdk:docType" />
+ <xsd:element name="sample" type="sdk:sampleType" />
+ <xsd:element name="license" type="sdk:licenseType" />
+ </xsd:choice>
+ </xsd:complexType>
+
+ <!-- The definition of an SDK platform package. -->
+
+ <xsd:complexType name="platformType">
+ <xsd:annotation>
+ <xsd:documentation>An SDK platform package.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:all>
+ <!-- The Android platform version. It is string such as "1.0". -->
+ <xsd:element name="version" type="xsd:normalizedString" />
+ <!-- The Android API Level for the platform. An int > 0. -->
+ <xsd:element name="api-level" type="xsd:positiveInteger" />
+ <!-- The optional codename for this platform, if it's a preview. -->
+ <xsd:element name="codename" type="xsd:string" minOccurs="0" />
+ <!-- The revision, an int > 0, incremented each time a new
+ package is generated. -->
+ <xsd:element name="revision" type="xsd:positiveInteger" />
+
+ <!-- Information on the layoutlib packaged in this platform. -->
+ <xsd:element name="layoutlib" type="sdk:layoutlibType" />
+
+ <!-- optional elements -->
+
+ <!-- The optional license of this package. If present, users will have
+ to agree to it before downloading. -->
+ <xsd:element name="uses-license" type="sdk:usesLicenseType" minOccurs="0" />
+ <!-- The optional description of this package. -->
+ <xsd:element name="description" type="xsd:string" minOccurs="0" />
+ <!-- The optional description URL of this package -->
+ <xsd:element name="desc-url" type="xsd:token" minOccurs="0" />
+ <!-- The optional release note for this package. -->
+ <xsd:element name="release-note" type="xsd:string" minOccurs="0" />
+ <!-- The optional release note URL of this package -->
+ <xsd:element name="release-url" type="xsd:token" minOccurs="0" />
+ <!-- A list of file archives for this package. -->
+ <xsd:element name="archives" type="sdk:archivesType" />
+ <!-- The minimal revision of tools required by this package.
+ Optional. If present, must be an int > 0. -->
+ <xsd:element name="min-tools-rev" type="xsd:positiveInteger" minOccurs="0" />
+
+ <!-- The ABI of the system image *included* in this platform, if any.
+ When the field is present, it means the platform already embeds one
+ system image. A platform can also have any number of external
+ <system-image> associated with it. -->
+ <xsd:element name="included-abi" type="sdk:abiType" minOccurs="0" />
+
+ <!-- An optional element indicating the package is obsolete.
+ The string content is however currently not defined and ignored. -->
+ <xsd:element name="obsolete" type="xsd:string" minOccurs="0" />
+ </xsd:all>
+ </xsd:complexType>
+
+
+ <!-- The definition of a layout library used by a platform. -->
+
+ <xsd:complexType name="layoutlibType" >
+ <xsd:annotation>
+ <xsd:documentation>
+ Version information for a layoutlib included in a platform.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:all>
+ <!-- The layoutlib API level, an int > 0,
+ incremented with each new incompatible lib. -->
+ <xsd:element name="api" type="xsd:positiveInteger" />
+ <!-- The incremental minor revision for that API, e.g. in case of bug fixes.
+ Optional. An int >= 0, assumed to be 0 if the element is missing. -->
+ <xsd:element name="revision" type="xsd:nonNegativeInteger" minOccurs="0" />
+ </xsd:all>
+ </xsd:complexType>
+
+
+ <!-- The definition of a system image used by a platform. -->
+
+ <xsd:complexType name="systemImageType" >
+ <xsd:annotation>
+ <xsd:documentation>
+ System Image for a platform.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:all>
+ <!-- api-level + codename identifies the platform to which this system image belongs. -->
+
+ <!-- The Android API Level for the platform. An int > 0. -->
+ <xsd:element name="api-level" type="xsd:positiveInteger" />
+ <!-- The optional codename for this platform, if it's a preview. -->
+ <xsd:element name="codename" type="xsd:string" minOccurs="0" />
+
+ <!-- The revision, an int > 0, incremented each time a new
+ package is generated. -->
+ <xsd:element name="revision" type="xsd:positiveInteger" />
+
+ <!-- The ABI of the system emulated by this image. -->
+ <xsd:element name="abi" type="sdk:abiType" />
+
+ <!-- The optional license of this package. If present, users will have
+ to agree to it before downloading. -->
+ <xsd:element name="uses-license" type="sdk:usesLicenseType" minOccurs="0" />
+ <!-- The optional description of this package. -->
+ <xsd:element name="description" type="xsd:string" minOccurs="0" />
+ <!-- The optional description URL of this package -->
+ <xsd:element name="desc-url" type="xsd:token" minOccurs="0" />
+ <!-- The optional release note for this package. -->
+ <xsd:element name="release-note" type="xsd:string" minOccurs="0" />
+ <!-- The optional release note URL of this package -->
+ <xsd:element name="release-url" type="xsd:token" minOccurs="0" />
+
+ <!-- A list of file archives for this package. -->
+ <xsd:element name="archives" type="sdk:archivesType" />
+ </xsd:all>
+ </xsd:complexType>
+
+ <!-- The definition of the ABI supported by a platform's system image. -->
+
+ <xsd:simpleType name="abiType">
+ <xsd:annotation>
+ <xsd:documentation>The ABI of a platform's system image.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:token">
+ <xsd:enumeration value="armeabi" />
+ <xsd:enumeration value="armeabi-v7a" />
+ <xsd:enumeration value="x86" />
+ </xsd:restriction>
+ </xsd:simpleType>
+
+
+ <!-- The definition of a source package. -->
+
+ <xsd:complexType name="sourceType" >
+ <xsd:annotation>
+ <xsd:documentation>
+ Sources for a platform.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:all>
+ <!-- api-level + codename identifies the platform to which this source belongs. -->
+
+ <!-- The Android API Level for the platform. An int > 0. -->
+ <xsd:element name="api-level" type="xsd:positiveInteger" />
+ <!-- The optional codename for this platform, if it's a preview. -->
+ <xsd:element name="codename" type="xsd:string" minOccurs="0" />
+
+ <!-- The revision, an int > 0, incremented each time a new
+ package is generated. -->
+ <xsd:element name="revision" type="xsd:positiveInteger" />
+
+ <!-- The optional license of this package. If present, users will have
+ to agree to it before downloading. -->
+ <xsd:element name="uses-license" type="sdk:usesLicenseType" minOccurs="0" />
+ <!-- The optional description of this package. -->
+ <xsd:element name="description" type="xsd:string" minOccurs="0" />
+ <!-- The optional description URL of this package -->
+ <xsd:element name="desc-url" type="xsd:token" minOccurs="0" />
+ <!-- The optional release note for this package. -->
+ <xsd:element name="release-note" type="xsd:string" minOccurs="0" />
+ <!-- The optional release note URL of this package -->
+ <xsd:element name="release-url" type="xsd:token" minOccurs="0" />
+
+ <!-- A list of file archives for this package. -->
+ <xsd:element name="archives" type="sdk:archivesType" />
+ </xsd:all>
+ </xsd:complexType>
+
+
+ <!-- The definition of an SDK tool package. -->
+
+ <xsd:complexType name="toolType" >
+ <xsd:annotation>
+ <xsd:documentation>An SDK tool package.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:all>
+ <!-- The revision, an int > 0, incremented each time a new
+ package is generated. -->
+ <xsd:element name="revision" type="xsd:positiveInteger" />
+ <!-- The optional license of this package. If present, users will have
+ to agree to it before downloading. -->
+ <xsd:element name="uses-license" type="sdk:usesLicenseType" minOccurs="0" />
+ <!-- The optional description of this package. -->
+ <xsd:element name="description" type="xsd:string" minOccurs="0" />
+ <!-- The optional description URL of this package -->
+ <xsd:element name="desc-url" type="xsd:token" minOccurs="0" />
+ <!-- The optional release note for this package. -->
+ <xsd:element name="release-note" type="xsd:string" minOccurs="0" />
+ <!-- The optional release note URL of this package -->
+ <xsd:element name="release-url" type="xsd:token" minOccurs="0" />
+ <!-- A list of file archives for this package. -->
+ <xsd:element name="archives" type="sdk:archivesType" />
+ <!-- An optional element indicating the package is obsolete.
+ The string content is however currently not defined and ignored. -->
+ <xsd:element name="obsolete" type="xsd:string" minOccurs="0" />
+
+ <!-- The minimal revision of platform-tools required by this package.
+ Mandatory. Must be an int > 0. -->
+ <xsd:element name="min-platform-tools-rev" type="xsd:positiveInteger" />
+ </xsd:all>
+ </xsd:complexType>
+
+
+ <!-- The definition of an SDK platform-tool package. -->
+
+ <xsd:complexType name="platformToolType" >
+ <xsd:annotation>
+ <xsd:documentation>An SDK platform-tool package.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:all>
+ <!-- The revision, an int > 0, incremented each time a new
+ package is generated. -->
+ <xsd:element name="revision" type="xsd:positiveInteger" />
+ <!-- The optional license of this package. If present, users will have
+ to agree to it before downloading. -->
+ <xsd:element name="uses-license" type="sdk:usesLicenseType" minOccurs="0" />
+ <!-- The optional description of this package. -->
+ <xsd:element name="description" type="xsd:string" minOccurs="0" />
+ <!-- The optional description URL of this package -->
+ <xsd:element name="desc-url" type="xsd:token" minOccurs="0" />
+ <!-- The optional release note for this package. -->
+ <xsd:element name="release-note" type="xsd:string" minOccurs="0" />
+ <!-- The optional release note URL of this package -->
+ <xsd:element name="release-url" type="xsd:token" minOccurs="0" />
+ <!-- A list of file archives for this package. -->
+ <xsd:element name="archives" type="sdk:archivesType" />
+
+ <!-- An optional element indicating the package is obsolete.
+ The string content is however currently not defined and ignored. -->
+ <xsd:element name="obsolete" type="xsd:string" minOccurs="0" />
+ </xsd:all>
+ </xsd:complexType>
+
+
+ <!-- The definition of an SDK doc package. -->
+
+ <xsd:complexType name="docType" >
+ <xsd:annotation>
+ <xsd:documentation>An SDK doc package.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:all>
+ <!-- The Android API Level for the documentation. An int > 0. -->
+ <xsd:element name="api-level" type="xsd:positiveInteger" />
+ <!-- The optional codename for this doc, if it's a preview. -->
+ <xsd:element name="codename" type="xsd:string" minOccurs="0" />
+
+ <!-- The revision, an int > 0, incremented each time a new
+ package is generated. -->
+ <xsd:element name="revision" type="xsd:positiveInteger" />
+ <!-- The optional license of this package. If present, users will have
+ to agree to it before downloading. -->
+ <xsd:element name="uses-license" type="sdk:usesLicenseType" minOccurs="0" />
+ <!-- The optional description of this package. -->
+ <xsd:element name="description" type="xsd:string" minOccurs="0" />
+ <!-- The optional description URL of this package -->
+ <xsd:element name="desc-url" type="xsd:token" minOccurs="0" />
+ <!-- The optional release note for this package. -->
+ <xsd:element name="release-note" type="xsd:string" minOccurs="0" />
+ <!-- The optional release note URL of this package -->
+ <xsd:element name="release-url" type="xsd:token" minOccurs="0" />
+ <!-- A list of file archives for this package. -->
+ <xsd:element name="archives" type="sdk:archivesType" />
+
+ <!-- An optional element indicating the package is obsolete.
+ The string content is however currently not defined and ignored. -->
+ <xsd:element name="obsolete" type="xsd:string" minOccurs="0" />
+ </xsd:all>
+ </xsd:complexType>
+
+
+ <!-- The definition of an SDK sample package. -->
+
+ <xsd:complexType name="sampleType" >
+ <xsd:annotation>
+ <xsd:documentation>An SDK sample package.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:all>
+ <!-- The Android API Level for the documentation. An int > 0. -->
+ <xsd:element name="api-level" type="xsd:positiveInteger" />
+ <!-- The optional codename for this doc, if it's a preview. -->
+ <xsd:element name="codename" type="xsd:string" minOccurs="0" />
+
+ <!-- The revision, an int > 0, incremented each time a new
+ package is generated. -->
+ <xsd:element name="revision" type="xsd:positiveInteger" />
+ <!-- The optional license of this package. If present, users will have
+ to agree to it before downloading. -->
+ <xsd:element name="uses-license" type="sdk:usesLicenseType" minOccurs="0" />
+ <!-- The optional description of this package. -->
+ <xsd:element name="description" type="xsd:string" minOccurs="0" />
+ <!-- The optional description URL of this package -->
+ <xsd:element name="desc-url" type="xsd:token" minOccurs="0" />
+ <!-- The optional release note for this package. -->
+ <xsd:element name="release-note" type="xsd:string" minOccurs="0" />
+ <!-- The optional release note URL of this package -->
+ <xsd:element name="release-url" type="xsd:token" minOccurs="0" />
+ <!-- A list of file archives for this package. -->
+ <xsd:element name="archives" type="sdk:archivesType" />
+ <!-- The minimal revision of tools required by this package.
+ Optional. If present, must be an int > 0. -->
+ <xsd:element name="min-tools-rev" type="xsd:positiveInteger" minOccurs="0" />
+
+ <!-- An optional element indicating the package is obsolete.
+ The string content is however currently not defined and ignored. -->
+ <xsd:element name="obsolete" type="xsd:string" minOccurs="0" />
+ </xsd:all>
+ </xsd:complexType>
+
+
+ <!-- The definition of a path segment used by the extra element. -->
+
+ <xsd:simpleType name="segmentType">
+ <xsd:annotation>
+ <xsd:documentation>
+ One path segment for the install path of an extra element.
+ It must be a single-segment path.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:token">
+ <xsd:pattern value="[a-zA-Z0-9_]+"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:simpleType name="segmentListType">
+ <xsd:annotation>
+ <xsd:documentation>
+ A semi-colon separated list of a segmentTypes.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:token">
+ <xsd:pattern value="[a-zA-Z0-9_;]+"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+
+ <!-- The definition of a license to be referenced by the uses-license element. -->
+
+ <xsd:complexType name="licenseType">
+ <xsd:annotation>
+ <xsd:documentation>
+ A license definition. Such a license must be used later as a reference
+ using a uses-license element in one of the package elements.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="id" type="xsd:ID" />
+ <xsd:attribute name="type" type="xsd:token" fixed="text" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+
+
+ <!-- Type describing the license used by a package.
+ The license MUST be defined using a license node and referenced
+ using the ref attribute of the license element inside a package.
+ -->
+
+ <xsd:complexType name="usesLicenseType">
+ <xsd:annotation>
+ <xsd:documentation>
+ Describes the license used by a package. The license MUST be defined
+ using a license node and referenced using the ref attribute of the
+ license element inside a package.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:attribute name="ref" type="xsd:IDREF" />
+ </xsd:complexType>
+
+
+ <!-- A collection of files that can be downloaded for a given architecture.
+ The <archives> node is mandatory in the repository elements and the
+ collection must have at least one <archive> declared.
+ Each archive is a zip file that will be unzipped in a location that depends
+ on its package type.
+ -->
+
+ <xsd:complexType name="archivesType">
+ <xsd:annotation>
+ <xsd:documentation>
+ A collection of files that can be downloaded for a given architecture.
+ The <archives> node is mandatory in the repository packages and the
+ collection must have at least one <archive> declared.
+ Each archive is a zip file that will be unzipped in a location that depends
+ on its package type.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence minOccurs="1" maxOccurs="unbounded">
+ <!-- One archive file -->
+ <xsd:element name="archive">
+ <xsd:complexType>
+ <!-- Properties of the archive file -->
+ <xsd:all>
+ <!-- The size in bytes of the archive to download. -->
+ <xsd:element name="size" type="xsd:positiveInteger" />
+ <!-- The checksum of the archive file. -->
+ <xsd:element name="checksum" type="sdk:checksumType" />
+ <!-- The URL is an absolute URL if it starts with http://, https://
+ or ftp://. Otherwise it is relative to the parent directory that
+ contains this repository.xml -->
+ <xsd:element name="url" type="xsd:token" />
+ </xsd:all>
+
+ <!-- Attributes that identify the OS and architecture -->
+ <xsd:attribute name="os" use="required">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:token">
+ <xsd:enumeration value="any" />
+ <xsd:enumeration value="linux" />
+ <xsd:enumeration value="macosx" />
+ <xsd:enumeration value="windows" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+ <xsd:attribute name="arch" use="optional">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:token">
+ <xsd:enumeration value="any" />
+ <xsd:enumeration value="ppc" />
+ <xsd:enumeration value="x86" />
+ <xsd:enumeration value="x86_64" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+
+
+ <!-- A collection of file paths available in an <extra> package
+ that can be installed in an Android project.
+ If present, the <project-files> collection must contain at least one path.
+ Each path is relative to the root directory of the package.
+ -->
+
+ <xsd:complexType name="projectFilesType">
+ <xsd:annotation>
+ <xsd:documentation>
+ A collection of file paths available in an <extra> package
+ that can be installed in an Android project.
+ If present, the <project-files> collection must contain at least one path.
+ Each path is relative to the root directory of the package.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence minOccurs="1" maxOccurs="unbounded">
+ <!-- One JAR Path, relative to the root folder of the package. -->
+ <xsd:element name="path" type="xsd:string" />
+ </xsd:sequence>
+ </xsd:complexType>
+
+
+ <!-- The definition of a file checksum -->
+
+ <xsd:simpleType name="sha1Number">
+ <xsd:annotation>
+ <xsd:documentation>A SHA1 checksum.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:string">
+ <xsd:pattern value="([0-9a-fA-F]){40}"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:complexType name="checksumType">
+ <xsd:annotation>
+ <xsd:documentation>A file checksum, currently only SHA1.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleContent>
+ <xsd:extension base="sdk:sha1Number">
+ <xsd:attribute name="type" type="xsd:token" fixed="sha1" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+
+</xsd:schema>
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/PkgProps.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/PkgProps.java
index d16a35f..579656a 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/PkgProps.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/PkgProps.java
@@ -47,7 +47,12 @@
// AddonPackage
public static final String ADDON_NAME = "Addon.Name"; //$NON-NLS-1$
+ public static final String ADDON_NAME_ID = "Addon.NameId"; //$NON-NLS-1$
+ public static final String ADDON_NAME_DISPLAY = "Addon.NameDisplay"; //$NON-NLS-1$
+
public static final String ADDON_VENDOR = "Addon.Vendor"; //$NON-NLS-1$
+ public static final String ADDON_VENDOR_ID = "Addon.VendorId"; //$NON-NLS-1$
+ public static final String ADDON_VENDOR_DISPLAY = "Addon.VendorDisplay"; //$NON-NLS-1$
// DocPackage
@@ -55,9 +60,12 @@
public static final String EXTRA_PATH = "Extra.Path"; //$NON-NLS-1$
public static final String EXTRA_OLD_PATHS = "Extra.OldPaths"; //$NON-NLS-1$
- public static final String EXTRA_VENDOR = "Extra.Vendor"; //$NON-NLS-1$
public static final String EXTRA_MIN_API_LEVEL = "Extra.MinApiLevel"; //$NON-NLS-1$
public static final String EXTRA_PROJECT_FILES = "Extra.ProjectFiles"; //$NON-NLS-1$
+ public static final String EXTRA_VENDOR = "Extra.Vendor"; //$NON-NLS-1$
+ public static final String EXTRA_VENDOR_ID = "Extra.VendorId"; //$NON-NLS-1$
+ public static final String EXTRA_VENDOR_DISPLAY = "Extra.VendorDisplay"; //$NON-NLS-1$
+ public static final String EXTRA_NAME_DISPLAY = "Extra.NameDisplay"; //$NON-NLS-1$
// ILayoutlibVersion
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/RepoConstants.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/RepoConstants.java
index b7f8774..53db79f 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/RepoConstants.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/RepoConstants.java
@@ -25,9 +25,6 @@
*/
public class RepoConstants {
- /** An extra package. */
- public static final String NODE_EXTRA = "extra"; //$NON-NLS-1$
-
/** The license definition. */
public static final String NODE_LICENSE = "license"; //$NON-NLS-1$
/** The optional uses-license for all packages or for a lib. */
@@ -60,10 +57,20 @@
public static final String NODE_API_LEVEL = "api-level"; //$NON-NLS-1$
/** The codename, a string, for platform packages. */
public static final String NODE_CODENAME = "codename"; //$NON-NLS-1$
- /** The vendor, a string, for add-on and extra packages. */
+ /** The *old* vendor, a string, for add-on and extra packages.
+ * Replaced by {@link #NODE_VENDOR_DISPLAY} and {@link #NODE_VENDOR_ID} in addon-v4.xsd. */
public static final String NODE_VENDOR = "vendor"; //$NON-NLS-1$
- /** The name, a string, for add-on packages or for libraries. */
+ /** The vendor display string, for add-on and extra packages. */
+ public static final String NODE_VENDOR_DISPLAY = "vendor-display"; //$NON-NLS-1$
+ /** The unique vendor id string, for add-on and extra packages. */
+ public static final String NODE_VENDOR_ID = "vendor-id"; //$NON-NLS-1$
+ /** The name, a string, for add-on packages or for libraries.
+ * Replaced by {@link #NODE_NAME_DISPLAY} and {@link #NODE_NAME_ID} in addon-v4.xsd. */
public static final String NODE_NAME = "name"; //$NON-NLS-1$
+ /** The name display string, for add-on packages or for libraries. */
+ public static final String NODE_NAME_DISPLAY = "name-display"; //$NON-NLS-1$
+ /** The unique name id string, for add-on packages or for libraries. */
+ public static final String NODE_NAME_ID = "name-id"; //$NON-NLS-1$
/** A layoutlib package. */
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/SdkAddonConstants.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/SdkAddonConstants.java
index 122d40a..41b184e 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/SdkAddonConstants.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/SdkAddonConstants.java
@@ -26,8 +26,10 @@
*/
public class SdkAddonConstants extends RepoConstants {
- /** The default name looked for by {@link SdkSource} when trying to load an
- * sdk-addon XML if the URL doesn't match an existing resource. */
+ /**
+ * The default name looked for by {@link SdkSource} when trying to load an
+ * sdk-addon XML if the URL doesn't match an existing resource.
+ */
public static final String URL_DEFAULT_FILENAME = "addon.xml"; //$NON-NLS-1$
/** The base of our sdk-addon XML namespace. */
@@ -40,9 +42,11 @@
*/
public static final String NS_PATTERN = NS_BASE + "([1-9][0-9]*)"; //$NON-NLS-1$
- /** The latest version of the sdk-addon XML Schema.
- * Valid version numbers are between 1 and this number, included. */
- public static final int NS_LATEST_VERSION = 3;
+ /**
+ * The latest version of the sdk-addon XML Schema.
+ * Valid version numbers are between 1 and this number, included.
+ */
+ public static final int NS_LATEST_VERSION = 4;
/** The XML namespace of the latest sdk-addon XML. */
public static final String NS_URI = getSchemaUri(NS_LATEST_VERSION);
@@ -53,6 +57,9 @@
/** An add-on package. */
public static final String NODE_ADD_ON = "add-on"; //$NON-NLS-1$
+ /** An extra package. */
+ public static final String NODE_EXTRA = "extra"; //$NON-NLS-1$
+
/**
* List of possible nodes in a repository XML. Used to populate options automatically
* in the no-GUI mode.
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/SdkRepoConstants.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/SdkRepoConstants.java
index 710ec97..b4a75a9 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/SdkRepoConstants.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/SdkRepoConstants.java
@@ -26,25 +26,43 @@
*/
public class SdkRepoConstants extends RepoConstants {
- /** The latest version of the sdk-repository XML Schema.
- * Valid version numbers are between 1 and this number, included. */
- public static final int NS_LATEST_VERSION = 5;
+ /**
+ * The latest version of the sdk-repository XML Schema.
+ * Valid version numbers are between 1 and this number, included.
+ */
+ public static final int NS_LATEST_VERSION = 6;
- /** The URL of the official Google sdk-repository site.
- * The URL ends with a /, allowing easy concatenation. */
+ /**
+ * The min version of the sdk-repository XML Schema we'll try to load.
+ * When looking for a repository-N.xml on the server, we'll check from
+ * {@link #NS_LATEST_VERSION} down to this revision.
+ * We only introduced the "repository-N.xml" pattern start with revision
+ * 5, so we know that <em>our</em> server will never contain a repository
+ * XML with a schema version lower than this one.
+ */
+ public static final int NS_SERVER_MIN_VERSION = 5;
+
+ /**
+ * The URL of the official Google sdk-repository site.
+ * The URL ends with a /, allowing easy concatenation.
+ * */
public static final String URL_GOOGLE_SDK_SITE =
"https://dl-ssl.google.com/android/repository/"; //$NON-NLS-1$
- /** The default name looked for by {@link SdkSource} when trying to load an
- * sdk-repository XML if the URL doesn't match an existing resource. */
+ /**
+ * The default name looked for by {@link SdkSource} when trying to load an
+ * sdk-repository XML if the URL doesn't match an existing resource.
+ */
public static final String URL_DEFAULT_FILENAME = "repository.xml"; //$NON-NLS-1$
- /** The pattern name looked by {@link SdkSource} when trying to load
- * the latest sdk-repository XML that is specific to the current XSD
- * schema revision.
+ /**
+ * The pattern name looked by {@link SdkSource} when trying to load
+ * an sdk-repository XML that is specific to a given XSD revision.
+ * <p/>
+ * This must be used with {@link String#format(String, Object...)} with
+ * one integer parameter between 1 and {@link #NS_LATEST_VERSION}.
*/
- public static final String URL_DEFAULT_FILENAME2 =
- String.format("repository-%d.xml", NS_LATEST_VERSION); //$NON-NLS-1$
+ public static final String URL_FILENAME_PATTERN = "repository-%1$d.xml"; //$NON-NLS-1$
/** The base of our sdk-repository XML namespace. */
private static final String NS_BASE =
@@ -94,7 +112,6 @@
NODE_PLATFORM_TOOL,
NODE_DOC,
NODE_SAMPLE,
- NODE_EXTRA,
NODE_SOURCE,
};
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/sdk-addon-4.xsd b/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/sdk-addon-4.xsd
new file mode 100755
index 0000000..9289e1c
--- /dev/null
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/sdk-addon-4.xsd
@@ -0,0 +1,396 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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.
+-->
+<xsd:schema
+ targetNamespace="http://schemas.android.com/sdk/android/addon/4"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:sdk="http://schemas.android.com/sdk/android/addon/4"
+ elementFormDefault="qualified"
+ attributeFormDefault="unqualified"
+ version="1">
+
+ <!-- The repository contains a collection of downloadable items known as
+ "packages". Each package has a type and various attributes and contains
+ a list of file "archives" that can be downloaded for specific OSes.
+
+ An Android Addon repository is a web site that contains an "addon.xml"
+ file that conforms to this XML Schema.
+
+ History:
+ - v1 is used by the SDK Updater in Tools r8. It is split out of the
+ main SDK Repository XML Schema and can only contain <addon> and
+ <extra> packages.
+
+ - v2 is used by the SDK Updater in Tools r12.
+ - <extra> element now has a <project-files> element that contains 1 or
+ or more <path>, each indicating the relative path of a file that this package
+ can contribute to installed projects.
+ - <addon> element now has an optional <layoutlib> that indicates the API
+ and revision of the layout library for this particular add-on, if any.
+
+ - v3 is used by the SDK Updater in Tools R14:
+ - <extra> now has an <old-paths> element, a ;-separated list of old paths that
+ should be detected and migrated to the new <path> for that package.
+ -->
+
+ <xsd:element name="sdk-addon" type="sdk:repositoryType" />
+
+ <xsd:complexType name="repositoryType">
+ <xsd:annotation>
+ <xsd:documentation>
+ The repository contains a collection of downloadable packages.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:choice minOccurs="0" maxOccurs="unbounded">
+ <xsd:element name="add-on" type="sdk:addonType" />
+ <xsd:element name="extra" type="sdk:extraType" />
+ <xsd:element name="license" type="sdk:licenseType" />
+ </xsd:choice>
+ </xsd:complexType>
+
+ <!-- The definition of an SDK Add-on package. -->
+
+ <xsd:complexType name="addonType">
+ <xsd:annotation>
+ <xsd:documentation>An SDK add-on package.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:all>
+ <!-- The internal name id of the add-on. Must be unique per vendor. -->
+ <xsd:element name="name-id" type="sdk:idType" />
+ <!-- The displayed name of the add-on. -->
+ <xsd:element name="name-display" type="xsd:normalizedString" />
+
+ <!-- The internal vendor id of the add-on. Must be unique amongst vendors. -->
+ <xsd:element name="vendor-id" type="sdk:idType" />
+ <!-- The displayed vendor name of the add-on. -->
+ <xsd:element name="vendor-display" type="xsd:normalizedString" />
+
+ <!-- The Android API Level for the add-on. An int > 0. -->
+ <xsd:element name="api-level" type="xsd:positiveInteger" />
+ <!-- Note: Add-ons do not support 'codenames' (a.k.a. API previews). -->
+ <!-- The revision, an int > 0, incremented each time a new
+ package is generated. -->
+ <xsd:element name="revision" type="xsd:positiveInteger" />
+
+ <!-- An add-on can declare 0 or more libraries.
+ This element is mandatory but it can be empty.
+ -->
+
+ <xsd:element name="libs">
+ <xsd:complexType>
+ <xsd:sequence minOccurs="0" maxOccurs="unbounded">
+ <xsd:element name="lib">
+ <xsd:complexType>
+ <xsd:all>
+ <!-- The name of the library. -->
+ <xsd:element name="name" type="xsd:normalizedString" />
+ <!-- The optional description of this add-on library. -->
+ <xsd:element name="description" type="xsd:string" minOccurs="0" />
+ </xsd:all>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <!-- optional elements -->
+
+ <!-- The optional license of this package. If present, users will have
+ to agree to it before downloading. -->
+ <xsd:element name="uses-license" type="sdk:usesLicenseType" minOccurs="0" />
+ <!-- The optional description of this package. -->
+ <xsd:element name="description" type="xsd:string" minOccurs="0" />
+ <!-- The optional description URL of this package -->
+ <xsd:element name="desc-url" type="xsd:token" minOccurs="0" />
+ <!-- The optional release note for this package. -->
+ <xsd:element name="release-note" type="xsd:string" minOccurs="0" />
+ <!-- The optional release note URL of this package -->
+ <xsd:element name="release-url" type="xsd:token" minOccurs="0" />
+ <!-- A list of file archives for this package. -->
+ <xsd:element name="archives" type="sdk:archivesType" />
+
+ <!-- An optional element indicating the package is obsolete.
+ The string content is however currently not defined and ignored. -->
+ <xsd:element name="obsolete" type="xsd:string" minOccurs="0" />
+
+ <!-- Optional information on the layoutlib packaged in this platform. -->
+ <xsd:element name="layoutlib" type="sdk:layoutlibType" minOccurs="0" />
+ </xsd:all>
+ </xsd:complexType>
+
+
+ <xsd:simpleType name="idType">
+ <xsd:annotation>
+ <xsd:documentation>
+ An ID string for an addon/extra name-id or vendor-id
+ can only be simple alphanumeric string.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:token">
+ <xsd:pattern value="[a-zA-Z0-9_-]+"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+
+ <!-- The definition of a layout library used by an addon. -->
+
+ <xsd:complexType name="layoutlibType" >
+ <xsd:annotation>
+ <xsd:documentation>
+ Version information for a layoutlib included in an addon.
+ .</xsd:documentation>
+ </xsd:annotation>
+ <xsd:all>
+ <!-- The layoutlib API level, an int > 0,
+ incremented with each new incompatible lib. -->
+ <xsd:element name="api" type="xsd:positiveInteger" />
+ <!-- The incremental minor revision for that API, e.g. in case of bug fixes.
+ Optional. An int >= 0, assumed to be 0 if the element is missing. -->
+ <xsd:element name="revision" type="xsd:nonNegativeInteger" minOccurs="0" />
+ </xsd:all>
+ </xsd:complexType>
+
+
+ <!-- The definition of an SDK extra package. This kind of package is for
+ "free" content. Such packages are installed in SDK/extras/vendor/path.
+ -->
+
+ <xsd:complexType name="extraType" >
+ <xsd:annotation>
+ <xsd:documentation>
+ An SDK extra package. This kind of package is for "free" content.
+ Such packages are installed in SDK/vendor/path.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:all>
+ <!-- The displayed name of the extra. -->
+ <xsd:element name="name-display" type="xsd:normalizedString" />
+
+ <!-- The internal vendor id of the extra. Must be unique amongst vendors. -->
+ <xsd:element name="vendor-id" type="sdk:idType" />
+ <!-- The displayed vendor name of the extra. -->
+ <xsd:element name="vendor-display" type="xsd:normalizedString" />
+
+ <!-- The install path sub-folder name. It must not be empty. -->
+ <xsd:element name="path" type="sdk:segmentType" />
+
+ <!-- A semi-colon separated list of "obsolete" path names which are equivalent
+ to the current 'path' name. When a package is seen using an old-paths' name,
+ the package manager will try to upgrade it to the new path. -->
+ <xsd:element name="old-paths" type="sdk:segmentListType" minOccurs="0" />
+
+ <!-- The revision, an int > 0, incremented each time a new
+ package is generated. -->
+ <xsd:element name="revision" type="xsd:positiveInteger" />
+
+ <!-- A list of file archives for this package. -->
+ <xsd:element name="archives" type="sdk:archivesType" />
+
+ <!-- optional elements -->
+
+ <!-- The optional license of this package. If present, users will have
+ to agree to it before downloading. -->
+ <xsd:element name="uses-license" type="sdk:usesLicenseType" minOccurs="0" />
+ <!-- The optional description of this package. -->
+ <xsd:element name="description" type="xsd:string" minOccurs="0" />
+ <!-- The optional description URL of this package -->
+ <xsd:element name="desc-url" type="xsd:token" minOccurs="0" />
+ <!-- The optional release note for this package. -->
+ <xsd:element name="release-note" type="xsd:string" minOccurs="0" />
+ <!-- The optional release note URL of this package -->
+ <xsd:element name="release-url" type="xsd:token" minOccurs="0" />
+ <!-- The minimal revision of tools required by this package.
+ Optional. If present, must be an int > 0. -->
+ <xsd:element name="min-tools-rev" type="xsd:positiveInteger" minOccurs="0" />
+ <!-- The minimal API level required by this package.
+ Optional. If present, must be an int > 0. -->
+ <xsd:element name="min-api-level" type="xsd:positiveInteger" minOccurs="0" />
+ <!-- An optional element indicating the package is obsolete.
+ The string content is however currently not defined and ignored. -->
+ <xsd:element name="obsolete" type="xsd:string" minOccurs="0" />
+
+ <!-- A list of project files contributed by this package. Optional. -->
+ <xsd:element name="project-files" type="sdk:projectFilesType" minOccurs="0" />
+ </xsd:all>
+ </xsd:complexType>
+
+
+ <!-- The definition of a path segment used by the extra element. -->
+
+ <xsd:simpleType name="segmentType">
+ <xsd:annotation>
+ <xsd:documentation>
+ One path segment for the install path of an extra element.
+ It must be a single-segment path. It must not be empty.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:token">
+ <xsd:pattern value="[a-zA-Z0-9_]+"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:simpleType name="segmentListType">
+ <xsd:annotation>
+ <xsd:documentation>
+ A semi-colon separated list of a segmentTypes.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:token">
+ <xsd:pattern value="[a-zA-Z0-9_;]+"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+
+ <!-- The definition of a license to be referenced by the uses-license element. -->
+
+ <xsd:complexType name="licenseType">
+ <xsd:annotation>
+ <xsd:documentation>
+ A license definition. Such a license must be used later as a reference
+ using a uses-license element in one of the package elements.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:string">
+ <xsd:attribute name="id" type="xsd:ID" />
+ <xsd:attribute name="type" type="xsd:token" fixed="text" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+
+
+ <!-- Type describing the license used by a package.
+ The license MUST be defined using a license node and referenced
+ using the ref attribute of the license element inside a package.
+ -->
+
+ <xsd:complexType name="usesLicenseType">
+ <xsd:annotation>
+ <xsd:documentation>
+ Describes the license used by a package. The license MUST be defined
+ using a license node and referenced using the ref attribute of the
+ license element inside a package.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:attribute name="ref" type="xsd:IDREF" />
+ </xsd:complexType>
+
+
+ <!-- A collection of files that can be downloaded for a given architecture.
+ The <archives> node is mandatory in the repository elements and the
+ collection must have at least one <archive> declared.
+ Each archive is a zip file that will be unzipped in a location that depends
+ on its package type.
+ -->
+
+ <xsd:complexType name="archivesType">
+ <xsd:annotation>
+ <xsd:documentation>
+ A collection of files that can be downloaded for a given architecture.
+ The <archives> node is mandatory in the repository packages and the
+ collection must have at least one <archive> declared.
+ Each archive is a zip file that will be unzipped in a location that depends
+ on its package type.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence minOccurs="1" maxOccurs="unbounded">
+ <!-- One archive file -->
+ <xsd:element name="archive">
+ <xsd:complexType>
+ <!-- Properties of the archive file -->
+ <xsd:all>
+ <!-- The size in bytes of the archive to download. -->
+ <xsd:element name="size" type="xsd:positiveInteger" />
+ <!-- The checksum of the archive file. -->
+ <xsd:element name="checksum" type="sdk:checksumType" />
+ <!-- The URL is an absolute URL if it starts with http://, https://
+ or ftp://. Otherwise it is relative to the parent directory that
+ contains this repository.xml -->
+ <xsd:element name="url" type="xsd:token" />
+ </xsd:all>
+
+ <!-- Attributes that identify the OS and architecture -->
+ <xsd:attribute name="os" use="required">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:token">
+ <xsd:enumeration value="any" />
+ <xsd:enumeration value="linux" />
+ <xsd:enumeration value="macosx" />
+ <xsd:enumeration value="windows" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+ <xsd:attribute name="arch" use="optional">
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:token">
+ <xsd:enumeration value="any" />
+ <xsd:enumeration value="ppc" />
+ <xsd:enumeration value="x86" />
+ <xsd:enumeration value="x86_64" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:attribute>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+
+
+ <!-- A collection of file paths available in an <extra> package
+ that can be installed in an Android project.
+ If present, the <project-files> collection must contain at least one path.
+ Each path is relative to the root directory of the package.
+ -->
+
+ <xsd:complexType name="projectFilesType">
+ <xsd:annotation>
+ <xsd:documentation>
+ A collection of file paths available in an <extra> package
+ that can be installed in an Android project.
+ If present, the <project-files> collection must contain at least one path.
+ Each path is relative to the root directory of the package.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence minOccurs="1" maxOccurs="unbounded">
+ <!-- One JAR Path, relative to the root folder of the package. -->
+ <xsd:element name="path" type="xsd:string" />
+ </xsd:sequence>
+ </xsd:complexType>
+
+
+ <!-- The definition of a file checksum -->
+
+ <xsd:simpleType name="sha1Number">
+ <xsd:annotation>
+ <xsd:documentation>A SHA1 checksum.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:string">
+ <xsd:pattern value="([0-9a-fA-F]){40}"/>
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:complexType name="checksumType">
+ <xsd:annotation>
+ <xsd:documentation>A file checksum, currently only SHA1.</xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleContent>
+ <xsd:extension base="sdk:sha1Number">
+ <xsd:attribute name="type" type="xsd:token" fixed="sha1" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+
+</xsd:schema>
diff --git a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/ArchiveInstallerTest.java b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/ArchiveInstallerTest.java
index 91fc2e6..46390b5 100755
--- a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/ArchiveInstallerTest.java
+++ b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/ArchiveInstallerTest.java
@@ -108,7 +108,7 @@
/** Test we can install a simple new archive. */
public void testInstall_NewArchive() throws Exception {
- SdkSource src1 = new SdkRepoSource("http://repo.com/url", "repo1");
+ SdkSource src1 = new SdkRepoSource("http://repo.example.com/url", "repo1");
MockEmptyPackage p = createRemoteEmptyPackage(src1, "testPkg");
ArchiveReplacement ar = new ArchiveReplacement(p.getArchives()[0], null /*replaced*/);
@@ -133,7 +133,7 @@
"Archive.Os=ANY\n" +
"Pkg.Revision=0\n" +
"Archive.Arch=ANY\n" +
- "Pkg.SourceUrl=http\\://repo.com/url\n" +
+ "Pkg.SourceUrl=http\\://repo.example.com/url\n" +
"'>]",
stripDate(Arrays.toString(mFile.getOutputStreams())));
@@ -145,7 +145,7 @@
/** Test we can replace and rename an Extra package. */
public void testInstall_InstallExtraArchive() throws Exception {
- SdkSource src1 = new SdkRepoSource("http://repo.com/url", "repo1");
+ SdkSource src1 = new SdkRepoSource("http://repo.example.com/url", "repo1");
MockExtraPackage newPkg = createRemoteExtraPackage(src1, "vendor1", "oldPath", 2, 1);
MockExtraPackage oldPkg = new MockExtraPackage(src1, "vendor1", "oldPath", 1, 1);
@@ -181,26 +181,28 @@
"[</sdk/extras/vendor1/oldPath/source.properties: " +
"'### Android Tool: Source of this archive.\n" +
"#...date...\n" +
- "Extra.Vendor=vendor1\n" +
+ "Extra.VendorDisplay=vendor1\n" +
"Pkg.Desc=desc\n" +
- "Pkg.DescUrl=url\n" +
- "Archive.Os=ANY\n" +
- "Pkg.Revision=2\n" +
- "Archive.Arch=ANY\n" +
"Extra.Path=oldPath\n" +
- "Pkg.SourceUrl=http\\://repo.com/url\n" +
+ "Archive.Arch=ANY\n" +
+ "Pkg.DescUrl=url\n" +
+ "Extra.NameDisplay=Vendor1 OldPath\n" +
+ "Archive.Os=ANY\n" +
+ "Pkg.SourceUrl=http\\://repo.example.com/url\n" +
+ "Pkg.Revision=2\n" +
+ "Extra.VendorId=vendor1\n" +
"'>]"),
stripDate(Arrays.toString(mFile.getOutputStreams())));
assertEquals(
- "Installing Vendor1 OldPath package, revision 2\n" +
- "Installed Vendor1 OldPath package, revision 2\n",
+ "Installing Vendor1 OldPath, revision 2\n" +
+ "Installed Vendor1 OldPath, revision 2\n",
mMon.getCapturedLog());
}
/** Test we can replace and rename an Extra package. */
public void testInstall_InstallRenamedExtraArchive() throws Exception {
- SdkSource src1 = new SdkRepoSource("http://repo.com/url", "repo1");
+ SdkSource src1 = new SdkRepoSource("http://repo.example.com/url", "repo1");
MockExtraPackage newPkg = createRemoteExtraPackage(
src1,
@@ -254,21 +256,23 @@
"[</sdk/extras/vendor1/newPath/source.properties: " +
"'### Android Tool: Source of this archive.\n" +
"#...date...\n" +
+ "Extra.VendorDisplay=vendor1\n" +
"Pkg.Desc=desc\n" +
"Extra.OldPaths=oldPath\n" +
- "Extra.Vendor=vendor1\n" +
"Extra.Path=newPath\n" +
"Archive.Arch=ANY\n" +
"Pkg.DescUrl=url\n" +
+ "Extra.NameDisplay=Vendor1 NewPath\n" +
"Archive.Os=ANY\n" +
- "Pkg.SourceUrl=http\\://repo.com/url\n" +
+ "Pkg.SourceUrl=http\\://repo.example.com/url\n" +
"Pkg.Revision=2\n" +
+ "Extra.VendorId=vendor1\n" +
"'>]"),
stripDate(Arrays.toString(mFile.getOutputStreams())));
assertEquals(
- "Installing Vendor1 NewPath package, revision 2\n" +
- "Installed Vendor1 NewPath package, revision 2\n",
+ "Installing Vendor1 NewPath, revision 2\n" +
+ "Installed Vendor1 NewPath, revision 2\n",
mMon.getCapturedLog());
}
diff --git a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/ExtraPackageTest.java b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/ExtraPackageTest_v3.java
similarity index 74%
copy from sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/ExtraPackageTest.java
copy to sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/ExtraPackageTest_v3.java
index 230e366..c895fc9 100755
--- a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/ExtraPackageTest.java
+++ b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/ExtraPackageTest_v3.java
@@ -24,7 +24,11 @@
import java.util.Arrays;
import java.util.Properties;
-public class ExtraPackageTest extends MinToolsPackageTest {
+/**
+ * Tests {@link ExtraPackage} using anddon-3.xsd: it has a {@code <path>} and {@code <vendor>}.
+ * (it lacks name-display, vendor-id and vendor-display with are in addon-4.xsd)
+ */
+public class ExtraPackageTest_v3 extends MinToolsPackageTest {
private static final char PS = File.pathSeparatorChar;
@@ -45,8 +49,8 @@
return p;
}
- @Override
- protected Properties createProps() {
+ /** Properties used to "load" the package. When saved, they become different. */
+ private Properties createLoadedProps() {
Properties props = super.createProps();
// ExtraPackage properties
@@ -60,12 +64,33 @@
return props;
}
+ /** Properties saved by the package. They differ from loaded ones in name and vendor. */
+ private Properties createSavedProps() {
+ Properties props = super.createProps();
+
+ // ExtraPackage properties
+ props.setProperty(PkgProps.EXTRA_VENDOR_ID, "vendor");
+ props.setProperty(PkgProps.EXTRA_VENDOR_DISPLAY, "vendor");
+ props.setProperty(PkgProps.EXTRA_NAME_DISPLAY, "Vendor The Path");
+ props.setProperty(PkgProps.EXTRA_PATH, "the_path");
+ props.setProperty(PkgProps.EXTRA_OLD_PATHS, "old_path1;oldpath2");
+ props.setProperty(PkgProps.EXTRA_MIN_API_LEVEL, "11");
+ props.setProperty(PkgProps.EXTRA_PROJECT_FILES,
+ "path1.jar" + PS + "dir2/jar 2.jar" + PS + "dir/3/path");
+
+ return props;
+ }
+
protected void testCreatedExtraPackage(ExtraPackage p) {
super.testCreatedPackage(p);
// Package properties
- assertEquals("vendor", p.getVendor());
+ // vendor becomes both vendor-id and vendor-display
+ assertEquals("vendor", p.getVendorId());
+ assertEquals("vendor", p.getVendorDisplay());
assertEquals("the_path", p.getPath());
+ // path and vendor are combined in the default display name
+ assertEquals("Vendor The Path", p.getDisplayName());
assertEquals("[old_path1, oldpath2]", Arrays.toString(p.getOldPaths()));
assertEquals(11, p.getMinApiLevel());
assertEquals(
@@ -77,7 +102,7 @@
@Override
public final void testCreate() {
- Properties props = createProps();
+ Properties props = createLoadedProps();
ExtraPackage p = createExtraPackage(props);
testCreatedExtraPackage(p);
@@ -85,17 +110,17 @@
@Override
public void testSaveProperties() {
- Properties props = createProps();
+ Properties props = createLoadedProps();
ExtraPackage p = createExtraPackage(props);
Properties props2 = new Properties();
p.saveProperties(props2);
- assertEquals(props2, props);
+ assertEquals(props2, createSavedProps());
}
public void testSameItemAs() {
- Properties props1 = createProps();
+ Properties props1 = createLoadedProps();
ExtraPackage p1 = createExtraPackage(props1);
assertTrue(p1.sameItemAs(p1));
@@ -144,7 +169,7 @@
}
public void testInstallId() {
- Properties props = createProps();
+ Properties props = createLoadedProps();
ExtraPackage p = createExtraPackage(props);
assertEquals("extra-vendor-the_path", p.installId());
diff --git a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/ExtraPackageTest.java b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/ExtraPackageTest_v4.java
similarity index 86%
rename from sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/ExtraPackageTest.java
rename to sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/ExtraPackageTest_v4.java
index 230e366..19e50f0 100755
--- a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/ExtraPackageTest.java
+++ b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/ExtraPackageTest_v4.java
@@ -24,7 +24,11 @@
import java.util.Arrays;
import java.util.Properties;
-public class ExtraPackageTest extends MinToolsPackageTest {
+/**
+ * Tests {@link ExtraPackage} using anddon-4.xsd:
+ * it has name-display, vendor-id and vendor-display.
+ */
+public class ExtraPackageTest_v4 extends MinToolsPackageTest {
private static final char PS = File.pathSeparatorChar;
@@ -50,7 +54,9 @@
Properties props = super.createProps();
// ExtraPackage properties
- props.setProperty(PkgProps.EXTRA_VENDOR, "vendor");
+ props.setProperty(PkgProps.EXTRA_VENDOR_ID, "the_vendor");
+ props.setProperty(PkgProps.EXTRA_VENDOR_DISPLAY, "The Company, Inc.");
+ props.setProperty(PkgProps.EXTRA_NAME_DISPLAY, "Some Extra Package");
props.setProperty(PkgProps.EXTRA_PATH, "the_path");
props.setProperty(PkgProps.EXTRA_OLD_PATHS, "old_path1;oldpath2");
props.setProperty(PkgProps.EXTRA_MIN_API_LEVEL, "11");
@@ -64,7 +70,9 @@
super.testCreatedPackage(p);
// Package properties
- assertEquals("vendor", p.getVendor());
+ assertEquals("the_vendor", p.getVendorId());
+ assertEquals("The Company, Inc.", p.getVendorDisplay());
+ assertEquals("Some Extra Package", p.getDisplayName());
assertEquals("the_path", p.getPath());
assertEquals("[old_path1, oldpath2]", Arrays.toString(p.getOldPaths()));
assertEquals(11, p.getMinApiLevel());
@@ -101,7 +109,8 @@
// different vendor, same path
Properties props2 = new Properties(props1);
- props2.setProperty(PkgProps.EXTRA_VENDOR, "vendor2");
+ props2.setProperty(PkgProps.EXTRA_VENDOR_ID, "vendor2");
+ props2.setProperty(PkgProps.EXTRA_VENDOR_DISPLAY, "Another Vendor Name");
ExtraPackage p2 = createExtraPackage(props2);
assertFalse(p1.sameItemAs(p2));
assertFalse(p2.sameItemAs(p1));
@@ -147,6 +156,6 @@
Properties props = createProps();
ExtraPackage p = createExtraPackage(props);
- assertEquals("extra-vendor-the_path", p.installId());
+ assertEquals("extra-the_vendor-the_path", p.installId());
}
}
diff --git a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/MockAddonPackage.java b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/MockAddonPackage.java
index cdf7bcc..3953f79 100755
--- a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/MockAddonPackage.java
+++ b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/MockAddonPackage.java
@@ -23,8 +23,10 @@
import com.android.sdklib.SdkConstants;
import com.android.sdklib.SystemImage;
import com.android.sdklib.io.FileOp;
+import com.android.sdklib.repository.PkgProps;
import java.util.Map;
+import java.util.Properties;
/**
* A mock {@link AddonPackage} for testing.
@@ -60,7 +62,21 @@
int revision) {
super(source,
new MockAddonTarget(name, basePlatform.getTarget(), revision),
- null /*props*/);
+ createProperties(name, basePlatform.getTarget()));
+ }
+
+ private static Properties createProperties(String name, IAndroidTarget baseTarget) {
+ String vendor = baseTarget.getVendor();
+ Properties props = new Properties();
+ props.setProperty(PkgProps.ADDON_NAME_ID, name);
+ props.setProperty(PkgProps.ADDON_NAME_DISPLAY,
+ String.format("The %1$s from %2$s", //$NON-NLS-1$
+ name, vendor));
+ props.setProperty(PkgProps.ADDON_VENDOR_ID,
+ String.format("vendor-id-%1$s", vendor)); //$NON-NLS-1$
+ props.setProperty(PkgProps.ADDON_VENDOR_DISPLAY,
+ String.format("The %1$s", vendor)); //$NON-NLS-1$
+ return props;
}
/**
diff --git a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/PackageTest.java b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/PackageTest.java
index ab560f6..5cf1c98 100755
--- a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/PackageTest.java
+++ b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/PackageTest.java
@@ -187,9 +187,9 @@
"[Android SDK Tools, revision 7, " +
"SDK Platform Android android-1, API 1, revision 2, " +
"Intel x86 Atom System Image, Android API 1, revision 4, " +
- "addon by vendor 1, Android API 1, revision 3, " +
+ "addon, Android API 1, revision 3, " +
"Broken package for API 1, " +
- "Vendor Path package, revision 5]",
+ "Vendor Path, revision 5]",
Arrays.toString(list.toArray()));
}
}
diff --git a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/SdkAddonSourceTest.java b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/SdkAddonSourceTest.java
index c11ff0d..11626e6 100755
--- a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/SdkAddonSourceTest.java
+++ b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/SdkAddonSourceTest.java
@@ -145,9 +145,9 @@
}
/**
- * Validate we can still load a valid add-on schema version 1
+ * Validate we can load a valid add-on schema version 1
*/
- public void testLoadOldXml_1() throws Exception {
+ public void testLoadAddonXml_1() throws Exception {
InputStream xmlStream = getTestResource("/com/android/sdklib/testdata/addon_sample_1.xml");
// guess the version from the XML document
@@ -171,12 +171,12 @@
// Get the packages
assertTrue(mSource._parsePackages(doc, uri, monitor));
- assertEquals("Found My First add-on by John Doe, Android API 1, revision 1\n" +
- "Found My Second add-on by John Deer, Android API 2, revision 42\n" +
- "Found This add-on has no libraries by Joe Bar, Android API 4, revision 3\n" +
- "Found G USB Driver package, revision 43 (Obsolete)\n" +
- "Found Android Vendor Extra API Dep package, revision 2 (Obsolete)\n" +
- "Found Unkown Extra package, revision 2 (Obsolete)\n",
+ assertEquals("Found My First add-on, Android API 1, revision 1\n" +
+ "Found My Second add-on, Android API 2, revision 42\n" +
+ "Found This add-on has no libraries, Android API 4, revision 3\n" +
+ "Found G USB Driver, revision 43 (Obsolete)\n" +
+ "Found Android Vendor Extra API Dep, revision 2 (Obsolete)\n" +
+ "Found Unknown Extra, revision 2 (Obsolete)\n",
monitor.getCapturedVerboseLog());
assertEquals("", monitor.getCapturedLog());
assertEquals("", monitor.getCapturedErrorLog());
@@ -199,16 +199,19 @@
ArrayList<File> extraInstall = new ArrayList<File>();
for (Package p : pkgs) {
if (p instanceof ExtraPackage) {
- extraPaths.add(((ExtraPackage) p).getPath());
- extraVendors.add(((ExtraPackage) p).getVendor());
- extraInstall.add(((ExtraPackage) p).getInstallFolder(osSdkPath, sdkManager));
+ ExtraPackage ep = (ExtraPackage) p;
+ extraPaths.add(ep.getPath());
+ extraVendors.add(ep.getVendorId() + "/" + ep.getVendorDisplay());
+ extraInstall.add(ep.getInstallFolder(osSdkPath, sdkManager));
}
}
assertEquals(
"[extra_api_dep, usb_driver, extra0000005f]",
Arrays.toString(extraPaths.toArray()));
assertEquals(
- "[android_vendor, g, vendor0000005f]",
+ "[android_vendor/android_vendor, " +
+ "g/g, " +
+ "vendor0000005f/____]",
Arrays.toString(extraVendors.toArray()));
assertEquals(
("[SDK/extras/android_vendor/extra_api_dep, " +
@@ -220,7 +223,7 @@
/**
* Validate we can still load a valid add-on schema version 2
*/
- public void testLoadOldXml_2() throws Exception {
+ public void testLoadAddonXml_2() throws Exception {
InputStream xmlStream = getTestResource("/com/android/sdklib/testdata/addon_sample_2.xml");
// guess the version from the XML document
@@ -244,12 +247,12 @@
// Get the packages
assertTrue(mSource._parsePackages(doc, uri, monitor));
- assertEquals("Found My First add-on by John Doe, Android API 1, revision 1\n" +
- "Found My Second add-on by John Deer, Android API 2, revision 42\n" +
- "Found This add-on has no libraries by Joe Bar, Android API 4, revision 3\n" +
- "Found G USB Driver package, revision 43 (Obsolete)\n" +
- "Found Android Vendor Extra API Dep package, revision 2 (Obsolete)\n" +
- "Found Unkown Extra package, revision 2 (Obsolete)\n",
+ assertEquals("Found My First add-on, Android API 1, revision 1\n" +
+ "Found My Second add-on, Android API 2, revision 42\n" +
+ "Found This add-on has no libraries, Android API 4, revision 3\n" +
+ "Found G USB Driver, revision 43 (Obsolete)\n" +
+ "Found Android Vendor Extra API Dep, revision 2 (Obsolete)\n" +
+ "Found Unknown Extra, revision 2 (Obsolete)\n",
monitor.getCapturedVerboseLog());
assertEquals("", monitor.getCapturedLog());
assertEquals("", monitor.getCapturedErrorLog());
@@ -275,8 +278,8 @@
}
assertEquals(
"[Pair [first=3, second=42], " + // for #3 "This add-on has no libraries"
- "Pair [first=0, second=0], " + // for #2 "My Second add-on"
- "Pair [first=5, second=0]]", // for #1 "My First add-on"
+ "Pair [first=0, second=0], " + // for #2 "My Second add-on"
+ "Pair [first=5, second=0]]", // for #1 "My First add-on"
Arrays.toString(layoutlibVers.toArray()));
@@ -290,16 +293,19 @@
ArrayList<File> extraInstall = new ArrayList<File>();
for (Package p : pkgs) {
if (p instanceof ExtraPackage) {
- extraPaths.add(((ExtraPackage) p).getPath());
- extraVendors.add(((ExtraPackage) p).getVendor());
- extraInstall.add(((ExtraPackage) p).getInstallFolder(osSdkPath, sdkManager));
+ ExtraPackage ep = (ExtraPackage) p;
+ extraPaths.add(ep.getPath());
+ extraVendors.add(ep.getVendorId() + "/" + ep.getVendorDisplay());
+ extraInstall.add(ep.getInstallFolder(osSdkPath, sdkManager));
}
}
assertEquals(
"[extra_api_dep, usb_driver, extra0000005f]",
Arrays.toString(extraPaths.toArray()));
assertEquals(
- "[android_vendor, g, vendor0000005f]",
+ "[android_vendor/android_vendor, " +
+ "g/g, " +
+ "vendor0000005f/____]",
Arrays.toString(extraVendors.toArray()));
assertEquals(
("[SDK/extras/android_vendor/extra_api_dep, " +
@@ -309,9 +315,9 @@
}
/**
- * Validate we can still load a valid add-on schema version 3
+ * Validate we can load a valid add-on schema version 3
*/
- public void testLoadOldXml_3() throws Exception {
+ public void testLoadAddonXml_3() throws Exception {
InputStream xmlStream = getTestResource("/com/android/sdklib/testdata/addon_sample_3.xml");
// guess the version from the XML document
@@ -335,12 +341,12 @@
// Get the packages
assertTrue(mSource._parsePackages(doc, uri, monitor));
- assertEquals("Found My First add-on by John Doe, Android API 1, revision 1\n" +
- "Found My Second add-on by John Deer, Android API 2, revision 42\n" +
- "Found This add-on has no libraries by Joe Bar, Android API 4, revision 3\n" +
- "Found G USB Driver package, revision 43 (Obsolete)\n" +
- "Found Android Vendor Extra API Dep package, revision 2 (Obsolete)\n" +
- "Found Unkown Extra package, revision 2 (Obsolete)\n",
+ assertEquals("Found My First add-on, Android API 1, revision 1\n" +
+ "Found My Second add-on, Android API 2, revision 42\n" +
+ "Found This add-on has no libraries, Android API 4, revision 3\n" +
+ "Found G USB Driver, revision 43 (Obsolete)\n" +
+ "Found Android Vendor Extra API Dep, revision 2 (Obsolete)\n" +
+ "Found Unknown Extra, revision 2 (Obsolete)\n",
monitor.getCapturedVerboseLog());
assertEquals("", monitor.getCapturedLog());
assertEquals("", monitor.getCapturedErrorLog());
@@ -366,8 +372,8 @@
}
assertEquals(
"[Pair [first=3, second=42], " + // for #3 "This add-on has no libraries"
- "Pair [first=0, second=0], " + // for #2 "My Second add-on"
- "Pair [first=5, second=0]]", // for #1 "My First add-on"
+ "Pair [first=0, second=0], " + // for #2 "My Second add-on"
+ "Pair [first=5, second=0]]", // for #1 "My First add-on"
Arrays.toString(layoutlibVers.toArray()));
@@ -385,7 +391,7 @@
ExtraPackage ep = (ExtraPackage) p;
// combine path and old-paths in the form "path [old_path1, old_path2]"
extraPaths.add(ep.getPath() + " " + Arrays.toString(ep.getOldPaths()));
- extraVendors.add(ep.getVendor());
+ extraVendors.add(ep.getVendorId() + "/" + ep.getVendorDisplay());
extraInstall.add(ep.getInstallFolder(osSdkPath, sdkManager));
ArrayList<String> filePaths = new ArrayList<String>();
@@ -401,9 +407,9 @@
"extra0000005f []]",
Arrays.toString(extraPaths.toArray()));
assertEquals(
- "[android_vendor, " +
- "g, " +
- "vendor0000005f]",
+ "[android_vendor/android_vendor, " +
+ "g/g, " +
+ "vendor0000005f/____]",
Arrays.toString(extraVendors.toArray()));
assertEquals(
("[SDK/extras/android_vendor/extra_api_dep, " +
@@ -418,6 +424,139 @@
}
/**
+ * Validate we can load a valid add-on schema version 4
+ */
+ public void testLoadAddonXml_4() throws Exception {
+ InputStream xmlStream = getTestResource("/com/android/sdklib/testdata/addon_sample_4.xml");
+
+ // guess the version from the XML document
+ int version = mSource._getXmlSchemaVersion(xmlStream);
+ assertEquals(4, version);
+
+ Boolean[] validatorFound = new Boolean[] { Boolean.FALSE };
+ String[] validationError = new String[] { null };
+ String url = "not-a-valid-url://" + SdkAddonConstants.URL_DEFAULT_FILENAME;
+
+ String uri = mSource._validateXml(xmlStream, url, version, validationError, validatorFound);
+ assertEquals(Boolean.TRUE, validatorFound[0]);
+ assertEquals(null, validationError[0]);
+ assertEquals(SdkAddonConstants.getSchemaUri(4), uri);
+
+ // Validation was successful, load the document
+ MockMonitor monitor = new MockMonitor();
+ Document doc = mSource._getDocument(xmlStream, monitor);
+ assertNotNull(doc);
+
+ // Get the packages
+ assertTrue(mSource._parsePackages(doc, uri, monitor));
+
+ assertEquals("Found My First add-on, Android API 1, revision 1\n" +
+ "Found My Second add-on, Android API 2, revision 42\n" +
+ "Found This add-on has no libraries, Android API 4, revision 3\n" +
+ "Found Random name, not an id!, revision 43 (Obsolete)\n" +
+ "Found Yet another extra, by Android, revision 2\n" +
+ "Found . -..- - .-. .-, revision 2 (Obsolete)\n",
+ monitor.getCapturedVerboseLog());
+ assertEquals("", monitor.getCapturedLog());
+ assertEquals("", monitor.getCapturedErrorLog());
+
+ // check the packages we found... we expected to find 6 packages with each at least
+ // one archive.
+ // Note the order doesn't necessary match the one from the
+ // assertEquald(getCapturedVerboseLog) because packages are sorted using the
+ // Packages' sorting order, e.g. all platforms are sorted by descending API level, etc.
+ Package[] pkgs = mSource.getPackages();
+
+ assertEquals(6, pkgs.length);
+ for (Package p : pkgs) {
+ assertTrue(p.getArchives().length >= 1);
+ }
+
+ // Check the addon packages: vendor/name id vs display
+ ArrayList<String> addonNames = new ArrayList<String>();
+ ArrayList<String> addonVendors = new ArrayList<String>();
+ for (Package p : pkgs) {
+ if (p instanceof AddonPackage) {
+ AddonPackage ap = (AddonPackage) p;
+ addonNames.add(ap.getNameId() + "/" + ap.getDisplayName());
+ addonVendors.add(ap.getVendorId() + "/" + ap.getDisplayVendor());
+ }
+ }
+ // Addons are sorted by addon/vendor id and thus their order differs from the
+ // XML or the parsed package list.
+ assertEquals(
+ "[no_libs/This add-on has no libraries, " +
+ "My_Second_add-on/My Second add-on, " +
+ "My_First_add-on/My First add-on]",
+ Arrays.toString(addonNames.toArray()));
+ assertEquals(
+ "[Joe_Bar/Joe Bar, " +
+ "John_Deer/John Deer, " +
+ "John_Doe/John Doe]",
+ Arrays.toString(addonVendors.toArray()));
+
+ // Check the layoutlib of the platform packages.
+ ArrayList<Pair<Integer, Integer>> layoutlibVers = new ArrayList<Pair<Integer,Integer>>();
+ for (Package p : pkgs) {
+ if (p instanceof AddonPackage) {
+ layoutlibVers.add(((AddonPackage) p).getLayoutlibVersion());
+ }
+ }
+ assertEquals(
+ "[Pair [first=3, second=42], " + // for #3 "This add-on has no libraries"
+ "Pair [first=0, second=0], " + // for #2 "My Second add-on"
+ "Pair [first=5, second=0]]", // for #1 "My First add-on"
+ Arrays.toString(layoutlibVers.toArray()));
+
+
+ // Check the extra packages: path, vendor, install folder, old-paths
+ final String osSdkPath = "SDK";
+ final SdkManager sdkManager = new MockEmptySdkManager(osSdkPath);
+
+ ArrayList<String> extraPaths = new ArrayList<String>();
+ ArrayList<String> extraVendors = new ArrayList<String>();
+ ArrayList<File> extraInstall = new ArrayList<File>();
+ ArrayList<ArrayList<String>> extraFilePaths = new ArrayList<ArrayList<String>>();
+ for (Package p : pkgs) {
+ if (p instanceof ExtraPackage) {
+ ExtraPackage ep = (ExtraPackage) p;
+ // combine path and old-paths in the form "path [old_path1, old_path2]"
+ extraPaths.add(ep.getPath() + " " + Arrays.toString(ep.getOldPaths()));
+ extraVendors.add(ep.getVendorId() + "/" + ep.getVendorDisplay());
+ extraInstall.add(ep.getInstallFolder(osSdkPath, sdkManager));
+
+ ArrayList<String> filePaths = new ArrayList<String>();
+ for (String filePath : ep.getProjectFiles()) {
+ filePaths.add(filePath);
+ }
+ extraFilePaths.add(filePaths);
+ }
+ }
+ // Extras are sorted by vendor-id/path and thus their order differs from the
+ // XML or the parsed package list.
+ assertEquals(
+ "[extra0000005f [], " + // for extra #3
+ "extra_api_dep [path1, old_path2, oldPath3], " + // for extra #2
+ "usb_driver []]", // for extra #1
+ Arrays.toString(extraPaths.toArray()));
+ assertEquals(
+ "[____/____, " +
+ "android_vendor/Android Vendor, " +
+ "cyclop/The big bus]",
+ Arrays.toString(extraVendors.toArray()));
+ assertEquals(
+ ("[SDK/extras/____/extra0000005f, " +
+ "SDK/extras/android_vendor/extra_api_dep, " +
+ "SDK/extras/cyclop/usb_driver]").replace('/', File.separatorChar),
+ Arrays.toString(extraInstall.toArray()));
+ assertEquals(
+ "[[], " +
+ "[v8/veggies_8.jar, root.jar, dir1/dir 2 with space/mylib.jar], " +
+ "[]]",
+ Arrays.toString(extraFilePaths.toArray()));
+ }
+
+ /**
* Returns an SdkLib file resource as a {@link ByteArrayInputStream},
* which has the advantage that we can use {@link InputStream#reset()} on it
* at any time to read it multiple times.
diff --git a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/SdkRepoSourceTest.java b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/SdkRepoSourceTest.java
index bd784e4..77e9312 100755
--- a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/SdkRepoSourceTest.java
+++ b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/SdkRepoSourceTest.java
@@ -225,15 +225,15 @@
assertEquals("Found SDK Platform Android 1.0, API 1, revision 3\n" +
"Found Documentation for Android SDK, API 1, revision 1\n" +
- "Found My First add-on by John Doe, Android API 1, revision 1\n" +
+ "Found My First add-on, Android API 1, revision 1\n" +
"Found SDK Platform Android 1.1, API 2, revision 12\n" +
- "Found My Second add-on by John Deer, Android API 2, revision 42\n" +
+ "Found My Second add-on, Android API 2, revision 42\n" +
"Found SDK Platform Android Pastry Preview, revision 3\n" +
"Found Android SDK Tools, revision 1\n" +
"Found Documentation for Android SDK, API 2, revision 42\n" +
"Found Android SDK Tools, revision 42\n" +
- "Found This add-on has no libraries by Joe Bar, Android API 4, revision 3\n" +
- "Found Usb Driver package, revision 43\n",
+ "Found This add-on has no libraries, Android API 4, revision 3\n" +
+ "Found Usb Driver, revision 43\n",
monitor.getCapturedVerboseLog());
assertEquals("", monitor.getCapturedLog());
assertEquals("", monitor.getCapturedErrorLog());
@@ -256,16 +256,17 @@
ArrayList<File> extraInstall = new ArrayList<File>();
for (Package p : pkgs) {
if (p instanceof ExtraPackage) {
- extraPaths.add(((ExtraPackage) p).getPath());
- extraVendors.add(((ExtraPackage) p).getVendor());
- extraInstall.add(((ExtraPackage) p).getInstallFolder(osSdkPath, sdkManager));
+ ExtraPackage ep = (ExtraPackage) p;
+ extraPaths.add(ep.getPath());
+ extraVendors.add(ep.getVendorId() + "/" + ep.getVendorDisplay());
+ extraInstall.add(ep.getInstallFolder(osSdkPath, sdkManager));
}
}
assertEquals(
"[usb_driver]",
Arrays.toString(extraPaths.toArray()));
assertEquals(
- "[]",
+ "[/]",
Arrays.toString(extraVendors.toArray()));
assertEquals(
"[SDK/extras/usb_driver]".replace('/', File.separatorChar),
@@ -302,16 +303,16 @@
assertEquals("Found SDK Platform Android 1.0, API 1, revision 3\n" +
"Found Documentation for Android SDK, API 1, revision 1\n" +
- "Found My First add-on by John Doe, Android API 1, revision 1\n" +
+ "Found My First add-on, Android API 1, revision 1\n" +
"Found SDK Platform Android 1.1, API 2, revision 12\n" +
- "Found My Second add-on by John Deer, Android API 2, revision 42\n" +
+ "Found My Second add-on, Android API 2, revision 42\n" +
"Found SDK Platform Android Pastry Preview, revision 3\n" +
"Found Android SDK Tools, revision 1\n" +
"Found Documentation for Android SDK, API 2, revision 42\n" +
"Found Android SDK Tools, revision 42\n" +
- "Found This add-on has no libraries by Joe Bar, Android API 4, revision 3\n" +
- "Found Usb Driver package, revision 43 (Obsolete)\n" +
- "Found Extra API Dep package, revision 2 (Obsolete)\n" +
+ "Found This add-on has no libraries, Android API 4, revision 3\n" +
+ "Found Usb Driver, revision 43 (Obsolete)\n" +
+ "Found Extra API Dep, revision 2 (Obsolete)\n" +
"Found Samples for SDK API 14, revision 24 (Obsolete)\n",
monitor.getCapturedVerboseLog());
assertEquals("", monitor.getCapturedLog());
@@ -335,16 +336,17 @@
ArrayList<File> extraInstall = new ArrayList<File>();
for (Package p : pkgs) {
if (p instanceof ExtraPackage) {
- extraPaths.add(((ExtraPackage) p).getPath());
- extraVendors.add(((ExtraPackage) p).getVendor());
- extraInstall.add(((ExtraPackage) p).getInstallFolder(osSdkPath, sdkManager));
+ ExtraPackage ep = (ExtraPackage) p;
+ extraPaths.add(ep.getPath());
+ extraVendors.add(ep.getVendorId() + "/" + ep.getVendorDisplay());
+ extraInstall.add(ep.getInstallFolder(osSdkPath, sdkManager));
}
}
assertEquals(
"[extra_api_dep, usb_driver]",
Arrays.toString(extraPaths.toArray()));
assertEquals(
- "[, ]",
+ "[/, /]",
Arrays.toString(extraVendors.toArray()));
assertEquals(
"[SDK/extras/extra_api_dep, SDK/extras/usb_driver]".replace('/', File.separatorChar),
@@ -387,8 +389,8 @@
"Found Documentation for Android SDK, API 2, revision 42\n" +
"Found Android SDK Tools, revision 42\n" +
"Found Android SDK Platform-tools, revision 3\n" +
- "Found A USB Driver package, revision 43 (Obsolete)\n" +
- "Found Android Vendor Extra API Dep package, revision 2 (Obsolete)\n" +
+ "Found A USB Driver, revision 43 (Obsolete)\n" +
+ "Found Android Vendor Extra API Dep, revision 2 (Obsolete)\n" +
"Found Samples for SDK API 14, revision 24 (Obsolete)\n",
monitor.getCapturedVerboseLog());
assertEquals("", monitor.getCapturedLog());
@@ -412,16 +414,17 @@
ArrayList<File> extraInstall = new ArrayList<File>();
for (Package p : pkgs) {
if (p instanceof ExtraPackage) {
- extraPaths.add(((ExtraPackage) p).getPath());
- extraVendors.add(((ExtraPackage) p).getVendor());
- extraInstall.add(((ExtraPackage) p).getInstallFolder(osSdkPath, sdkManager));
+ ExtraPackage ep = (ExtraPackage) p;
+ extraPaths.add(ep.getPath());
+ extraVendors.add(ep.getVendorId() + "/" + ep.getVendorDisplay());
+ extraInstall.add(ep.getInstallFolder(osSdkPath, sdkManager));
}
}
assertEquals(
"[extra_api_dep, usb_driver]",
Arrays.toString(extraPaths.toArray()));
assertEquals(
- "[android_vendor, a]",
+ "[android_vendor/android_vendor, a/a]",
Arrays.toString(extraVendors.toArray()));
assertEquals(
"[SDK/extras/android_vendor/extra_api_dep, SDK/extras/a/usb_driver]"
@@ -465,8 +468,8 @@
"Found Documentation for Android SDK, API 2, revision 42\n" +
"Found Android SDK Tools, revision 42\n" +
"Found Android SDK Platform-tools, revision 3\n" +
- "Found A USB Driver package, revision 43 (Obsolete)\n" +
- "Found Android Vendor Extra API Dep package, revision 2 (Obsolete)\n" +
+ "Found A USB Driver, revision 43 (Obsolete)\n" +
+ "Found Android Vendor Extra API Dep, revision 2 (Obsolete)\n" +
"Found Samples for SDK API 14, revision 24 (Obsolete)\n",
monitor.getCapturedVerboseLog());
assertEquals("", monitor.getCapturedLog());
@@ -508,12 +511,13 @@
ArrayList<ArrayList<String>> extraFilePaths = new ArrayList<ArrayList<String>>();
for (Package p : pkgs) {
if (p instanceof ExtraPackage) {
- extraPaths.add(((ExtraPackage) p).getPath());
- extraVendors.add(((ExtraPackage) p).getVendor());
- extraInstall.add(((ExtraPackage) p).getInstallFolder(osSdkPath, sdkManager));
+ ExtraPackage ep = (ExtraPackage) p;
+ extraPaths.add(ep.getPath());
+ extraVendors.add(ep.getVendorId() + "/" + ep.getVendorDisplay());
+ extraInstall.add(ep.getInstallFolder(osSdkPath, sdkManager));
ArrayList<String> filePaths = new ArrayList<String>();
- for (String filePath : ((ExtraPackage) p).getProjectFiles()) {
+ for (String filePath : ep.getProjectFiles()) {
filePaths.add(filePath);
}
extraFilePaths.add(filePaths);
@@ -523,7 +527,7 @@
"[extra_api_dep, usb_driver]",
Arrays.toString(extraPaths.toArray()));
assertEquals(
- "[android_vendor, a]",
+ "[android_vendor/android_vendor, a/a]",
Arrays.toString(extraVendors.toArray()));
assertEquals(
"[SDK/extras/android_vendor/extra_api_dep, SDK/extras/a/usb_driver]"
@@ -575,8 +579,8 @@
"Found Documentation for Android SDK, API 2, revision 42\n" +
"Found Android SDK Tools, revision 42\n" +
"Found Android SDK Platform-tools, revision 3\n" +
- "Found A USB Driver package, revision 43 (Obsolete)\n" +
- "Found Android Vendor Extra API Dep package, revision 2 (Obsolete)\n" +
+ "Found A USB Driver, revision 43 (Obsolete)\n" +
+ "Found Android Vendor Extra API Dep, revision 2 (Obsolete)\n" +
"Found Samples for SDK API 14, revision 24 (Obsolete)\n" +
"Found ARM EABI System Image, Android API 42, revision 12\n" +
"Found Sources for Android SDK, API 42, revision 12\n",
@@ -631,7 +635,7 @@
ExtraPackage ep = (ExtraPackage) p;
// combine path and old-paths in the form "path [old_path1, old_path2]"
extraPaths.add(ep.getPath() + " " + Arrays.toString(ep.getOldPaths()));
- extraVendors.add(ep.getVendor());
+ extraVendors.add(ep.getVendorId() + "/" + ep.getVendorDisplay());
extraInstall.add(ep.getInstallFolder(osSdkPath, sdkManager));
ArrayList<String> filePaths = new ArrayList<String>();
@@ -646,8 +650,8 @@
"usb_driver []]",
Arrays.toString(extraPaths.toArray()));
assertEquals(
- "[android_vendor, " +
- "a]",
+ "[android_vendor/android_vendor, " +
+ "a/a]",
Arrays.toString(extraVendors.toArray()));
assertEquals(
("[SDK/extras/android_vendor/extra_api_dep, " +
@@ -689,6 +693,147 @@
}
/**
+ * Validate what we can load from repository in schema version 6
+ */
+ public void testLoadXml_6() throws Exception {
+ InputStream xmlStream = getTestResource(
+ "/com/android/sdklib/testdata/repository_sample_6.xml");
+
+ // guess the version from the XML document
+ int version = mSource._getXmlSchemaVersion(xmlStream);
+ assertEquals(6, version);
+
+ Boolean[] validatorFound = new Boolean[] { Boolean.FALSE };
+ String[] validationError = new String[] { null };
+ String url = "not-a-valid-url://" + SdkRepoConstants.URL_DEFAULT_FILENAME;
+
+ String uri = mSource._validateXml(xmlStream, url, version, validationError, validatorFound);
+ assertEquals(Boolean.TRUE, validatorFound[0]);
+ assertEquals(null, validationError[0]);
+ assertEquals(SdkRepoConstants.getSchemaUri(6), uri);
+
+ // Validation was successful, load the document
+ MockMonitor monitor = new MockMonitor();
+ Document doc = mSource._getDocument(xmlStream, monitor);
+ assertNotNull(doc);
+
+ // Get the packages
+ assertTrue(mSource._parsePackages(doc, uri, monitor));
+
+ assertEquals("Found SDK Platform Android 1.0, API 1, revision 3\n" +
+ "Found Documentation for Android SDK, API 1, revision 1\n" +
+ "Found Sources for Android SDK, API 1, revision 1\n" +
+ "Found SDK Platform Android 1.1, API 2, revision 12\n" +
+ "Found Intel x86 Atom System Image, Android API 2, revision 1\n" +
+ "Found ARM EABI v7a System Image, Android API 2, revision 2\n" +
+ "Found Sources for Android SDK, API 2, revision 2\n" +
+ "Found SDK Platform Android Pastry Preview, revision 3\n" +
+ "Found Android SDK Tools, revision 1\n" +
+ "Found Documentation for Android SDK, API 2, revision 42\n" +
+ "Found Android SDK Tools, revision 42\n" +
+ "Found Android SDK Platform-tools, revision 3\n" +
+ "Found Samples for SDK API 14, revision 24 (Obsolete)\n" +
+ "Found ARM EABI System Image, Android API 42, revision 12\n" +
+ "Found Sources for Android SDK, API 42, revision 12\n",
+ monitor.getCapturedVerboseLog());
+ assertEquals("", monitor.getCapturedLog());
+ assertEquals("", monitor.getCapturedErrorLog());
+
+ // check the packages we found... we expected to find 13 packages with each at least
+ // one archive.
+ // Note the order doesn't necessary match the one from the
+ // assertEquald(getCapturedVerboseLog) because packages are sorted using the
+ // Packages' sorting order, e.g. all platforms are sorted by descending API level, etc.
+ Package[] pkgs = mSource.getPackages();
+
+ assertEquals(15, pkgs.length);
+ for (Package p : pkgs) {
+ assertTrue(p.getArchives().length >= 1);
+ }
+
+ // Check the layoutlib & included-abi of the platform packages.
+ ArrayList<Pair<Integer, Integer>> layoutlibVers = new ArrayList<Pair<Integer,Integer>>();
+ ArrayList<String> includedAbi = new ArrayList<String>();
+ for (Package p : pkgs) {
+ if (p instanceof PlatformPackage) {
+ layoutlibVers.add(((PlatformPackage) p).getLayoutlibVersion());
+ String abi = ((PlatformPackage) p).getIncludedAbi();
+ includedAbi.add(abi == null ? "(null)" : abi);
+ }
+ }
+ assertEquals(
+ "[Pair [first=1, second=0], " + // platform API 5 preview
+ "Pair [first=5, second=31415], " + // platform API 2
+ "Pair [first=5, second=0]]", // platform API 1
+ Arrays.toString(layoutlibVers.toArray()));
+ assertEquals(
+ "[(null), " + // platform API 5 preview
+ "x86, " + // platform API 2
+ "armeabi]", // platform API 1
+ Arrays.toString(includedAbi.toArray()));
+
+ // Check the extra packages path, vendor, install folder, project-files, old-paths
+
+ final String osSdkPath = "SDK";
+ final SdkManager sdkManager = new MockEmptySdkManager(osSdkPath);
+
+ ArrayList<String> extraPaths = new ArrayList<String>();
+ ArrayList<String> extraVendors = new ArrayList<String>();
+ ArrayList<File> extraInstall = new ArrayList<File>();
+ ArrayList<ArrayList<String>> extraFilePaths = new ArrayList<ArrayList<String>>();
+ for (Package p : pkgs) {
+ if (p instanceof ExtraPackage) {
+ ExtraPackage ep = (ExtraPackage) p;
+ // combine path and old-paths in the form "path [old_path1, old_path2]"
+ extraPaths.add(ep.getPath() + " " + Arrays.toString(ep.getOldPaths()));
+ extraVendors.add(ep.getVendorId() + "/" + ep.getVendorDisplay());
+ extraInstall.add(ep.getInstallFolder(osSdkPath, sdkManager));
+
+ ArrayList<String> filePaths = new ArrayList<String>();
+ for (String filePath : ep.getProjectFiles()) {
+ filePaths.add(filePath);
+ }
+ extraFilePaths.add(filePaths);
+ }
+ }
+
+ // There are no extra packages anymore in repository-6
+ assertEquals("[]", Arrays.toString(extraPaths.toArray()));
+ assertEquals("[]", Arrays.toString(extraVendors.toArray()));
+ assertEquals("[]", Arrays.toString(extraInstall.toArray()));
+ assertEquals("[]", Arrays.toString(extraFilePaths.toArray()));
+
+ // Check the system-image packages
+ ArrayList<String> sysImgVersionAbi = new ArrayList<String>();
+ for (Package p : pkgs) {
+ if (p instanceof SystemImagePackage) {
+ SystemImagePackage sip = (SystemImagePackage) p;
+ String v = sip.getVersion().getApiString();
+ String a = sip.getAbi();
+ sysImgVersionAbi.add(String.format("%1$s %2$s", v, a)); //$NON-NLS-1$
+ }
+ }
+ assertEquals(
+ "[42 armeabi, " +
+ "2 armeabi-v7a, " +
+ "2 x86]",
+ Arrays.toString(sysImgVersionAbi.toArray()));
+
+ // Check the source packages
+ ArrayList<String> sourceVersion = new ArrayList<String>();
+ for (Package p : pkgs) {
+ if (p instanceof SourcePackage) {
+ SourcePackage sp = (SourcePackage) p;
+ String v = sp.getVersion().getApiString();
+ sourceVersion.add(v);
+ }
+ }
+ assertEquals(
+ "[42, 2, 1]",
+ Arrays.toString(sourceVersion.toArray()));
+ }
+
+ /**
* Returns an SdkLib file resource as a {@link ByteArrayInputStream},
* which has the advantage that we can use {@link InputStream#reset()} on it
* at any time to read it multiple times.
diff --git a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/repository/ValidateAddonXmlTest.java b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/repository/ValidateAddonXmlTest.java
index c90fc90..d88d566 100755
--- a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/repository/ValidateAddonXmlTest.java
+++ b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/repository/ValidateAddonXmlTest.java
@@ -120,7 +120,7 @@
handler.verify();
}
- /** Validate a valid sample using namespace version 2 using an InputStream */
+ /** Validate a valid sample using namespace version 3 using an InputStream */
public void testValidateLocalAddonFile3() throws Exception {
InputStream xmlStream = this.getClass().getResourceAsStream(
"/com/android/sdklib/testdata/addon_sample_3.xml");
@@ -132,6 +132,18 @@
handler.verify();
}
+ /** Validate a valid sample using namespace version 4 using an InputStream */
+ public void testValidateLocalAddonFile4() throws Exception {
+ InputStream xmlStream = this.getClass().getResourceAsStream(
+ "/com/android/sdklib/testdata/addon_sample_4.xml");
+ Source source = new StreamSource(xmlStream);
+
+ CaptureErrorHandler handler = new CaptureErrorHandler();
+ Validator validator = getAddonValidator(4, handler);
+ validator.validate(source);
+ handler.verify();
+ }
+
// IMPORTANT: each time you add a test here, you should add a corresponding
// test in SdkAddonSourceTest to validate the XML content is parsed correctly.
@@ -148,7 +160,9 @@
OPEN_TAG_ADDON +
"<r:license id=\"lic1\"> some license </r:license> " +
"<r:add-on> <r:uses-license ref=\"lic1\" /> <r:revision>1</r:revision> " +
- "<r:name>AddonName</r:name> <r:vendor>AddonVendor</r:vendor> <r:api-level>42</r:api-level> " +
+ "<r:name-id>AddonName</r:name-id> <r:name-display>The Addon Name</r:name-display> " +
+ "<r:vendor-id>AddonVendor</r:vendor-id> <r:vendor-display>The Addon Vendor</r:vendor-display> " +
+ "<r:api-level>42</r:api-level> " +
"<r:codename>Addons do not support codenames</r:codenames> " +
"<r:libs><r:lib><r:name>com.example.LibName</r:name></r:lib></r:libs> " +
"<r:archives> <r:archive os=\"any\"> <r:size>1</r:size> <r:checksum>2822ae37115ebf13412bbef91339ee0d9454525e</r:checksum> " +
@@ -170,4 +184,29 @@
// If we get here, the validator has not failed as we expected it to.
fail();
}
+
+ /** A document with a slash in an extra path. */
+ public void testExtraPathWithSlash() throws Exception {
+ String document = "<?xml version=\"1.0\"?>" +
+ OPEN_TAG_ADDON +
+ "<r:extra> <r:revision>1</r:revision> <r:path>path/cannot\\contain\\segments</r:path> " +
+ "<r:archives> <r:archive os=\"any\"> <r:size>1</r:size> <r:checksum>2822ae37115ebf13412bbef91339ee0d9454525e</r:checksum> " +
+ "<r:url>url</r:url> </r:archive> </r:archives> </r:extra>" +
+ CLOSE_TAG_ADDON;
+
+ Source source = new StreamSource(new StringReader(document));
+
+ // don't capture the validator errors, we want it to fail and catch the exception
+ Validator validator = getAddonValidator(SdkAddonConstants.NS_LATEST_VERSION, null);
+ try {
+ validator.validate(source);
+ } catch (SAXParseException e) {
+ // We expect a parse error referring to this grammar rule
+ assertRegex("cvc-pattern-valid: Value 'path/cannot\\\\contain\\\\segments' is not facet-valid with respect to pattern.*",
+ e.getMessage());
+ return;
+ }
+ // If we get here, the validator has not failed as we expected it to.
+ fail();
+ }
}
diff --git a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/repository/ValidateRepositoryXmlTest.java b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/repository/ValidateRepositoryXmlTest.java
index 2752c32..ce21650 100755
--- a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/repository/ValidateRepositoryXmlTest.java
+++ b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/repository/ValidateRepositoryXmlTest.java
@@ -298,12 +298,11 @@
fail();
}
- /** A document a slash in an extra path. */
+ /** The latest XSD repository-6 should fail when an 'extra' is present. */
public void testExtraPathWithSlash() throws Exception {
- // we define a license named "lic1" and then reference "lic2" instead
String document = "<?xml version=\"1.0\"?>" +
OPEN_TAG_REPO +
- "<r:extra> <r:revision>1</r:revision> <r:path>path/cannot\\contain\\segments</r:path> " +
+ "<r:extra> <r:revision>1</r:revision> <r:path>path</r:path> " +
"<r:archives> <r:archive os=\"any\"> <r:size>1</r:size> <r:checksum>2822ae37115ebf13412bbef91339ee0d9454525e</r:checksum> " +
"<r:url>url</r:url> </r:archive> </r:archives> </r:extra>" +
CLOSE_TAG_REPO;
@@ -316,7 +315,7 @@
validator.validate(source);
} catch (SAXParseException e) {
// We expect a parse error referring to this grammar rule
- assertRegex("cvc-pattern-valid: Value 'path/cannot\\\\contain\\\\segments' is not facet-valid with respect to pattern.*",
+ assertRegex("cvc-complex-type.2.4.a: Invalid content was found starting with element 'r:extra'.*",
e.getMessage());
return;
}
diff --git a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/testdata/addon_sample_4.xml b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/testdata/addon_sample_4.xml
new file mode 100755
index 0000000..6fba439
--- /dev/null
+++ b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/testdata/addon_sample_4.xml
@@ -0,0 +1,203 @@
+<?xml version="1.0"?>
+<!--
+ * 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.
+-->
+<sdk:sdk-addon
+ xmlns:sdk="http://schemas.android.com/sdk/android/addon/4">
+
+ <!-- Define a couple of licenses. These will be referenced by uses-license later. -->
+
+ <sdk:license type="text" id="license1">
+ This is the license
+ for this platform.
+ </sdk:license>
+
+ <sdk:license id="license2">
+ Licenses are only of type 'text' right now, so this is implied.
+ </sdk:license>
+
+ <!-- Inner elements must be either platform, add-on, doc or tool.
+ There can be 0 or more of each, in any order. -->
+
+ <sdk:add-on>
+ <sdk:name-id>My_First_add-on</sdk:name-id>
+ <sdk:name-display>My First add-on</sdk:name-display>
+
+ <sdk:vendor-id>John_Doe</sdk:vendor-id>
+ <sdk:vendor-display>John Doe</sdk:vendor-display>
+
+ <sdk:api-level>1</sdk:api-level>
+ <sdk:revision>1</sdk:revision>
+ <sdk:uses-license ref="license2" />
+ <sdk:description>Some optional description</sdk:description>
+ <sdk:desc-url>http://www.example.com/myfirstaddon</sdk:desc-url>
+ <sdk:archives>
+ <sdk:archive os="any">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>http://www.example.com/add-ons/first.zip</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ <!-- The libs node is mandatory, however it can be empty. -->
+ <sdk:libs>
+ <sdk:lib>
+ <sdk:name>android.blah.somelib</sdk:name>
+ <sdk:description>The description for this library.</sdk:description>
+ </sdk:lib>
+ <sdk:lib>
+ <!-- sdk:description is optional, name is not -->
+ <sdk:name>com.android.mymaps</sdk:name>
+ </sdk:lib>
+ </sdk:libs>
+ <sdk:layoutlib>
+ <sdk:api>5</sdk:api>
+ <sdk:revision>0</sdk:revision>
+ </sdk:layoutlib>
+ </sdk:add-on>
+
+ <sdk:add-on>
+ <sdk:name-id>My_Second_add-on</sdk:name-id>
+ <sdk:name-display>My Second add-on</sdk:name-display>
+
+ <sdk:vendor-id>John_Deer</sdk:vendor-id>
+ <sdk:vendor-display>John Deer</sdk:vendor-display>
+
+ <sdk:api-level>2</sdk:api-level>
+ <sdk:revision>42</sdk:revision>
+ <sdk:archives>
+ <sdk:archive os="windows">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/second-42-win.zip</sdk:url>
+ </sdk:archive>
+ <sdk:archive os="linux">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/second-42-linux.tar.bz2</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ <sdk:libs>
+ <sdk:lib>
+ <sdk:name>android.blah.somelib</sdk:name>
+ <sdk:description>The description for this library.</sdk:description>
+ </sdk:lib>
+ <sdk:lib>
+ <sdk:name>com.android.mymaps</sdk:name>
+ </sdk:lib>
+ </sdk:libs>
+ <sdk:uses-license ref="license2" />
+ <!-- No layoutlib element in this package. It's optional. -->
+ </sdk:add-on>
+
+ <sdk:add-on>
+ <sdk:name-id>no_libs</sdk:name-id>
+ <sdk:name-display>This add-on has no libraries</sdk:name-display>
+
+ <sdk:vendor-id>Joe_Bar</sdk:vendor-id>
+ <sdk:vendor-display>Joe Bar</sdk:vendor-display>
+
+ <sdk:uses-license ref="license2" />
+ <sdk:api-level>4</sdk:api-level>
+ <sdk:revision>3</sdk:revision>
+ <sdk:archives>
+ <sdk:archive os="any" arch="any">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/imnotanarchiveimadoctorjim.zip</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ <!-- The libs node is mandatory, however it can be empty. -->
+ <sdk:libs />
+ <sdk:layoutlib>
+ <sdk:api>3</sdk:api>
+ <sdk:revision>42</sdk:revision>
+ </sdk:layoutlib>
+ </sdk:add-on>
+
+ <sdk:extra>
+ <sdk:name-display>Random name, not an id!</sdk:name-display>
+
+ <sdk:vendor-id>cyclop</sdk:vendor-id>
+ <sdk:vendor-display>The big bus</sdk:vendor-display>
+
+ <sdk:path>usb_driver</sdk:path>
+ <sdk:uses-license ref="license2" />
+ <sdk:revision>43</sdk:revision>
+ <sdk:archives>
+ <sdk:archive os="any" arch="any">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/extraduff.zip</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ <sdk:description>An Extra package for the USB driver, it will install in $SDK/usb_driver</sdk:description>
+ <sdk:desc-url>http://www.example.com/extra.html</sdk:desc-url>
+ <sdk:min-tools-rev>3</sdk:min-tools-rev>
+ <sdk:obsolete/>
+ </sdk:extra>
+
+ <sdk:extra>
+ <sdk:name-display>Yet another extra, by Android</sdk:name-display>
+
+ <sdk:vendor-id>android_vendor</sdk:vendor-id>
+ <sdk:vendor-display>Android Vendor</sdk:vendor-display>
+
+ <sdk:path>extra_api_dep</sdk:path>
+ <sdk:uses-license ref="license2" />
+ <sdk:revision>2</sdk:revision>
+ <sdk:archives>
+ <sdk:archive os="any" arch="any">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/extra_mega_duff.zip</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ <sdk:description>Some extra package that has a min-api-level of 42</sdk:description>
+ <sdk:desc-url>http://www.example.com/extra.html</sdk:desc-url>
+ <sdk:min-tools-rev>3</sdk:min-tools-rev>
+ <sdk:min-api-level>42</sdk:min-api-level>
+ <sdk:project-files>
+ <sdk:path>v8/veggies_8.jar</sdk:path>
+ <sdk:path>root.jar</sdk:path>
+ <sdk:path>dir1/dir 2 with space/mylib.jar</sdk:path>
+ </sdk:project-files>
+ <sdk:old-paths>path1;old_path2;oldPath3</sdk:old-paths>
+ </sdk:extra>
+
+ <sdk:extra>
+ <sdk:name-display>. -..- - .-. .-</sdk:name-display>
+
+ <sdk:vendor-id>____</sdk:vendor-id>
+ <sdk:vendor-display>____</sdk:vendor-display>
+
+ <sdk:path>____</sdk:path>
+ <sdk:uses-license ref="license2" />
+ <sdk:revision>2</sdk:revision>
+ <sdk:archives>
+ <sdk:archive os="any" arch="any">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/extra_mega_duff.zip</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ <sdk:description>Some extra package that has a min-api-level of 42</sdk:description>
+ <sdk:desc-url>http://www.example.com/extra.html</sdk:desc-url>
+ <sdk:min-tools-rev>3</sdk:min-tools-rev>
+ <sdk:min-api-level>42</sdk:min-api-level>
+ <sdk:obsolete></sdk:obsolete>
+ <!-- No project-files element in this package. -->
+ </sdk:extra>
+
+</sdk:sdk-addon>
diff --git a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/testdata/repository_sample_6.xml b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/testdata/repository_sample_6.xml
new file mode 100755
index 0000000..f29ebdf
--- /dev/null
+++ b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/testdata/repository_sample_6.xml
@@ -0,0 +1,312 @@
+<?xml version="1.0"?>
+<!--
+ * Copyright (C) 2010 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.
+-->
+<sdk:sdk-repository
+ xmlns:sdk="http://schemas.android.com/sdk/android/repository/6">
+
+ <!-- Define a couple of licenses. These will be referenced by uses-license later. -->
+
+ <sdk:license type="text" id="license1">
+ This is the license
+ for this platform.
+ </sdk:license>
+
+ <sdk:license id="license2">
+ Licenses are only of type 'text' right now, so this is implied.
+ </sdk:license>
+
+ <!-- Inner elements must be either platform, add-on, doc or tool.
+ There can be 0 or more of each, in any order. -->
+
+ <sdk:platform>
+ <sdk:version>1.0</sdk:version>
+ <sdk:api-level>1</sdk:api-level>
+ <sdk:revision>3</sdk:revision>
+ <sdk:uses-license ref="license1" />
+ <sdk:description>Some optional description</sdk:description>
+ <sdk:desc-url>http://www.example.com/platform1.html</sdk:desc-url>
+ <sdk:release-note>This is an optional release note
+ for this package. It's a free multi-line text.
+ </sdk:release-note>
+ <sdk:release-url>http://some/url/for/the/release/note.html</sdk:release-url>
+ <sdk:min-tools-rev>2</sdk:min-tools-rev>
+ <!-- The archives node is mandatory and it cannot be empty. -->
+ <sdk:archives>
+ <sdk:archive os="any">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>http://www.example.com/files/plat1.zip</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ <sdk:layoutlib>
+ <sdk:api>5</sdk:api>
+ <sdk:revision>0</sdk:revision>
+ </sdk:layoutlib>
+ <sdk:included-abi>armeabi</sdk:included-abi>
+ </sdk:platform>
+
+ <sdk:doc>
+ <sdk:api-level>1</sdk:api-level>
+ <sdk:revision>1</sdk:revision>
+ <!-- the license element is not mandatory. -->
+ <sdk:description>Some optional description</sdk:description>
+ <sdk:desc-url>http://www.example.com/docs.html</sdk:desc-url>
+ <sdk:archives>
+ <sdk:archive os="any">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>http://www.example.com/docs/docs1.zip</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ </sdk:doc>
+
+ <sdk:source>
+ <sdk:api-level>1</sdk:api-level>
+ <sdk:revision>1</sdk:revision>
+ <sdk:archives>
+ <sdk:archive os="any">
+ <sdk:size>65535</sdk:size>
+ <sdk:checksum type="sha1">1234ae37115ebf13412bbef91339ee0d94541234</sdk:checksum>
+ <sdk:url>http://www.example.com/plat1/sources1.zip</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ </sdk:source>
+
+ <sdk:platform>
+ <sdk:version>1.1</sdk:version>
+ <sdk:api-level>2</sdk:api-level>
+ <sdk:revision>12</sdk:revision>
+ <sdk:uses-license ref="license1" />
+ <!-- sdk:description and sdk:desc-url are optional -->
+ <sdk:archives>
+ <sdk:archive os="windows">
+ <!-- arch attribute is optional -->
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/platform-2-12-win.zip</sdk:url>
+ </sdk:archive>
+ <sdk:archive os="macosx" arch="any">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/platform-2-12-mac.zip</sdk:url>
+ </sdk:archive>
+ <sdk:archive os="macosx" arch="ppc">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/platform-2-12-mac.zip</sdk:url>
+ </sdk:archive>
+ <sdk:archive os="linux" arch="x86">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/platform-2-12-linux.tar.bz2</sdk:url>
+ </sdk:archive>
+ <sdk:archive os="linux" arch="x86_64">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/platform-2-12-linux.tar.bz2</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ <sdk:layoutlib>
+ <sdk:api>5</sdk:api>
+ <sdk:revision>31415</sdk:revision>
+ </sdk:layoutlib>
+ <sdk:included-abi>x86</sdk:included-abi>
+ </sdk:platform>
+
+ <sdk:system-image>
+ <sdk:api-level>2</sdk:api-level>
+ <sdk:revision>1</sdk:revision>
+ <sdk:abi>x86</sdk:abi>
+ <sdk:archives>
+ <sdk:archive os="any">
+ <sdk:size>65535</sdk:size>
+ <sdk:checksum type="sha1">1234ae37115ebf13412bbef91339ee0d94541234</sdk:checksum>
+ <sdk:url>http://www.example.com/plat1/x86/image1.zip</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ </sdk:system-image>
+
+ <sdk:system-image>
+ <sdk:api-level>2</sdk:api-level>
+ <sdk:revision>2</sdk:revision>
+ <sdk:abi>armeabi-v7a</sdk:abi>
+ <sdk:archives>
+ <sdk:archive os="any">
+ <sdk:size>65534</sdk:size>
+ <sdk:checksum type="sha1">1234ae37115ebf13412bbef91339ee0d94541234</sdk:checksum>
+ <sdk:url>http://www.example.com/plat1/armv7/image2.zip</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ </sdk:system-image>
+
+ <sdk:source>
+ <sdk:api-level>2</sdk:api-level>
+ <sdk:revision>2</sdk:revision>
+ <sdk:archives>
+ <sdk:archive os="any">
+ <sdk:size>65534</sdk:size>
+ <sdk:checksum type="sha1">1234ae37115ebf13412bbef91339ee0d94541234</sdk:checksum>
+ <sdk:url>http://www.example.com/plat1/sources2.zip</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ </sdk:source>
+
+ <sdk:platform>
+ <sdk:version>Pastry</sdk:version>
+ <sdk:api-level>5</sdk:api-level>
+ <sdk:codename>Pastry</sdk:codename>
+ <sdk:revision>3</sdk:revision>
+ <sdk:uses-license ref="license1" />
+ <sdk:description>Preview version for Pastry</sdk:description>
+ <sdk:desc-url>http://www.example.com/platform1.html</sdk:desc-url>
+ <!-- The archives node is mandatory and it cannot be empty. -->
+ <sdk:archives>
+ <sdk:archive os="any">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>http://www.example.com/files/plat1.zip</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ <sdk:layoutlib>
+ <sdk:api>1</sdk:api>
+ </sdk:layoutlib>
+ </sdk:platform>
+
+ <sdk:tool>
+ <sdk:revision>1</sdk:revision>
+ <sdk:description>Some optional description</sdk:description>
+ <sdk:desc-url>http://www.example.com/tools.html</sdk:desc-url>
+ <sdk:uses-license ref="license1" />
+ <sdk:min-platform-tools-rev>4</sdk:min-platform-tools-rev>
+ <sdk:archives>
+ <sdk:archive os="any">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>http://www.example.com/files/tools1.zip</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ </sdk:tool>
+
+ <sdk:doc>
+ <sdk:api-level>2</sdk:api-level>
+ <sdk:revision>42</sdk:revision>
+ <sdk:uses-license ref="license2" />
+ <sdk:archives>
+ <sdk:archive os="windows">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/docs/2.zip</sdk:url>
+ </sdk:archive>
+ <sdk:archive os="linux">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/docs2-linux.tar.bz2</sdk:url>
+ </sdk:archive>
+ <sdk:archive os="macosx">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/docs2-mac.tar.bz2</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ </sdk:doc>
+
+ <sdk:tool>
+ <sdk:revision>42</sdk:revision>
+ <sdk:uses-license ref="license1" />
+ <sdk:min-platform-tools-rev>3</sdk:min-platform-tools-rev>
+ <sdk:archives>
+ <sdk:archive os="windows">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/tools/2.zip</sdk:url>
+ </sdk:archive>
+ <sdk:archive os="linux">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/tools2-linux.tar.bz2</sdk:url>
+ </sdk:archive>
+ <sdk:archive os="macosx">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/tools2-mac.tar.bz2</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ </sdk:tool>
+
+ <sdk:platform-tool>
+ <sdk:revision>3</sdk:revision>
+ <sdk:uses-license ref="license1" />
+ <sdk:archives>
+ <sdk:archive os="windows">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">3822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/platform-tools/2.zip</sdk:url>
+ </sdk:archive>
+ <sdk:archive os="linux">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">3822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/platform-tools2-linux.tar.bz2</sdk:url>
+ </sdk:archive>
+ <sdk:archive os="macosx">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">3822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/platform-tools2-mac.tar.bz2</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ </sdk:platform-tool>
+
+ <sdk:sample>
+ <sdk:api-level>14</sdk:api-level>
+ <sdk:revision>24</sdk:revision>
+ <sdk:archives>
+ <sdk:archive os="any" arch="any">
+ <sdk:size>65537</sdk:size>
+ <sdk:checksum type="sha1">3822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/sample_duff.zip</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ <sdk:description>Some sample package</sdk:description>
+ <sdk:desc-url>http://www.example.com/sample.html</sdk:desc-url>
+ <sdk:min-tools-rev>5</sdk:min-tools-rev>
+ <sdk:obsolete>This is obsolete</sdk:obsolete>
+ </sdk:sample>
+
+ <sdk:system-image>
+ <sdk:api-level>42</sdk:api-level>
+ <sdk:revision>12</sdk:revision>
+ <sdk:abi>armeabi</sdk:abi>
+ <sdk:archives>
+ <sdk:archive os="any">
+ <sdk:size>1234</sdk:size>
+ <sdk:checksum type="sha1">12345637115ebf13412bbef91339ee0d94541234</sdk:checksum>
+ <sdk:url>http://www.example.com/plat42/86/image12.zip</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ </sdk:system-image>
+
+ <sdk:source>
+ <sdk:api-level>42</sdk:api-level>
+ <sdk:revision>12</sdk:revision>
+ <sdk:archives>
+ <sdk:archive os="any">
+ <sdk:size>1234</sdk:size>
+ <sdk:checksum type="sha1">12345637115ebf13412bbef91339ee0d94541234</sdk:checksum>
+ <sdk:url>http://www.example.com/plat42/source12.zip</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ </sdk:source>
+
+</sdk:sdk-repository>
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/SdkUpdaterNoWindow.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/SdkUpdaterNoWindow.java
index 7b94c94..89f084c 100755
--- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/SdkUpdaterNoWindow.java
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/SdkUpdaterNoWindow.java
@@ -347,11 +347,37 @@
@Override
public boolean displayPrompt(final String title, final String message) {
// TODO Make it interactive if mForce==false
- mSdkLog.printf("\n%s\n%s\n[y/n] => %s\n",
+ mSdkLog.printf("\n%1$s\n%2$s\n%3$s", //$NON-NLS-1$
title,
message,
- mForce ? "yes" : "no (use --force to override)");
- return mForce;
+ mForce ? "--force used, will reply yes\n" :
+ "Note: you can use --force to override to yes.\n");
+ if (mForce) {
+ return true;
+ }
+
+ while (true) {
+ mSdkLog.printf("%1$s", "[y/n] =>"); //$NON-NLS-1$
+ try {
+ byte[] readBuffer = new byte[2048];
+ String reply = readLine(readBuffer).trim();
+ mSdkLog.printf("\n"); //$NON-NLS-1$
+ if (reply.length() > 0 && reply.length() <= 3) {
+ char c = reply.charAt(0);
+ if (c == 'y' || c == 'Y') {
+ return true;
+ } else if (c == 'n' || c == 'N') {
+ return false;
+ }
+ }
+ mSdkLog.printf("Unknown reply '%s'. Please use y[es]/n[o].\n"); //$NON-NLS-1$
+
+ } catch (IOException e) {
+ // Exception. Be conservative and say no.
+ mSdkLog.printf("\n"); //$NON-NLS-1$
+ return false;
+ }
+ }
}
/**
@@ -417,6 +443,14 @@
return new UserCredentials(login, password, workstation, domain);
}
+ /**
+ * Reads current console input in the given buffer.
+ *
+ * @param buffer Buffer to hold the user input. Must be larger than the largest
+ * expected input. Cannot be null.
+ * @return A new string. May be empty but not null.
+ * @throws IOException in case the buffer isn't long enough.
+ */
private String readLine(byte[] buffer) throws IOException {
int count = System.in.read(buffer);
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/AdtUpdateDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/AdtUpdateDialog.java
index dce4110..2311df2 100755
--- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/AdtUpdateDialog.java
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/AdtUpdateDialog.java
@@ -309,7 +309,7 @@
boolean accept(Package pkg) {
if (pkg instanceof ExtraPackage) {
ExtraPackage ep = (ExtraPackage) pkg;
- if (ep.getVendor().equals(mVendor)) {
+ if (ep.getVendorId().equals(mVendor)) {
// Check actual extra <path> field first
if (ep.getPath().equals(mPath)) {
return true;
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/PackagesDiffLogic.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/PackagesDiffLogic.java
index 49395ef..944dffb 100755
--- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/PackagesDiffLogic.java
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/PackagesDiffLogic.java
@@ -221,8 +221,8 @@
Package p = item.getMainPackage();
if (p instanceof ExtraPackage && item.getState() == PkgState.NEW) {
ExtraPackage ep = (ExtraPackage) p;
- if (ep.getVendor().equals("google") && //$NON-NLS-1$
- ep.getPath().equals("usb_driver")) { //$NON-NLS-1$
+ if (ep.getVendorId().equals("google") && //$NON-NLS-1$
+ ep.getPath().equals("usb_driver")) { //$NON-NLS-1$
item.setChecked(true);
}
}
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/PackagesPage.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/PackagesPage.java
index 58d7daa..d3dc7b6 100755
--- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/PackagesPage.java
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/sdkman2/PackagesPage.java
@@ -519,7 +519,9 @@
value = button.getSelection();
}
- item.setSelection(value);
+ if (!item.isDisposed()) {
+ item.setSelection(value);
+ }
}
}
@@ -1564,12 +1566,25 @@
if (element instanceof IDescription) {
String s = ((IDescription) element).getLongDescription();
if (element instanceof Package) {
- SdkSource src = ((Package) element).getParentSource();
+ Package p = (Package) element;
+
+ if (!p.isLocal()) {
+ // For non-installed item, try to find a download size
+ for (Archive a : p.getArchives()) {
+ if (!a.isLocal() && a.isCompatible()) {
+ s += '\n' + a.getSizeDescription();
+ break;
+ }
+ }
+ }
+
+ // Display info about where this package comes/came from
+ SdkSource src = p.getParentSource();
if (src != null) {
try {
URL url = new URL(src.getUrl());
String host = url.getHost();
- if (((Package) element).isLocal()) {
+ if (p.isLocal()) {
s += String.format("\nInstalled from %1$s", host);
} else {
s += String.format("\nProvided by %1$s", host);
diff --git a/sdkmanager/libs/sdkuilib/tests/com/android/sdkuilib/internal/repository/sdkman2/PackagesDiffLogicTest.java b/sdkmanager/libs/sdkuilib/tests/com/android/sdkuilib/internal/repository/sdkman2/PackagesDiffLogicTest.java
index eafe5ac..cf4b232 100755
--- a/sdkmanager/libs/sdkuilib/tests/com/android/sdkuilib/internal/repository/sdkman2/PackagesDiffLogicTest.java
+++ b/sdkmanager/libs/sdkuilib/tests/com/android/sdkuilib/internal/repository/sdkman2/PackagesDiffLogicTest.java
@@ -326,8 +326,8 @@
"-- <INSTALLED, pkg:Android SDK Tools, revision 10>\n" +
"-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3>\n" +
"PkgCategoryApi <API=EXTRAS, label=Extras, #items=2>\n" +
- "-- <INSTALLED, pkg:Android USB Driver package, revision 5>\n" +
- "-- <INSTALLED, pkg:Carrier Custom Rom package, revision 1>\n",
+ "-- <INSTALLED, pkg:Android USB Driver, revision 5>\n" +
+ "-- <INSTALLED, pkg:Carrier Custom Rom, revision 1>\n",
getTree(m, true /*displaySortByApi*/));
assertEquals(
@@ -335,8 +335,8 @@
"-- <INSTALLED, pkg:Android SDK Tools, revision 10>\n" +
"-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3>\n" +
"PkgCategorySource <source=repo2 (example.com), #items=2>\n" +
- "-- <INSTALLED, pkg:Android USB Driver package, revision 5>\n" +
- "-- <INSTALLED, pkg:Carrier Custom Rom package, revision 1>\n",
+ "-- <INSTALLED, pkg:Android USB Driver, revision 5>\n" +
+ "-- <INSTALLED, pkg:Carrier Custom Rom, revision 1>\n",
getTree(m, false /*displaySortByApi*/));
}
@@ -371,8 +371,8 @@
"-- <INSTALLED, pkg:Android SDK Tools, revision 10>\n" +
"-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3>\n" +
"PkgCategoryApi <API=EXTRAS, label=Extras, #items=2>\n" +
- "-- <INSTALLED, pkg:Android USB Driver package, revision 4, updated by:Android USB Driver package, revision 5>\n" +
- "-- <NEW, pkg:Carrier Custom Rom package, revision 1>\n",
+ "-- <INSTALLED, pkg:Android USB Driver, revision 4, updated by:Android USB Driver, revision 5>\n" +
+ "-- <NEW, pkg:Carrier Custom Rom, revision 1>\n",
getTree(m, true /*displaySortByApi*/));
// Next update adds platforms and addon, sorted in a category based on their API level
@@ -423,15 +423,15 @@
"-- <INSTALLED, pkg:SDK Platform Android android-3, API 3, revision 6>\n" +
"PkgCategoryApi <API=API 2, label=Android android-2 (API 2), #items=3>\n" +
"-- <NEW, pkg:SDK Platform Android android-2, API 2, revision 4>\n" +
- "-- <NEW, pkg:addon B by vendor 2, Android API 2, revision 9>\n" +
- "-- <NEW, pkg:addon C by vendor 2, Android API 2, revision 9>\n" +
+ "-- <NEW, pkg:The addon B from vendor 2, Android API 2, revision 9>\n" +
+ "-- <NEW, pkg:The addon C from vendor 2, Android API 2, revision 9>\n" +
"PkgCategoryApi <API=API 1, label=Android android-1 (API 1), #items=3>\n" +
"-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" +
- "-- <INSTALLED, pkg:addon A by vendor 1, Android API 1, revision 5, updated by:addon A by vendor 1, Android API 1, revision 6>\n" +
- "-- <INSTALLED, pkg:addon D by vendor 1, Android API 1, revision 10, updated by:addon D by vendor 1, Android API 1, revision 13>\n" +
+ "-- <INSTALLED, pkg:The addon A from vendor 1, Android API 1, revision 5, updated by:The addon A from vendor 1, Android API 1, revision 6>\n" +
+ "-- <INSTALLED, pkg:The addon D from vendor 1, Android API 1, revision 10, updated by:The addon D from vendor 1, Android API 1, revision 13>\n" +
"PkgCategoryApi <API=EXTRAS, label=Extras, #items=2>\n" +
- "-- <INSTALLED, pkg:Android USB Driver package, revision 4, updated by:Android USB Driver package, revision 5>\n" +
- "-- <NEW, pkg:Carrier Custom Rom package, revision 1>\n",
+ "-- <INSTALLED, pkg:Android USB Driver, revision 4, updated by:Android USB Driver, revision 5>\n" +
+ "-- <NEW, pkg:Carrier Custom Rom, revision 1>\n",
getTree(m, true /*displaySortByApi*/));
// Reloading the same thing should have no impact except for the update methods
@@ -479,15 +479,15 @@
"-- <INSTALLED, pkg:SDK Platform Android android-3, API 3, revision 6>\n" +
"PkgCategoryApi <API=API 2, label=Android android-2 (API 2), #items=3>\n" +
"-- <NEW, pkg:SDK Platform Android android-2, API 2, revision 4>\n" +
- "-- <NEW, pkg:addon B by vendor 2, Android API 2, revision 9>\n" +
- "-- <NEW, pkg:addon C by vendor 2, Android API 2, revision 9>\n" +
+ "-- <NEW, pkg:The addon B from vendor 2, Android API 2, revision 9>\n" +
+ "-- <NEW, pkg:The addon C from vendor 2, Android API 2, revision 9>\n" +
"PkgCategoryApi <API=API 1, label=Android android-1 (API 1), #items=3>\n" +
"-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" +
- "-- <INSTALLED, pkg:addon A by vendor 1, Android API 1, revision 5, updated by:addon A by vendor 1, Android API 1, revision 6>\n" +
- "-- <INSTALLED, pkg:addon D by vendor 1, Android API 1, revision 10, updated by:addon D by vendor 1, Android API 1, revision 13>\n" +
+ "-- <INSTALLED, pkg:The addon A from vendor 1, Android API 1, revision 5, updated by:The addon A from vendor 1, Android API 1, revision 6>\n" +
+ "-- <INSTALLED, pkg:The addon D from vendor 1, Android API 1, revision 10, updated by:The addon D from vendor 1, Android API 1, revision 13>\n" +
"PkgCategoryApi <API=EXTRAS, label=Extras, #items=2>\n" +
- "-- <INSTALLED, pkg:Android USB Driver package, revision 4, updated by:Android USB Driver package, revision 5>\n" +
- "-- <NEW, pkg:Carrier Custom Rom package, revision 1>\n",
+ "-- <INSTALLED, pkg:Android USB Driver, revision 4, updated by:Android USB Driver, revision 5>\n" +
+ "-- <NEW, pkg:Carrier Custom Rom, revision 1>\n",
getTree(m, true /*displaySortByApi*/));
}
@@ -714,8 +714,8 @@
"PkgCategorySource <source=repo1 (1.example.com), #items=4>\n" +
"-- <INSTALLED, pkg:Android SDK Tools, revision 10>\n" +
"-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3>\n" +
- "-- <INSTALLED, pkg:Android USB Driver package, revision 4, updated by:Android USB Driver package, revision 5>\n" +
- "-- <NEW, pkg:Carrier Custom Rom package, revision 1>\n",
+ "-- <INSTALLED, pkg:Android USB Driver, revision 4, updated by:Android USB Driver, revision 5>\n" +
+ "-- <NEW, pkg:Carrier Custom Rom, revision 1>\n",
getTree(m, false /*displaySortByApi*/));
// Next update adds platforms and addon, sorted in a category based on their API level
@@ -766,13 +766,13 @@
"-- <INSTALLED, pkg:SDK Platform Android android-3, API 3, revision 6>\n" +
"-- <NEW, pkg:SDK Platform Android android-2, API 2, revision 4>\n" +
"-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" +
- "-- <INSTALLED, pkg:Android USB Driver package, revision 4, updated by:Android USB Driver package, revision 5>\n" +
- "-- <NEW, pkg:Carrier Custom Rom package, revision 1>\n" +
+ "-- <INSTALLED, pkg:Android USB Driver, revision 4, updated by:Android USB Driver, revision 5>\n" +
+ "-- <NEW, pkg:Carrier Custom Rom, revision 1>\n" +
"PkgCategorySource <source=repo2 (2.example.com), #items=4>\n" +
- "-- <NEW, pkg:addon B by vendor 2, Android API 2, revision 9>\n" +
- "-- <NEW, pkg:addon C by vendor 2, Android API 2, revision 9>\n" +
- "-- <INSTALLED, pkg:addon A by vendor 1, Android API 1, revision 5, updated by:addon A by vendor 1, Android API 1, revision 6>\n" +
- "-- <INSTALLED, pkg:addon D by vendor 1, Android API 1, revision 10, updated by:addon D by vendor 1, Android API 1, revision 13>\n",
+ "-- <NEW, pkg:The addon B from vendor 2, Android API 2, revision 9>\n" +
+ "-- <NEW, pkg:The addon C from vendor 2, Android API 2, revision 9>\n" +
+ "-- <INSTALLED, pkg:The addon A from vendor 1, Android API 1, revision 5, updated by:The addon A from vendor 1, Android API 1, revision 6>\n" +
+ "-- <INSTALLED, pkg:The addon D from vendor 1, Android API 1, revision 10, updated by:The addon D from vendor 1, Android API 1, revision 13>\n",
getTree(m, false /*displaySortByApi*/));
// Reloading the same thing should have no impact except for the update methods
@@ -820,13 +820,13 @@
"-- <INSTALLED, pkg:SDK Platform Android android-3, API 3, revision 6>\n" +
"-- <NEW, pkg:SDK Platform Android android-2, API 2, revision 4>\n" +
"-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" +
- "-- <INSTALLED, pkg:Android USB Driver package, revision 4, updated by:Android USB Driver package, revision 5>\n" +
- "-- <NEW, pkg:Carrier Custom Rom package, revision 1>\n" +
+ "-- <INSTALLED, pkg:Android USB Driver, revision 4, updated by:Android USB Driver, revision 5>\n" +
+ "-- <NEW, pkg:Carrier Custom Rom, revision 1>\n" +
"PkgCategorySource <source=repo2 (2.example.com), #items=4>\n" +
- "-- <NEW, pkg:addon B by vendor 2, Android API 2, revision 9>\n" +
- "-- <NEW, pkg:addon C by vendor 2, Android API 2, revision 9>\n" +
- "-- <INSTALLED, pkg:addon A by vendor 1, Android API 1, revision 5, updated by:addon A by vendor 1, Android API 1, revision 6>\n" +
- "-- <INSTALLED, pkg:addon D by vendor 1, Android API 1, revision 10, updated by:addon D by vendor 1, Android API 1, revision 13>\n",
+ "-- <NEW, pkg:The addon B from vendor 2, Android API 2, revision 9>\n" +
+ "-- <NEW, pkg:The addon C from vendor 2, Android API 2, revision 9>\n" +
+ "-- <INSTALLED, pkg:The addon A from vendor 1, Android API 1, revision 5, updated by:The addon A from vendor 1, Android API 1, revision 6>\n" +
+ "-- <INSTALLED, pkg:The addon D from vendor 1, Android API 1, revision 10, updated by:The addon D from vendor 1, Android API 1, revision 13>\n",
getTree(m, false /*displaySortByApi*/));
}
@@ -970,13 +970,13 @@
"-- < * NEW, pkg:SDK Platform Android android-2, API 2, revision 4>\n" +
"-- < * NEW, pkg:ARM EABI System Image, Android API 2, revision 1>\n" +
"-- < * NEW, pkg:Intel x86 Atom System Image, Android API 2, revision 1>\n" +
- "-- < * NEW, pkg:addon B by vendor 2, Android API 2, revision 7>\n" +
+ "-- < * NEW, pkg:The addon B from vendor 2, Android API 2, revision 7>\n" +
"PkgCategoryApi <API=API 1, label=Android android-1 (API 1), #items=2>\n" +
"-- <NEW, pkg:SDK Platform Android android-1, API 1, revision 2>\n" +
- "-- <NEW, pkg:addon A by vendor 1, Android API 1, revision 5>\n" +
+ "-- <NEW, pkg:The addon A from vendor 1, Android API 1, revision 5>\n" +
"PkgCategoryApi <API=EXTRAS, label=Extras, #items=2>\n" +
- "-- <NEW, pkg:Carrier Custom Rom package, revision 1>\n" +
- "-- <NEW, pkg:Google USB Driver package, revision 5>\n",
+ "-- <NEW, pkg:Carrier Custom Rom, revision 1>\n" +
+ "-- <NEW, pkg:Google USB Driver, revision 5>\n",
getTree(m, true /*displaySortByApi*/));
assertEquals(
"PkgCategorySource <source=repo1 (1.example.com), #items=7>\n" +
@@ -986,11 +986,11 @@
"-- <NEW, pkg:SDK Platform Android android-1, API 1, revision 2>\n" +
"-- < * NEW, pkg:ARM EABI System Image, Android API 2, revision 1>\n" +
"-- < * NEW, pkg:Intel x86 Atom System Image, Android API 2, revision 1>\n" +
- "-- <NEW, pkg:Google USB Driver package, revision 5>\n" +
+ "-- <NEW, pkg:Google USB Driver, revision 5>\n" +
"PkgCategorySource <source=repo2 (2.example.com), #items=3>\n" +
- "-- < * NEW, pkg:addon B by vendor 2, Android API 2, revision 7>\n" +
- "-- <NEW, pkg:addon A by vendor 1, Android API 1, revision 5>\n" +
- "-- <NEW, pkg:Carrier Custom Rom package, revision 1>\n",
+ "-- < * NEW, pkg:The addon B from vendor 2, Android API 2, revision 7>\n" +
+ "-- <NEW, pkg:The addon A from vendor 1, Android API 1, revision 5>\n" +
+ "-- <NEW, pkg:Carrier Custom Rom, revision 1>\n",
getTree(m, false /*displaySortByApi*/));
// We don't install the USB driver by default on Mac or Linux, only on Windows
@@ -1005,11 +1005,11 @@
assertEquals(
"PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" +
"PkgCategoryApi <API=EXTRAS, label=Extras, #items=1>\n" +
- "-- <NEW, pkg:Google USB Driver package, revision 5>\n",
+ "-- <NEW, pkg:Google USB Driver, revision 5>\n",
getTree(m, true /*displaySortByApi*/));
assertEquals(
"PkgCategorySource <source=repo1 (1.example.com), #items=1>\n" +
- "-- <NEW, pkg:Google USB Driver package, revision 5>\n",
+ "-- <NEW, pkg:Google USB Driver, revision 5>\n",
getTree(m, false /*displaySortByApi*/));
m.clear();
@@ -1023,11 +1023,11 @@
assertEquals(
"PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" +
"PkgCategoryApi <API=EXTRAS, label=Extras, #items=1>\n" +
- "-- <NEW, pkg:Google USB Driver package, revision 5>\n",
+ "-- <NEW, pkg:Google USB Driver, revision 5>\n",
getTree(m, true /*displaySortByApi*/));
assertEquals(
"PkgCategorySource <source=repo1 (1.example.com), #items=1>\n" +
- "-- <NEW, pkg:Google USB Driver package, revision 5>\n",
+ "-- <NEW, pkg:Google USB Driver, revision 5>\n",
getTree(m, false /*displaySortByApi*/));
m.clear();
@@ -1041,11 +1041,11 @@
assertEquals(
"PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" +
"PkgCategoryApi <API=EXTRAS, label=Extras, #items=1>\n" +
- "-- < * NEW, pkg:Google USB Driver package, revision 5>\n",
+ "-- < * NEW, pkg:Google USB Driver, revision 5>\n",
getTree(m, true /*displaySortByApi*/));
assertEquals(
"PkgCategorySource <source=repo1 (1.example.com), #items=1>\n" +
- "-- < * NEW, pkg:Google USB Driver package, revision 5>\n",
+ "-- < * NEW, pkg:Google USB Driver, revision 5>\n",
getTree(m, false /*displaySortByApi*/));
}
@@ -1213,8 +1213,8 @@
"-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3>\n" +
"PkgCategoryApi <API=API 1, label=Android android-1 (API 1), #items=3>\n" +
"-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" +
- "-- <NEW, pkg:addon A by vendor 1, Android API 1, revision 5>\n" + // from src2+3+4
- "-- <NEW, pkg:addon B by vendor 1, Android API 1, revision 7>\n" + // from src3+4
+ "-- <NEW, pkg:The addon A from vendor 1, Android API 1, revision 5>\n" + // from src2+3+4
+ "-- <NEW, pkg:The addon B from vendor 1, Android API 1, revision 7>\n" + // from src3+4
"PkgCategoryApi <API=EXTRAS, label=Extras, #items=0>\n",
getTree(m, true /*displaySortByApi*/));
// When sorting by source, the src4 packages are not listed at all since
@@ -1226,9 +1226,9 @@
"-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3>\n" +
"-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" +
"PkgCategorySource <source=repo2 (example.com), #items=1>\n" +
- "-- <NEW, pkg:addon A by vendor 1, Android API 1, revision 5>\n" + // from src2+3+4
+ "-- <NEW, pkg:The addon A from vendor 1, Android API 1, revision 5>\n" + // from src2+3+4
"PkgCategorySource <source=repo3 (example.com), #items=1>\n" +
- "-- <NEW, pkg:addon B by vendor 1, Android API 1, revision 7>\n", // from src3+4
+ "-- <NEW, pkg:The addon B from vendor 1, Android API 1, revision 7>\n", // from src3+4
getTree(m, false /*displaySortByApi*/));
}
@@ -1254,13 +1254,13 @@
assertEquals(
"PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" +
"PkgCategoryApi <API=EXTRAS, label=Extras, #items=2>\n" +
- "-- <NEW, pkg:Vendor1 New Path2 package, revision 2>\n" +
- "-- <INSTALLED, pkg:Vendor1 Old Path1 package, revision 1>\n",
+ "-- <NEW, pkg:Vendor1 New Path2, revision 2>\n" +
+ "-- <INSTALLED, pkg:Vendor1 Old Path1, revision 1>\n",
getTree(m, true /*displaySortByApi*/));
assertEquals(
"PkgCategorySource <source=repo1 (example.com), #items=2>\n" +
- "-- <NEW, pkg:Vendor1 New Path2 package, revision 2>\n" +
- "-- <INSTALLED, pkg:Vendor1 Old Path1 package, revision 1>\n",
+ "-- <NEW, pkg:Vendor1 New Path2, revision 2>\n" +
+ "-- <INSTALLED, pkg:Vendor1 Old Path1, revision 1>\n",
getTree(m, false /*displaySortByApi*/));
// Now, start again, but this time the new package uses the old-path attribute
@@ -1280,11 +1280,11 @@
assertEquals(
"PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" +
"PkgCategoryApi <API=EXTRAS, label=Extras, #items=1>\n" +
- "-- <INSTALLED, pkg:Vendor1 Old Path1 package, revision 1, updated by:Vendor1 New Path2 package, revision 2>\n",
+ "-- <INSTALLED, pkg:Vendor1 Old Path1, revision 1, updated by:Vendor1 New Path2, revision 2>\n",
getTree(m, true /*displaySortByApi*/));
assertEquals(
"PkgCategorySource <source=repo1 (example.com), #items=1>\n" +
- "-- <INSTALLED, pkg:Vendor1 Old Path1 package, revision 1, updated by:Vendor1 New Path2 package, revision 2>\n",
+ "-- <INSTALLED, pkg:Vendor1 Old Path1, revision 1, updated by:Vendor1 New Path2, revision 2>\n",
getTree(m, false /*displaySortByApi*/));
}
@@ -1313,14 +1313,14 @@
"PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" +
"PkgCategoryApi <API=API 1, label=Android android-1 (API 1), #items=2>\n" +
"-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" +
- "-- <INSTALLED, pkg:addon A by vendor 1, Android API 1, revision 4>\n" +
+ "-- <INSTALLED, pkg:The addon A from vendor 1, Android API 1, revision 4>\n" +
"PkgCategoryApi <API=EXTRAS, label=Extras, #items=0>\n",
getTree(m, true /*displaySortByApi*/));
assertEquals(
"PkgCategorySource <source=repo1 (1.example.com), #items=1>\n" +
"-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" +
"PkgCategorySource <source=repo2 (2.example.com), #items=1>\n" +
- "-- <INSTALLED, pkg:addon A by vendor 1, Android API 1, revision 4>\n",
+ "-- <INSTALLED, pkg:The addon A from vendor 1, Android API 1, revision 4>\n",
getTree(m, false /*displaySortByApi*/));
// Now user deletes the platform on disk and reload.
@@ -1340,7 +1340,7 @@
"PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" +
"PkgCategoryApi <API=API 1, label=Android android-1 (API 1), #items=2>\n" +
"-- <NEW, pkg:SDK Platform Android android-1, API 1, revision 2>\n" +
- "-- <NEW, pkg:addon A by vendor 1, Android API 1, revision 4>\n" +
+ "-- <NEW, pkg:The addon A from vendor 1, Android API 1, revision 4>\n" +
"PkgCategoryApi <API=EXTRAS, label=Extras, #items=1>\n" +
"-- <INSTALLED, pkg:Broken package for API 1>\n",
getTree(m, true /*displaySortByApi*/));
@@ -1348,7 +1348,7 @@
"PkgCategorySource <source=repo1 (1.example.com), #items=1>\n" +
"-- <NEW, pkg:SDK Platform Android android-1, API 1, revision 2>\n" +
"PkgCategorySource <source=repo2 (2.example.com), #items=1>\n" +
- "-- <NEW, pkg:addon A by vendor 1, Android API 1, revision 4>\n" +
+ "-- <NEW, pkg:The addon A from vendor 1, Android API 1, revision 4>\n" +
"PkgCategorySource <source=Local Packages (no.source), #items=1>\n" +
"-- <INSTALLED, pkg:Broken package for API 1>\n",
getTree(m, false /*displaySortByApi*/));
@@ -1370,14 +1370,14 @@
"PkgCategoryApi <API=TOOLS, label=Tools, #items=0>\n" +
"PkgCategoryApi <API=API 1, label=Android android-1 (API 1), #items=2>\n" +
"-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" +
- "-- <INSTALLED, pkg:addon A by vendor 1, Android API 1, revision 4>\n" +
+ "-- <INSTALLED, pkg:The addon A from vendor 1, Android API 1, revision 4>\n" +
"PkgCategoryApi <API=EXTRAS, label=Extras, #items=0>\n",
getTree(m, true /*displaySortByApi*/));
assertEquals(
"PkgCategorySource <source=repo1 (1.example.com), #items=1>\n" +
"-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" +
"PkgCategorySource <source=repo2 (2.example.com), #items=1>\n" +
- "-- <INSTALLED, pkg:addon A by vendor 1, Android API 1, revision 4>\n",
+ "-- <INSTALLED, pkg:The addon A from vendor 1, Android API 1, revision 4>\n",
getTree(m, false /*displaySortByApi*/));
}
@@ -1411,8 +1411,8 @@
"-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3, updated by:Android SDK Platform-tools, revision 4>\n" +
"PkgCategoryApi <API=API 1, label=Android android-1 (API 1), #items=3>\n" +
"-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" +
- "-- <NEW, pkg:addon A by vendor 1, Android API 1, revision 5>\n" +
- "-- <NEW, pkg:addon B by vendor 1, Android API 1, revision 6>\n" +
+ "-- <NEW, pkg:The addon A from vendor 1, Android API 1, revision 5>\n" +
+ "-- <NEW, pkg:The addon B from vendor 1, Android API 1, revision 6>\n" +
"PkgCategoryApi <API=EXTRAS, label=Extras, #items=0>\n",
getTree(m, true /*displaySortByApi*/));
assertEquals(
@@ -1422,8 +1422,8 @@
"-- <INSTALLED, pkg:Android SDK Platform-tools, revision 3, updated by:Android SDK Platform-tools, revision 4>\n" +
"-- <INSTALLED, pkg:SDK Platform Android android-1, API 1, revision 2>\n" +
"PkgCategorySource <source=repo2 (2.example.com), #items=2>\n" +
- "-- <NEW, pkg:addon A by vendor 1, Android API 1, revision 5>\n" +
- "-- <NEW, pkg:addon B by vendor 1, Android API 1, revision 6>\n",
+ "-- <NEW, pkg:The addon A from vendor 1, Android API 1, revision 5>\n" +
+ "-- <NEW, pkg:The addon B from vendor 1, Android API 1, revision 6>\n",
getTree(m, false /*displaySortByApi*/));
}
// ----