Merge change 3439

* changes:
  updating sample plugin to use lifecycle events.
diff --git a/build/tools/make_windows_sdk.sh b/build/tools/make_windows_sdk.sh
index 7b15e83..33d6c46 100755
--- a/build/tools/make_windows_sdk.sh
+++ b/build/tools/make_windows_sdk.sh
@@ -141,23 +141,25 @@
 
     # Copy all the new stuff in tools
     # Note: some tools are first copied here and then moved in platforms/<name>/tools/
-    cp -v out/host/windows-x86/bin/*.{exe,dll} "$TOOLS"
-    cp -v prebuilt/windows/swt/swt.jar         "$LIB"/x86
-    cp -v prebuilt/windows-x86_64/swt/swt.jar  "$LIB"/x86_64
+    cp -v out/host/windows-x86/bin/*.{exe,dll} "$TOOLS"/
+    mkdir -pv "$LIB"/x86
+    cp -v prebuilt/windows/swt/swt.jar         "$LIB"/x86/
+    mkdir -pv "$LIB"/x86_64
+    cp -v prebuilt/windows-x86_64/swt/swt.jar  "$LIB"/x86_64/
 
     # If you want the emulator NOTICE in the tools dir, uncomment the following line:
     # cp -v external/qemu/NOTICE "$TOOLS"/emulator_NOTICE.txt
 
     # We currently need libz from MinGW for aapt
-    cp -v /cygdrive/c/cygwin/bin/mgwz.dll "$TOOLS"
+    cp -v /cygdrive/c/cygwin/bin/mgwz.dll "$TOOLS"/
 
     # Update a bunch of bat files
-    cp -v development/tools/apkbuilder/etc/apkbuilder.bat           "$TOOLS"
-    cp -v development/tools/ddms/app/etc/ddms.bat                   "$TOOLS"
-    cp -v development/tools/traceview/etc/traceview.bat             "$TOOLS"
-    cp -v development/tools/hierarchyviewer/etc/hierarchyviewer.bat "$TOOLS"
-    cp -v development/tools/draw9patch/etc/draw9patch.bat           "$TOOLS"
-    cp -v development/tools/sdkmanager/app/etc/android.bat          "$TOOLS"
+    cp -v development/tools/apkbuilder/etc/apkbuilder.bat           "$TOOLS"/
+    cp -v development/tools/ddms/app/etc/ddms.bat                   "$TOOLS"/
+    cp -v development/tools/traceview/etc/traceview.bat             "$TOOLS"/
+    cp -v development/tools/hierarchyviewer/etc/hierarchyviewer.bat "$TOOLS"/
+    cp -v development/tools/draw9patch/etc/draw9patch.bat           "$TOOLS"/
+    cp -v development/tools/sdkmanager/app/etc/android.bat          "$TOOLS"/
 
     # Put the JetCreator tools, content and docs (not available in the linux SDK)
     JET="$TOOLS/Jet"
@@ -174,9 +176,9 @@
     mkdir -v "$JET"
     mkdir -v "$JETDOC"
 
-    cp -rv external/sonivox/jet_tools/JetCreator         "$JETCREATOR"
-    cp -rv external/sonivox/jet_tools/JetCreator_content "$JETDEMOCONTENT"
-    cp -rv external/sonivox/jet_tools/logic_templates    "$JETLOGICTEMPLATES"
+    cp -rv external/sonivox/jet_tools/JetCreator         "$JETCREATOR"/
+    cp -rv external/sonivox/jet_tools/JetCreator_content "$JETDEMOCONTENT"/
+    cp -rv external/sonivox/jet_tools/logic_templates    "$JETLOGICTEMPLATES"/
     chmod -vR u+w "$JETCREATOR"  # fixes an issue where Cygwin might copy the above as u+rx only
     cp -v prebuilt/windows/jetcreator/EASDLL.dll         "$JETCREATOR"/
     
@@ -186,16 +188,16 @@
     cp -rv external/sonivox/docs/JET_Creator_User_Manual_files  "$JETDOC"/
 
     # Copy or move platform specific tools to the default platform.
-    cp -v dalvik/dx/etc/dx.bat "$PLATFORM_TOOLS"
+    cp -v dalvik/dx/etc/dx.bat "$PLATFORM_TOOLS"/
     # Note: mgwz.dll must be in same folder than aapt.exe
-    mv -v "$TOOLS"/{aapt.exe,aidl.exe,dexdump.exe,mgwz.dll} "$PLATFORM_TOOLS"
+    mv -v "$TOOLS"/{aapt.exe,aidl.exe,dexdump.exe,mgwz.dll} "$PLATFORM_TOOLS"/
 
     # Fix EOL chars to make window users happy - fix all files at the top level only
     # as well as all batch files including those in platforms/<name>/tools/
     find "$TEMP_SDK_DIR" -maxdepth 1 -type f -writable -print0 | xargs -0 unix2dos -D
     find "$TEMP_SDK_DIR" -maxdepth 3 -name "*.bat" -type f -writable -print0 | xargs -0 unix2dos -D
 
-    # Done.. Zip it. Clean the temp folder ONLY if the zip worked (to easy debugging)
+    # Done.. Zip it. Clean the temp folder ONLY if the zip worked (to ease debugging)
     pushd "$TEMP_DIR" > /dev/null
     [ -e "$DEST_NAME_ZIP" ] && rm -rfv "$DEST_NAME_ZIP"
     zip -9r "$DEST_NAME_ZIP" "$DEST_NAME" && rm -rfv "$DEST_NAME"
diff --git a/tools/sdkmanager/app/src/com/android/sdkmanager/Main.java b/tools/sdkmanager/app/src/com/android/sdkmanager/Main.java
index 26af498..1836d33 100644
--- a/tools/sdkmanager/app/src/com/android/sdkmanager/Main.java
+++ b/tools/sdkmanager/app/src/com/android/sdkmanager/Main.java
@@ -386,9 +386,11 @@
             if (target.isPlatform()) {
                 mSdkLog.printf("     Type: Platform\n");
                 mSdkLog.printf("     API level: %d\n", target.getApiVersionNumber());
+                mSdkLog.printf("     Revision: %d\n", target.getRevision());
             } else {
                 mSdkLog.printf("     Type: Add-On\n");
                 mSdkLog.printf("     Vendor: %s\n", target.getVendor());
+                mSdkLog.printf("     Revision: %d\n", target.getRevision());
                 if (target.getDescription() != null) {
                     mSdkLog.printf("     Description: %s\n", target.getDescription());
                 }
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 c02c247..3ac0d1a 100644
--- a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/AddOnTarget.java
+++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/AddOnTarget.java
@@ -68,6 +68,7 @@
     private final PlatformTarget mBasePlatform;
     private final String mName;
     private final String mVendor;
+    private final int mRevision;
     private final String mDescription;
     private String[] mSkins;
     private String mDefaultSkin;
@@ -79,12 +80,13 @@
      * @param location the OS path location of the add-on
      * @param name the name of the add-on
      * @param vendor the vendor name of the add-on
+     * @param revision the revision of the add-on
      * @param description the add-on description
      * @param libMap A map containing the optional libraries. The map key is the fully-qualified
      * library name. The value is a 2 string array with the .jar filename, and the description.
      * @param basePlatform the platform the add-on is extending.
      */
