diff --git a/tools/sdkmanager/app/src/com/android/sdkmanager/Main.java b/tools/sdkmanager/app/src/com/android/sdkmanager/Main.java index 35d9bb165..344be1b33 100644 --- a/tools/sdkmanager/app/src/com/android/sdkmanager/Main.java +++ b/tools/sdkmanager/app/src/com/android/sdkmanager/Main.java @@ -226,6 +226,10 @@ class Main { SdkCommandLine.OBJECT_PROJECT.equals(directObject)) { updateProject(); + } else if (SdkCommandLine.VERB_UPDATE.equals(verb) && + SdkCommandLine.OBJECT_ADB.equals(directObject)) { + updateAdb(); + } else { mSdkCommandLine.printHelpAndExit(null); } @@ -390,7 +394,12 @@ class Main { // get the target skins displaySkinList(target, " Skins: "); - + + if (target.getUsbVendorId() != IAndroidTarget.NO_USB_ID) { + mSdkLog.printf(" Adds USB support for devices (Vendor: 0x%04X)\n", + target.getUsbVendorId()); + } + index++; } } @@ -740,7 +749,25 @@ class Main { errorAndExit(e.getMessage()); } } - + + /** + * Updates adb with the USB devices declared in the SDK add-ons. + */ + private void updateAdb() { + try { + mSdkManager.updateAdb(); + + mSdkLog.printf( + "adb has been updated. You must restart adb with the following commands\n" + + "\tadb kill-server\n" + + "\tadb start-server\n"); + } catch (AndroidLocationException e) { + errorAndExit(e.getMessage()); + } catch (IOException e) { + errorAndExit(e.getMessage()); + } + } + /** * Prompts the user to setup a hardware config for a Platform-based AVD. * @throws IOException diff --git a/tools/sdkmanager/app/src/com/android/sdkmanager/SdkCommandLine.java b/tools/sdkmanager/app/src/com/android/sdkmanager/SdkCommandLine.java index 36172e96c..c3cd3725b 100644 --- a/tools/sdkmanager/app/src/com/android/sdkmanager/SdkCommandLine.java +++ b/tools/sdkmanager/app/src/com/android/sdkmanager/SdkCommandLine.java @@ -36,6 +36,7 @@ public class SdkCommandLine extends CommandLineProcessor { public static final String OBJECT_TARGET = "target"; public static final String OBJECT_TARGETS = "targets"; public static final String OBJECT_PROJECT = "project"; + public static final String OBJECT_ADB = "adb"; public static final String ARG_ALIAS = "alias"; public static final String ARG_ACTIVITY = "activity"; @@ -86,6 +87,9 @@ public class SdkCommandLine extends CommandLineProcessor { "Creates a new Android Project." }, { VERB_UPDATE, OBJECT_PROJECT, "Updates an Android Project (must have an AndroidManifest.xml)." }, + + { VERB_UPDATE, OBJECT_ADB, + "Updates adb to support the USB devices declared in the SDK add-ons." }, }; public SdkCommandLine(ISdkLog logger) { diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/AddOnTarget.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/AddOnTarget.java index 2336f471e..d5c0e2680 100644 --- a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/AddOnTarget.java +++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/AddOnTarget.java @@ -72,6 +72,7 @@ final class AddOnTarget implements IAndroidTarget { private String[] mSkins; private String mDefaultSkin; private IOptionalLibrary[] mLibraries; + private int mVendorId = NO_USB_ID; /** * Creates a new add-on @@ -191,7 +192,11 @@ final class AddOnTarget implements IAndroidTarget { public IOptionalLibrary[] getOptionalLibraries() { return mLibraries; } - + + public int getUsbVendorId() { + return mVendorId; + } + public boolean isCompatibleBaseFor(IAndroidTarget target) { // basic test if (target == this) { @@ -276,4 +281,15 @@ final class AddOnTarget implements IAndroidTarget { mSkins = skinSet.toArray(new String[skinSet.size()]); } + + /** + * Sets the USB vendor id in the add-on. + */ + void setUsbVendorId(int vendorId) { + if (vendorId == 0) { + throw new IllegalArgumentException( "VendorId must be > 0"); + } + + mVendorId = vendorId; + } } diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/IAndroidTarget.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/IAndroidTarget.java index 896a83cd8..b8699d398 100644 --- a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/IAndroidTarget.java +++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/IAndroidTarget.java @@ -23,52 +23,58 @@ package com.android.sdklib; public interface IAndroidTarget extends Comparable { /** OS Path to the "android.jar" file. */ - public static int ANDROID_JAR = 1; + public final static int ANDROID_JAR = 1; /** OS Path to the "framework.aidl" file. */ - public static int ANDROID_AIDL = 2; + public final static int ANDROID_AIDL = 2; /** OS Path to "images" folder which contains the emulator system images. */ - public static int IMAGES = 3; + public final static int IMAGES = 3; /** OS Path to the "samples" folder which contains sample projects. */ - public static int SAMPLES = 4; + public final static int SAMPLES = 4; /** OS Path to the "skins" folder which contains the emulator skins. */ - public static int SKINS = 5; + public final static int SKINS = 5; /** OS Path to the "templates" folder which contains the templates for new projects. */ - public static int TEMPLATES = 6; + public final static int TEMPLATES = 6; /** OS Path to the "data" folder which contains data & libraries for the SDK tools. */ - public static int DATA = 7; + public final static int DATA = 7; /** OS Path to the "attrs.xml" file. */ - public static int ATTRIBUTES = 8; + public final static int ATTRIBUTES = 8; /** OS Path to the "attrs_manifest.xml" file. */ - public static int MANIFEST_ATTRIBUTES = 9; + public final static int MANIFEST_ATTRIBUTES = 9; /** OS Path to the "data/layoutlib.jar" library. */ - public static int LAYOUT_LIB = 10; + public final static int LAYOUT_LIB = 10; /** OS Path to the "data/res" folder. */ - public static int RESOURCES = 11; + public final static int RESOURCES = 11; /** OS Path to the "data/fonts" folder. */ - public static int FONTS = 12; + public final static int FONTS = 12; /** OS Path to the "data/widgets.txt" file. */ - public static int WIDGETS = 13; + public final static int WIDGETS = 13; /** OS Path to the "data/activity_actions.txt" file. */ - public static int ACTIONS_ACTIVITY = 14; + public final static int ACTIONS_ACTIVITY = 14; /** OS Path to the "data/broadcast_actions.txt" file. */ - public static int ACTIONS_BROADCAST = 15; + public final static int ACTIONS_BROADCAST = 15; /** OS Path to the "data/service_actions.txt" file. */ - public static int ACTIONS_SERVICE = 16; + public final static int ACTIONS_SERVICE = 16; /** OS Path to the "data/categories.txt" file. */ - public static int CATEGORIES = 17; + public final static int CATEGORIES = 17; /** OS Path to the "sources" folder. */ - public static int SOURCES = 18; + public final static int SOURCES = 18; /** OS Path to the target specific docs */ - public static int DOCS = 19; + public final static int DOCS = 19; /** OS Path to the target's version of the aapt tool. */ - public static int AAPT = 20; + public final static int AAPT = 20; /** OS Path to the target's version of the aidl tool. */ - public static int AIDL = 21; + public final static int AIDL = 21; /** OS Path to the target's version of the dx too. */ - public static int DX = 22; + public final static int DX = 22; /** OS Path to the target's version of the dx.jar file. */ - public static int DX_JAR = 23; - + public final static int DX_JAR = 23; + + /** + * Return value for {@link #getUsbVendorId()} meaning no USB vendor IDs are defined by the + * Android target. + */ + public final static int NO_USB_ID = 0; + public interface IOptionalLibrary { String getName(); String getJarName(); @@ -149,7 +155,13 @@ public interface IAndroidTarget extends Comparable { * @return an array of optional libraries or null if there is none. */ IOptionalLibrary[] getOptionalLibraries(); - + + /** + * Returns the USB Vendor ID for the vendor of this target. + *

If the target defines no USB Vendor ID, then the method return 0. + */ + int getUsbVendorId(); + /** * Returns whether the given target is compatible with the receiver. *

A target is considered compatible if applications developed for the receiver can run on diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/PlatformTarget.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/PlatformTarget.java index d4e40b182..6d29f642d 100644 --- a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/PlatformTarget.java +++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/PlatformTarget.java @@ -158,7 +158,15 @@ final class PlatformTarget implements IAndroidTarget { public IOptionalLibrary[] getOptionalLibraries() { return null; } - + + /** + * The platform has no USB Vendor Id: always return {@link IAndroidTarget#NO_USB_ID}. + * {@inheritDoc} + */ + public int getUsbVendorId() { + return NO_USB_ID; + } + public boolean isCompatibleBaseFor(IAndroidTarget target) { // basic test if (target == this) { diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java index 28227c6d2..6dddf3749 100644 --- a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java +++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java @@ -16,15 +16,20 @@ package com.android.sdklib; +import com.android.prefs.AndroidLocation; +import com.android.prefs.AndroidLocation.AndroidLocationException; + import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -45,13 +50,18 @@ public final class SdkManager { private final static String ADDON_DESCRIPTION = "description"; private final static String ADDON_LIBRARIES = "libraries"; private final static String ADDON_DEFAULT_SKIN = "skin"; - + private final static String ADDON_USB_VENDOR = "usb-vendor"; + private final static Pattern PATTERN_PROP = Pattern.compile( "^([a-zA-Z0-9._-]+)\\s*=\\s*(.*)\\s*$"); private final static Pattern PATTERN_LIB_DATA = Pattern.compile( "^([a-zA-Z0-9._-]+\\.jar);(.*)$", Pattern.CASE_INSENSITIVE); - + + // usb ids are 16-bit hexadecimal values. + private final static Pattern PATTERN_USB_IDS = Pattern.compile( + "^0x[a-f0-9]{4}$", Pattern.CASE_INSENSITIVE); + /** List of items in the platform to check when parsing it. These paths are relative to the * platform root folder. */ private final static String[] sPlatformContentList = new String[] { @@ -63,6 +73,14 @@ public final class SdkManager { SdkConstants.OS_SDK_TOOLS_LIB_FOLDER + SdkConstants.FN_DX_JAR, }; + /** Preference file containing the usb ids for adb */ + private final static String ADB_INI_FILE = "adb_usb.ini"; + //0--------90--------90--------90--------90--------90--------90--------90--------9 + private final static String ADB_INI_HEADER = + "# ANDROID 3RD PARTY USB VENDOR ID LIST -- DO NOT EDIT.\n" + + "# USE 'android update adb' TO GENERATE.\n" + + "# 1 USB VENDOR ID PER LINE.\n"; + /** the location of the SDK */ private final String mSdkLocation; private IAndroidTarget[] mTargets; @@ -127,6 +145,38 @@ public final class SdkManager { return null; } + /** + * Updates adb with the USB devices declared in the SDK add-ons. + * @throws AndroidLocationException + * @throws IOException + */ + public void updateAdb() throws AndroidLocationException, IOException { + FileWriter writer = null; + try { + // get the android prefs location to know where to write the file. + File adbIni = new File(AndroidLocation.getFolder(), ADB_INI_FILE); + writer = new FileWriter(adbIni); + + // first, put all the vendor id in an HashSet to remove duplicate. + HashSet set = new HashSet(); + IAndroidTarget[] targets = getTargets(); + for (IAndroidTarget target : targets) { + if (target.getUsbVendorId() != IAndroidTarget.NO_USB_ID) { + set.add(target.getUsbVendorId()); + } + } + + // write file header. + writer.write(ADB_INI_HEADER); + + // now write the Id in a text file, one per line. + for (Integer i : set) { + writer.write(String.format("0x%04x\n", i)); + } + } finally { + writer.close(); + } + } private SdkManager(String sdkLocation) { mSdkLocation = sdkLocation; @@ -370,7 +420,6 @@ public final class SdkManager { // get the default skin, or take it from the base platform if needed. String defaultSkin = propertyMap.get(ADDON_DEFAULT_SKIN); - if (defaultSkin == null) { if (skins.length == 1) { defaultSkin = skins[1]; @@ -381,6 +430,12 @@ public final class SdkManager { target.setSkins(skins, defaultSkin); + // get the USB ID (if available) + int usbVendorId = convertId(propertyMap.get(ADDON_USB_VENDOR)); + if (usbVendorId != IAndroidTarget.NO_USB_ID) { + target.setUsbVendorId(usbVendorId); + } + return target; } } else if (log != null) { @@ -390,7 +445,28 @@ public final class SdkManager { return null; } - + + /** + * Converts a string representation of an hexadecimal ID into an int. + * @param value the string to convert. + * @return the int value, or {@link IAndroidTarget#NO_USB_ID} if the convertion failed. + */ + private int convertId(String value) { + if (value != null && value.length() > 0) { + if (PATTERN_USB_IDS.matcher(value).matches()) { + String v = value.substring(2); + try { + return Integer.parseInt(v, 16); + } catch (NumberFormatException e) { + // this shouldn't happen since we check the pattern above, but this is safer. + // the method will return 0 below. + } + } + } + + return IAndroidTarget.NO_USB_ID; + } + private void displayAddonManifestError(ISdkLog log, String addonName, String valueName) { if (log != null) { log.error(null, "Ignoring add-on '%1$s': '%2$s' is missing from %3$s.",