-    AddOnTarget(String location, String name, String vendor, String description,
+    AddOnTarget(String location, String name, String vendor, int revision, String description,
             Map<String, String[]> libMap, PlatformTarget basePlatform) {
         if (location.endsWith(File.separator) == false) {
             location = location + File.separator;
@@ -93,6 +95,7 @@
         mLocation = location;
         mName = name;
         mVendor = vendor;
+        mRevision = revision;
         mDescription = description;
         mBasePlatform = basePlatform;
 
@@ -144,6 +147,10 @@
         return mBasePlatform.getApiVersionNumber();
     }
 
+    public int getRevision() {
+        return mRevision;
+    }
+
     public boolean isPlatform() {
         return false;
     }
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 d988340..f64b7ea 100644
--- a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/IAndroidTarget.java
+++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/IAndroidTarget.java
@@ -76,10 +76,15 @@
      */
     public final static int NO_USB_ID = 0;
 
+    /** An optional library provided by an Android Target */
     public interface IOptionalLibrary {
+        /** The name of the library, as used in the manifest (&lt;uses-library&gt;). */
         String getName();
+        /** The file name of the jar file. */
         String getJarName();
+        /** Absolute OS path to the jar file. */
         String getJarPath();
+        /** Description of the library. */
         String getDescription();
     }
 
@@ -123,6 +128,9 @@
      */
     String getApiVersionName();
 
+    /** Returns the revision number for the target. */
+    int getRevision();
+
     /**
      * Returns true if the target is a standard Android platform.
      */
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 bbb3cd7..ae621f3 100644
--- a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/PlatformTarget.java
+++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/PlatformTarget.java
@@ -35,12 +35,13 @@
     private final String mName;
     private final int mApiVersionNumber;
     private final String mApiVersionName;
+    private final int mRevision;
     private final Map<String, String> mProperties;
     private final Map<Integer, String> mPaths = new HashMap<Integer, String>();
     private String[] mSkins;
 
     PlatformTarget(String location, Map<String, String> properties,
-            int apiNumber, String apiName) {
+            int apiNumber, String apiName, int revision) {
         mName = String.format(PLATFORM_NAME, apiName);
         if (location.endsWith(File.separator) == false) {
             location = location + File.separator;
@@ -49,6 +50,7 @@
         mProperties = Collections.unmodifiableMap(properties);
         mApiVersionNumber = apiNumber;
         mApiVersionName = apiName;
+        mRevision = revision;
 
         // pre-build the path to the platform components
         mPaths.put(ANDROID_JAR, mLocation + SdkConstants.FN_FRAMEWORK_LIBRARY);
@@ -128,6 +130,10 @@
         return mApiVersionName;
     }
 
+    public int getRevision() {
+        return mRevision;
+    }
+
     public boolean isPlatform() {
         return true;
     }
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 ebafa77..7a0b06b 100644
--- a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java
+++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java
@@ -43,6 +43,7 @@
 
     public final static String PROP_VERSION_SDK = "ro.build.version.sdk";
     public final static String PROP_VERSION_RELEASE = "ro.build.version.release";
+    public final static String PROP_VERSION_REVISION = "ro.build.version.incremental";
 
     private final static String ADDON_NAME = "name";
     private final static String ADDON_VENDOR = "vendor";
@@ -51,6 +52,8 @@
     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 String ADDON_REVISION = "revision";
+    private final static String ADDON_REVISION_OLD = "version";
 
     private final static Pattern PATTERN_PROP = Pattern.compile(
             "^([a-zA-Z0-9._-]+)\\s*=\\s*(.*)\\s*$");
@@ -58,6 +61,9 @@
     private final static Pattern PATTERN_LIB_DATA = Pattern.compile(
             "^([a-zA-Z0-9._-]+\\.jar);(.*)$", Pattern.CASE_INSENSITIVE);
 
+    private final static Pattern PATTERN_LOCAL_BUILD_PATTERN = Pattern.compile(
+            "^\\S+\\.\\S+\\.(\\d+)\\.\\d+$");
+
      // usb ids are 16-bit hexadecimal values.
     private final static Pattern PATTERN_USB_IDS = Pattern.compile(
             "^0x[a-f0-9]{4}$", Pattern.CASE_INSENSITIVE);
@@ -234,36 +240,97 @@
 
             if (map != null) {
                 // look for some specific values in the map.
-                try {
-                    String apiNumber = map.get(PROP_VERSION_SDK);
-                    String apiName = map.get(PROP_VERSION_RELEASE);
-                    if (apiNumber != null && apiName != null) {
-                        // api number and name looks valid, perform a few more checks
-                        if (checkPlatformContent(platform, log) == false) {
-                            return null;
-                        }
-                        // create the target.
-                        PlatformTarget target = new PlatformTarget(
-                                platform.getAbsolutePath(),
-                                map,
-                                Integer.parseInt(apiNumber),
-                                apiName);
-
-                        // need to parse the skins.
-                        String[] skins = parseSkinFolder(target.getPath(IAndroidTarget.SKINS));
-                        target.setSkins(skins);
-
-                        return target;
-                    }
-                } catch (NumberFormatException e) {
-                    // looks like apiNumber does not parse to a number.
-                    // Ignore this platform.
+                String apiName = map.get(PROP_VERSION_RELEASE);
+                if (apiName == null) {
                     if (log != null) {
                         log.error(null,
-                                "Ignoring platform '%1$s': %2$s is not a valid number in %3$s.",
+                                "Ignoring platform '%1$s': %2$s is missing from '%3$s'",
+                                platform.getName(), PROP_VERSION_RELEASE, SdkConstants.FN_BUILD_PROP);
+                    }
+                    return null;
+                }
+
+                int apiNumber;
+                String stringValue = map.get(PROP_VERSION_SDK);
+                if (stringValue == null) {
+                    if (log != null) {
+                        log.error(null,
+                                "Ignoring platform '%1$s': %2$s is missing from '%3$s'",
                                 platform.getName(), PROP_VERSION_SDK, SdkConstants.FN_BUILD_PROP);
                     }
+                    return null;
+                } else {
+                    try {
+                         apiNumber = Integer.parseInt(stringValue);
+                    } catch (NumberFormatException e) {
+                        // looks like apiNumber does not parse to a number.
+                        // Ignore this platform.
+                        if (log != null) {
+                            log.error(null,
+                                    "Ignoring platform '%1$s': %2$s is not a valid number in %3$s.",
+                                    platform.getName(), PROP_VERSION_SDK, SdkConstants.FN_BUILD_PROP);
+                        }
+                        return null;
+                    }
                 }
+
+                int revision = 1;
+                stringValue = map.get(PROP_VERSION_REVISION);
+                if (stringValue == null) {
+                    if (log != null) {
+                        log.error(null,
+                                "Ignoring platform '%1$s': %2$s is missing from '%3$s'",
+                                platform.getName(), PROP_VERSION_REVISION, SdkConstants.FN_BUILD_PROP);
+                    }
+                    return null;
+                } else {
+                    try {
+                         revision = Integer.parseInt(stringValue);
+                    } catch (NumberFormatException e) {
+                        // looks like the revision does not parse to a number.
+                        // we look if it's a local build in the format
+                        // <buildtype>.<username>.<date>.<time>
+                        Matcher m = PATTERN_LOCAL_BUILD_PATTERN.matcher(stringValue);
+                        boolean valid = false;
+                        if (m.matches()) {
+                            String date = m.group(1);
+                            try {
+                                revision = Integer.parseInt(date);
+                                valid = true;
+                            } catch (NumberFormatException e2) {
+                                // do nothing, we'll display an error and return below
+                            }
+                        }
+
+                        if (valid == false) {
+                            if (log != null) {
+                                log.error(null,
+                                        "Ignoring platform '%1$s': %2$s is not a valid number in %3$s.",
+                                        platform.getName(), PROP_VERSION_SDK,
+                                        SdkConstants.FN_BUILD_PROP);
+                            }
+                            return null;
+                        }
+                    }
+                }
+
+                // api number and name look valid, perform a few more checks
+                if (checkPlatformContent(platform, log) == false) {
+                    return null;
+                }
+                // create the target.
+                PlatformTarget target = new PlatformTarget(
+                        platform.getAbsolutePath(),
+                        map,
+                        apiNumber,
+                        apiName,
+                        revision);
+
+                // need to parse the skins.
+                String[] skins = parseSkinFolder(target.getPath(IAndroidTarget.SKINS));
+                target.setSkins(skins);
+
+                return target;
             }
         } else if (log != null) {
             log.error(null, "Ignoring platform '%1$s': %2$s is missing.", platform.getName(),
@@ -374,6 +441,27 @@
                 // get the optional description
                 String description = propertyMap.get(ADDON_DESCRIPTION);
 
+                // get the add-on revision
+                int revisionValue = 1;
+                String revision = propertyMap.get(ADDON_REVISION);
+                if (revision == null) {
+                    revision = propertyMap.get(ADDON_REVISION_OLD);
+                }
+                if (revision != null) {
+                    try {
+                        revisionValue = Integer.parseInt(revision);
+                    } catch (NumberFormatException e) {
+                        // looks like apiNumber does not parse to a number.
+                        // Ignore this add-on.
+                        if (log != null) {
+                            log.error(null,
+                                    "Ignoring add-on '%1$s': %2$s is not a valid number in %3$s.",
+                                    addon.getName(), ADDON_REVISION, SdkConstants.FN_BUILD_PROP);
+                        }
+                        return null;
+                    }
+                }
+
                 // get the optional libraries
                 String librariesValue = propertyMap.get(ADDON_LIBRARIES);
                 Map<String, String[]> libMap = null;
@@ -413,7 +501,7 @@
                 }
 
                 AddOnTarget target = new AddOnTarget(addon.getAbsolutePath(), name, vendor,
-                        description, libMap, baseTarget);
+                        revisionValue, description, libMap, baseTarget);
 
                 // need to parse the skins.
                 String[] skins = parseSkinFolder(target.getPath(IAndroidTarget.SKINS));