merge cupcake into donut
diff --git a/apps/Fallback/res/values-es-rUS/strings.xml b/apps/Fallback/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..0ce5751
--- /dev/null
+++ b/apps/Fallback/res/values-es-rUS/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="appTitle">"Fallback"</string>
+    <string name="title">"Acción no admitida"</string>
+    <string name="error">"Esa acción no se admite actualmente."</string>
+</resources>
diff --git a/apps/SdkSetup/src/com/android/sdksetup/DefaultActivity.java b/apps/SdkSetup/src/com/android/sdksetup/DefaultActivity.java
index db6385c..56f43a4 100644
--- a/apps/SdkSetup/src/com/android/sdksetup/DefaultActivity.java
+++ b/apps/SdkSetup/src/com/android/sdksetup/DefaultActivity.java
@@ -38,9 +38,7 @@
 
         // Enable the GPS.
         // Not needed since this SDK will contain the Settings app.
-        LocationManager locationManager = (LocationManager)getSystemService(LOCATION_SERVICE);
         Settings.Secure.putString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED, LocationManager.GPS_PROVIDER);
-        locationManager.updateProviders();
         
         // enable install from non market
         Settings.Secure.putInt(getContentResolver(), Settings.Secure.INSTALL_NON_MARKET_APPS, 1);
diff --git a/cmds/monkey/src/com/android/commands/monkey/Monkey.java b/cmds/monkey/src/com/android/commands/monkey/Monkey.java
index 00fb40c..fe0de99 100644
--- a/cmds/monkey/src/com/android/commands/monkey/Monkey.java
+++ b/cmds/monkey/src/com/android/commands/monkey/Monkey.java
@@ -362,7 +362,7 @@
         
         if (mScriptFileName != null) {
             // script mode, ignore other options
-            mEventSource = new MonkeySourceScript(mScriptFileName);
+            mEventSource = new MonkeySourceScript(mScriptFileName, mThrottle);
             mEventSource.setVerbose(mVerbose);
         } else {
             // random source by default
diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeyEvent.java b/cmds/monkey/src/com/android/commands/monkey/MonkeyEvent.java
index 7176073..d926be8 100644
--- a/cmds/monkey/src/com/android/commands/monkey/MonkeyEvent.java
+++ b/cmds/monkey/src/com/android/commands/monkey/MonkeyEvent.java
@@ -51,6 +51,14 @@
     }
     
     /**
+     * @return true if it is safe to throttle after this event, and false otherwise.
+     */
+    public boolean isThrottlable() {
+        return true;
+    }
+    
+    
+    /**
      * a method for injecting event
      * @param iwm wires to current window manager
      * @param iam wires to current activity manager
diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeyEventQueue.java b/cmds/monkey/src/com/android/commands/monkey/MonkeyEventQueue.java
new file mode 100644
index 0000000..dfe389a
--- /dev/null
+++ b/cmds/monkey/src/com/android/commands/monkey/MonkeyEventQueue.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2008 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.commands.monkey;
+
+import java.util.LinkedList;
+
+/**
+ * class for keeping a monkey event queue
+ */
+@SuppressWarnings("serial")
+public class MonkeyEventQueue extends LinkedList<MonkeyEvent> {   
+
+    private long mThrottle;
+    
+    public MonkeyEventQueue(long throttle) {
+        super();
+        mThrottle = throttle;
+    }
+    
+    @Override
+    public void addLast(MonkeyEvent e) {
+        super.add(e);
+        if (e.isThrottlable()) {
+            super.add(new MonkeyThrottleEvent(mThrottle));
+        }
+    }
+}
diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeyKeyEvent.java b/cmds/monkey/src/com/android/commands/monkey/MonkeyKeyEvent.java
index c1e0ffc..877ebb5 100644
--- a/cmds/monkey/src/com/android/commands/monkey/MonkeyKeyEvent.java
+++ b/cmds/monkey/src/com/android/commands/monkey/MonkeyKeyEvent.java
@@ -92,6 +92,11 @@
     }
 
     @Override
+    public boolean isThrottlable() {
+        return (getAction() == KeyEvent.ACTION_UP);
+    }
+    
+    @Override
     public int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose) {
         if (verbose > 1) {
             String note;
diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeyMotionEvent.java b/cmds/monkey/src/com/android/commands/monkey/MonkeyMotionEvent.java
index 2657061..81c64b4 100644
--- a/cmds/monkey/src/com/android/commands/monkey/MonkeyMotionEvent.java
+++ b/cmds/monkey/src/com/android/commands/monkey/MonkeyMotionEvent.java
@@ -20,6 +20,7 @@
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.view.IWindowManager;
+import android.view.KeyEvent;
 import android.view.MotionEvent;
 
 
@@ -124,6 +125,11 @@
     }
 
     @Override
+    public boolean isThrottlable() {
+        return (getAction() == KeyEvent.ACTION_UP);
+    }
+    
+    @Override
     public int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose) {
         
         String note;
diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeySourceRandom.java b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceRandom.java
index 902d8e8..5f9c10f 100644
--- a/cmds/monkey/src/com/android/commands/monkey/MonkeySourceRandom.java
+++ b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceRandom.java
@@ -31,7 +31,7 @@
 /**
  * monkey event queue
  */
-public class MonkeySourceRandom implements MonkeyEventSource{    
+public class MonkeySourceRandom implements MonkeyEventSource {    
     /** Key events that move around the UI. */
     private static final int[] NAV_KEYS = {
         KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_DOWN,
@@ -168,7 +168,7 @@
     private float[] mFactors = new float[FACTORZ_COUNT];
     private ArrayList<ComponentName> mMainApps;
     private int mEventCount = 0;  //total number of events generated so far
-    private LinkedList<MonkeyEvent> mQ = new LinkedList<MonkeyEvent>();
+    private MonkeyEventQueue mQ;
     private Random mRandom;    
     private int mVerbose = 0;
     private long mThrottle = 0;
@@ -203,7 +203,7 @@
         mRandom = new SecureRandom();
         mRandom.setSeed((seed == 0) ? -1 : seed);
         mMainApps = MainApps;
-        mThrottle = throttle;
+        mQ = new MonkeyEventQueue(throttle);
     }
 
     /**
@@ -336,7 +336,6 @@
                 downAt, MotionEvent.ACTION_UP, x, y, 0);        
         e.setIntermediateNote(false);        
         mQ.addLast(e);
-        addThrottle();
     }
   
     /**
@@ -387,7 +386,6 @@
             e.setIntermediateNote(false);        
             mQ.addLast(e);
         }        
-        addThrottle();
     }
     
     /** 
@@ -420,13 +418,11 @@
             MonkeyActivityEvent e = new MonkeyActivityEvent(mMainApps.get(
                     mRandom.nextInt(mMainApps.size())));
             mQ.addLast(e);
-            addThrottle();
             return;
         } else if (cls < mFactors[FACTOR_FLIP]) {
             MonkeyFlipEvent e = new MonkeyFlipEvent(mKeyboardOpen);
             mKeyboardOpen = !mKeyboardOpen;
             mQ.addLast(e);
-            addThrottle();
             return;
         } else {
             lastKey = 1 + mRandom.nextInt(KeyEvent.getMaxKeyCode() - 1);
@@ -437,8 +433,6 @@
         
         e = new MonkeyKeyEvent(KeyEvent.ACTION_UP, lastKey);
         mQ.addLast(e);
-        
-        addThrottle();
     }
     
     public boolean validate() {
@@ -472,8 +466,4 @@
         mQ.removeFirst();        
         return e;
     }
-    
-    private void addThrottle() {
-        mQ.addLast(new MonkeyThrottleEvent(MonkeyEvent.EVENT_TYPE_THROTTLE, mThrottle));
-    }
 }
diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeySourceScript.java b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceScript.java
index aadda9f..869af2c 100644
--- a/cmds/monkey/src/com/android/commands/monkey/MonkeySourceScript.java
+++ b/cmds/monkey/src/com/android/commands/monkey/MonkeySourceScript.java
@@ -35,18 +35,19 @@
  *      type= raw events
  *      count= 10
  *      speed= 1.0
+ *      start data >>
  *      captureDispatchPointer(5109520,5109520,0,230.75429,458.1814,0.20784314,
  *          0.06666667,0,0.0,0.0,65539,0)
  *      captureDispatchKey(5113146,5113146,0,20,0,0,0,0)
  *      captureDispatchFlip(true)
  *      ...
  */
-public class MonkeySourceScript implements MonkeyEventSource{    
+public class MonkeySourceScript implements MonkeyEventSource {    
     private int mEventCountInScript = 0;  //total number of events in the file
     private int mVerbose = 0;
     private double mSpeed = 1.0;
     private String mScriptFileName; 
-    private LinkedList<MonkeyEvent> mQ = new LinkedList<MonkeyEvent>();
+    private MonkeyEventQueue mQ;
     
     private static final String HEADER_TYPE = "type=";
     private static final String HEADER_COUNT = "count=";
@@ -80,12 +81,14 @@
     // a line at the end of the header
     private static final String STARTING_DATA_LINE = "start data >>";    
     private boolean mFileOpened = false;    
+    
     FileInputStream mFStream;
     DataInputStream mInputStream;
     BufferedReader mBufferReader;
     
-    public MonkeySourceScript(String filename) {
+    public MonkeySourceScript(String filename, long throttle) {
         mScriptFileName = filename;
+        mQ = new MonkeyEventQueue(throttle);
     }
     
     /**
diff --git a/cmds/monkey/src/com/android/commands/monkey/MonkeyThrottleEvent.java b/cmds/monkey/src/com/android/commands/monkey/MonkeyThrottleEvent.java
index 3d7d48a..0b4e6b6 100644
--- a/cmds/monkey/src/com/android/commands/monkey/MonkeyThrottleEvent.java
+++ b/cmds/monkey/src/com/android/commands/monkey/MonkeyThrottleEvent.java
@@ -16,11 +16,10 @@
 
 package com.android.commands.monkey;
 
+import java.util.List;
+
 import android.app.IActivityManager;
-import android.os.RemoteException;
-import android.os.SystemClock;
 import android.view.IWindowManager;
-import android.view.MotionEvent;
 
 
 /**
@@ -29,8 +28,8 @@
 public class MonkeyThrottleEvent extends MonkeyEvent {
     private long mThrottle; 
         
-    public MonkeyThrottleEvent(int type, long throttle) {
-        super(type);
+    public MonkeyThrottleEvent(long throttle) {
+        super(MonkeyEvent.EVENT_TYPE_THROTTLE);
         mThrottle = throttle;
     }  
 
diff --git a/samples/ApiDemos/AndroidManifest.xml b/samples/ApiDemos/AndroidManifest.xml
index a53718e..d353d31 100644
--- a/samples/ApiDemos/AndroidManifest.xml
+++ b/samples/ApiDemos/AndroidManifest.xml
@@ -1104,6 +1104,13 @@
             </intent-filter>
         </activity>
 
+        <activity android:name=".view.Animation3" android:label="Views/Animation/Interpolators">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.SAMPLE_CODE" />
+            </intent-filter>
+        </activity>
+
         <activity android:name=".view.LayoutAnimation1" android:label="Views/Layout Animation/1. Grid Fade">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
diff --git a/samples/ApiDemos/res/layout/animation_3.xml b/samples/ApiDemos/res/layout/animation_3.xml
new file mode 100644
index 0000000..4d1474c
--- /dev/null
+++ b/samples/ApiDemos/res/layout/animation_3.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:padding="10dip"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:clipToPadding="false">
+
+    <TextView
+        android:id="@+id/target"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="26sp"
+        android:text="@string/animation_3_text"/>
+
+    <TextView
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="20dip"
+        android:layout_marginBottom="5dip"
+        android:text="@string/animation_2_instructions" />
+
+    <Spinner
+        android:id="@+id/spinner"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content" />
+
+</LinearLayout>
+
diff --git a/samples/ApiDemos/res/values/strings.xml b/samples/ApiDemos/res/values/strings.xml
index 0cafe14..29bbcec 100644
--- a/samples/ApiDemos/res/values/strings.xml
+++ b/samples/ApiDemos/res/values/strings.xml
@@ -476,6 +476,7 @@
     <string name="animation_2_text_3">a chance to be better.</string>
     <string name="animation_2_text_4">— Albert Camus</string>
     <string name="animation_2_instructions">Select an animation:</string>
+    <string name="animation_3_text">Interpolators</string>
     <string name="autocomplete_1_instructions">Type in the text field for auto-completion.</string>
     <string name="autocomplete_1_country">Country:</string>
     <string name="autocomplete_1_focus">Give me Focus</string>
diff --git a/samples/ApiDemos/src/com/example/android/apis/view/Animation3.java b/samples/ApiDemos/src/com/example/android/apis/view/Animation3.java
new file mode 100644
index 0000000..11fc9ed
--- /dev/null
+++ b/samples/ApiDemos/src/com/example/android/apis/view/Animation3.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2009 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.example.android.apis.view;
+
+// Need the following import to get access to the app resources, since this
+// class is in a sub-package.
+import com.example.android.apis.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Animation;
+import android.view.animation.TranslateAnimation;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Spinner;
+
+public class Animation3 extends Activity implements AdapterView.OnItemSelectedListener {
+    private static final String[] INTERPOLATORS = {
+            "Accelerate", "Decelerate", "Accelerate/Decelerate",
+            "Anticipate", "Overshoot", "Anticipate/Overshoot",
+            "Bounce"
+    };
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.animation_3);
+
+        Spinner s = (Spinner) findViewById(R.id.spinner);
+        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
+                android.R.layout.simple_spinner_item, INTERPOLATORS);
+        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        s.setAdapter(adapter);
+        s.setOnItemSelectedListener(this);
+    }
+
+    public void onItemSelected(AdapterView parent, View v, int position, long id) {
+        final View target = findViewById(R.id.target);
+        final View targetParent = (View) target.getParent();
+
+        Animation a = new TranslateAnimation(0.0f,
+                targetParent.getWidth() - target.getWidth() - targetParent.getPaddingLeft() -
+                targetParent.getPaddingRight(), 0.0f, 0.0f);
+        a.setDuration(1000);
+        a.setStartOffset(300);
+        a.setRepeatMode(Animation.RESTART);
+        a.setRepeatCount(Animation.INFINITE);
+
+        switch (position) {
+            case 0:
+                a.setInterpolator(AnimationUtils.loadInterpolator(this,
+                        android.R.anim.accelerate_interpolator));
+                break;
+            case 1:
+                a.setInterpolator(AnimationUtils.loadInterpolator(this,
+                        android.R.anim.decelerate_interpolator));
+                break;
+            case 2:
+                a.setInterpolator(AnimationUtils.loadInterpolator(this,
+                        android.R.anim.accelerate_decelerate_interpolator));
+                break;
+            case 3:
+                a.setInterpolator(AnimationUtils.loadInterpolator(this,
+                        android.R.anim.anticipate_interpolator));
+                break;
+            case 4:
+                a.setInterpolator(AnimationUtils.loadInterpolator(this,
+                        android.R.anim.overshoot_interpolator));
+                break;
+            case 5:
+                a.setInterpolator(AnimationUtils.loadInterpolator(this,
+                        android.R.anim.anticipate_overshoot_interpolator));
+                break;
+            case 6:
+                a.setInterpolator(AnimationUtils.loadInterpolator(this,
+                        android.R.anim.bounce_interpolator));
+                break;
+        }
+
+        target.startAnimation(a);
+    }
+
+    public void onNothingSelected(AdapterView parent) {
+    }
+}
\ No newline at end of file
diff --git a/testrunner/runtest.py b/testrunner/runtest.py
index 243da77..6d6c6df 100755
--- a/testrunner/runtest.py
+++ b/testrunner/runtest.py
@@ -23,6 +23,7 @@
 import glob
 import optparse
 import os
+import re
 from sets import Set
 import sys
 
@@ -58,6 +59,7 @@
 
   def __init__(self):
     # disable logging of timestamp
+    self._root_path = android_build.GetTop()
     logger.SetTimestampLogging(False)  
 
   def _ProcessOptions(self):
@@ -137,8 +139,6 @@
     if self._options.verbose:
       logger.SetVerbose(True)
 
-    self._root_path = android_build.GetTop()
-
     self._known_tests = self._ReadTests()
 
     self._coverage_gen = coverage.CoverageGenerator(
@@ -172,22 +172,30 @@
     """Prints out set of defined tests."""
     print "The following tests are currently defined:"
     for test in self._known_tests:
-      print test.GetName()
+      print "%-15s %s" % (test.GetName(), test.GetDescription())
 
   def _DoBuild(self):
     logger.SilentLog("Building tests...")
     target_set = Set()
+    extra_args_set = Set()
     for test_suite in self._GetTestsToRun():
-      self._AddBuildTarget(test_suite.GetBuildPath(), target_set)
+      self._AddBuildTarget(test_suite, target_set, extra_args_set)
 
     if target_set:
       if self._options.coverage:
         self._coverage_gen.EnableCoverageBuild()
-        self._AddBuildTarget(self._coverage_gen.GetEmmaBuildPath(), target_set)
+        self._AddBuildTargetPath(self._coverage_gen.GetEmmaBuildPath(),
+                                 target_set)
       target_build_string = " ".join(list(target_set))
-      logger.Log("mmm %s" % target_build_string)
-      cmd = 'ONE_SHOT_MAKEFILE="%s" make -C "%s" files' %  (target_build_string,
-                                                            self._root_path)
+      extra_args_string = " ".join(list(extra_args_set))
+      # log the user-friendly equivalent make command, so developers can
+      # replicate this step
+      logger.Log("mmm %s %s" % (target_build_string, extra_args_string))
+      # mmm cannot be used from python, so perform a similiar operation using
+      # ONE_SHOT_MAKEFILE
+      cmd = 'ONE_SHOT_MAKEFILE="%s" make -C "%s" files %s' % (
+          target_build_string, self._root_path, extra_args_string)
+
       if self._options.preview:
         # in preview mode, just display to the user what command would have been
         # run
@@ -197,11 +205,18 @@
         logger.Log("Syncing to device...")
         self._adb.Sync()
 
-  def _AddBuildTarget(self, build_dir, target_set):
+  def _AddBuildTarget(self, test_suite, target_set, extra_args_set):
+    build_dir = test_suite.GetBuildPath()
+    if self._AddBuildTargetPath(build_dir, target_set):
+      extra_args_set.add(test_suite.GetExtraMakeArgs())
+
+  def _AddBuildTargetPath(self, build_dir, target_set):
     if build_dir is not None:
       build_file_path = os.path.join(build_dir, "Android.mk")
       if os.path.isfile(os.path.join(self._root_path, build_file_path)):
         target_set.add(build_file_path)
+        return True
+    return False
 
   def _GetTestsToRun(self):
     """Get a list of TestSuite objects to run, based on command line args."""
@@ -261,6 +276,37 @@
         if coverage_file is not None:
           logger.Log("Coverage report generated at %s" % coverage_file)
 
+  def _RunNativeTest(self, test_suite):
+    """Run the provided *native* test suite.
+
+    The test_suite must contain a build path where the native test files are.
+    Each test's name must start with 'test_' and have a .cc or .cpp extension.
+    A successful test must return 0. Any other value will be considered
+    as an error.
+
+    Args:
+      test_suite: TestSuite to run
+    """
+    # find all test files, convert unicode names to ascii, take the basename
+    # and drop the .cc/.cpp  extension.
+    file_pattern = os.path.join(test_suite.GetBuildPath(), "test_*")
+    file_list = []
+    for f in map(str, glob.glob(file_pattern)):
+      f = os.path.basename(f)
+      f = re.split(".[cp]+$", f)[0]
+      file_list.append(f)
+
+    for f in file_list:
+      full_path = "/system/bin/%s" % f
+
+      # Single quotes are needed to prevent the shell splitting it.
+      status = self._adb.SendShellCommand("'%s >/dev/null 2>&1;echo -n $?'" %
+                                          full_path)
+      logger.Log("%s... %s" % (f, status == "0" and "ok" or "failed"))
+
+      # Cleanup
+      self._adb.SendShellCommand("rm %s" % full_path)
+
   def RunTests(self):
     """Main entry method - executes the tests according to command line args."""
     try:
@@ -278,7 +324,10 @@
         self._DoBuild()
 
       for test_suite in self._GetTestsToRun():
-        self._RunTest(test_suite)
+        if test_suite.IsNative():
+          self._RunNativeTest(test_suite)
+        else:
+          self._RunTest(test_suite)
     except KeyboardInterrupt:
       logger.Log("Exiting...")
     except errors.AbortError:
diff --git a/testrunner/test_defs.py b/testrunner/test_defs.py
index 949ad6e..2cdcfa8 100644
--- a/testrunner/test_defs.py
+++ b/testrunner/test_defs.py
@@ -38,7 +38,14 @@
        [class=""]
        [coverage_target=""]
        [build_path=""]
-       [continuous]
+       [continuous=false]
+       [description=""]
+      />
+     <test-native
+       name=""
+       build_path=""
+       [continuous=false]
+       [description=""]
       />
      <test  ...
    </test-definitions>
@@ -48,13 +55,17 @@
 
   # tag/attribute constants
   _TEST_TAG_NAME = "test"
+  _TEST_NATIVE_TAG_NAME = "test-native"
 
   def __init__(self):
     # dictionary of test name to tests
     self._testname_map = {}
 
   def __iter__(self):
-    return iter(self._testname_map.values())
+    ordered_list = []
+    for k in sorted(self._testname_map):
+      ordered_list.append(self._testname_map[k])
+    return iter(ordered_list)
 
   def Parse(self, file_path):
     """Parse the test suite data from from given file path.
@@ -87,6 +98,12 @@
       test = self._ParseTestSuite(suite_element)
       self._AddTest(test)
 
+    suite_elements = doc.getElementsByTagName(self._TEST_NATIVE_TAG_NAME)
+
+    for suite_element in suite_elements:
+      test = self._ParseNativeTestSuite(suite_element)
+      self._AddTest(test)
+
   def _ParseTestSuite(self, suite_element):
     """Parse the suite element.
     
@@ -96,6 +113,17 @@
     test = TestSuite(suite_element)
     return test
 
+  def _ParseNativeTestSuite(self, suite_element):
+    """Parse the native test element.
+
+    Returns:
+      a TestSuite object, populated with parsed data
+    Raises:
+      ParseError if some required attribute is missing.
+    """
+    test = TestSuite(suite_element, native=True)
+    return test
+
   def _AddTest(self, test):
     """Adds a test to this TestManifest.
     
@@ -129,13 +157,28 @@
   _TARGET_ATTR = "coverage_target"
   _BUILD_ATTR = "build_path"
   _CONTINUOUS_ATTR = "continuous"
+  _DESCRIPTION_ATTR = "description"
+  _EXTRA_MAKE_ARGS_ATTR = "extra_make_args"
 
   _DEFAULT_RUNNER = "android.test.InstrumentationTestRunner"
 
-  def __init__(self, suite_element):
-    """Populates this instance's data from given suite xml element."""
+  def __init__(self, suite_element, native=False):
+    """Populates this instance's data from given suite xml element.
+    Raises:
+      ParseError if some required attribute is missing.
+    """
+    self._native = native
     self._name = suite_element.getAttribute(self._NAME_ATTR)
-    self._package = suite_element.getAttribute(self._PKG_ATTR)
+
+    if self._native:
+      # For native runs, _BUILD_ATTR is required
+      if not suite_element.hasAttribute(self._BUILD_ATTR):
+        logger.Log("Error: %s is missing required build_path attribute" %
+                   self._name)
+        raise errors.ParseError
+    else:
+      self._package = suite_element.getAttribute(self._PKG_ATTR)
+
     if suite_element.hasAttribute(self._RUNNER_ATTR):
       self._runner = suite_element.getAttribute(self._RUNNER_ATTR)
     else:
@@ -156,6 +199,15 @@
       self._continuous = suite_element.getAttribute(self._CONTINUOUS_ATTR)
     else:
       self._continuous = False
+    if suite_element.hasAttribute(self._DESCRIPTION_ATTR):
+      self._description = suite_element.getAttribute(self._DESCRIPTION_ATTR)
+    else:
+      self._description = ""
+    if suite_element.hasAttribute(self._EXTRA_MAKE_ARGS_ATTR):
+      self._extra_make_args = suite_element.getAttribute(
+          self._EXTRA_MAKE_ARGS_ATTR)
+    else:
+      self._extra_make_args = ""
 
   def GetName(self):
     return self._name
@@ -184,6 +236,18 @@
     """Returns true if test is flagged as being part of the continuous tests"""  
     return self._continuous
 
+  def IsNative(self):
+    """Returns true if test is a native one."""
+    return self._native
+
+  def GetDescription(self):
+    """Returns a description if available, an empty string otherwise."""
+    return self._description
+
+  def GetExtraMakeArgs(self):
+    """Returns the extra make args if available, an empty string otherwise."""
+    return self._extra_make_args
+
 def Parse(file_path):
   """Parses out a TestDefinitions from given path to xml file.
 
diff --git a/testrunner/test_defs.xml b/testrunner/test_defs.xml
index 87159fd..dd56db1 100644
--- a/testrunner/test_defs.xml
+++ b/testrunner/test_defs.xml
@@ -17,32 +17,67 @@
 <!-- 
 This file contains standard test definitions for the Android platform
           
-Tests are defined by <test> tags with the following attributes
+Java tests are defined by <test> tags and native ones (C/C++) are defined by
+<test-native> tags.
 
-name package [class runner build_path coverage_target continuous]
+JAVA/application tests:
+=======================
+  The java <test> element has the following attributes
 
-Where:
-name: Self-descriptive name used to uniquely identify the test
-build_path: File system path, relative to Android build root, to this package's
-   Android.mk file. If omitted, build/sync step for this test will be skipped
-package: Android application package that contains the tests
-class: Optional. Fully qualified Java test class to run. 
-runner: Fully qualified InstrumentationTestRunner to execute. If omitted, 
-   will default to android.test.InstrumentationTestRunner
-coverage_target: Build name of Android package this test targets - these targets
-   are defined in the coverage_targets.xml file.  Used as basis for code
-   coverage metrics. If omitted, code coverage will not be supported for this
-   test
-continuous: Optional boolean. Default is false. Set to true if tests are known
-   to be reliable, and should be included in a continuous test system. false if
-   they are under development.
+  name package [class runner build_path coverage_target continuous description]
 
-These attributes map to the following commands:  
-(if class is defined)
-    adb shell am instrument -w <package>/<runner>
-(else)
-    adb shell am instrument -w -e class <class> <package>/<runner>
+  Where:
+  name: Self-descriptive name used to uniquely identify the test
+  build_path: File system path, relative to Android build root, to this
+    package's Android.mk file. If omitted, build/sync step for this test will
+    be skipped.
+  package: Android application package that contains the tests
+  class: Optional. Fully qualified Java test class to run. 
+  runner: Fully qualified InstrumentationTestRunner to execute. If omitted, 
+     will default to android.test.InstrumentationTestRunner.
+  coverage_target: Build name of Android package this test targets - these
+    targets are defined in the coverage_targets.xml file.  Used as basis for
+    code coverage metrics. If omitted, code coverage will not be supported for
+    this test.
+  continuous: Optional boolean. Default is false. Set to true if tests are known
+    to be reliable, and should be included in a continuous test system. false if
+    they are under development.
 
+  description: Optional string. Default is empty. Short description (typically 
+     less than 60 characters) about this test.
+
+  These attributes map to the following commands:  
+  (if class is defined)
+      adb shell am instrument -w <package>/<runner>
+  (else)
+      adb shell am instrument -w -e class <class> <package>/<runner>
+
+Native tests:
+=============
+  The <test-native> element has the following attributes
+
+  name build_path [continuous description]
+
+  Where:
+  name: Self-descriptive name used to uniquely identify the test
+  build_path: File system path, relative to Android build root, to this
+     package's Android.mk file. By convention the name of a test starts with
+     'test_'.
+  continuous: Optional boolean. Default is false. Set to true if tests are known
+     to be reliable, and should be included in a continuous test system.
+     false if they are under development.
+  description: Optional string. Default is empty. Short description (typically
+     less than 60 characters) about this test.
+  extra_make_args: Optional string. Default is empty. Some test module require
+     extra make arguments to build. This string is append to the make command.
+
+  These attributes map to the following commands:
+    make <build_path>/Android.mk <extra_make_args>
+    adb sync
+    for test_prog in <tests built>; do
+      adb shell "/system/bin/${test_prog} >/dev/null 2>&1;echo \$?"
+      adb shell "rm /system/bin/${test_prog}"
+    done
 -->
 
 <test-definitions version="1">
@@ -222,4 +257,11 @@
     coverage_target="Settings" />
 -->
 
+<!--  native tests  -->
+<test-native name="libstdcpp"
+    build_path="system/extras/tests/bionic/libstdc++"
+    description="Bionic libstdc++."
+    extra_make_args="BIONIC_TESTS=1" />
+
+
 </test-definitions>
diff --git a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/AndroidDebugBridge.java b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/AndroidDebugBridge.java
index 795bf88..0957171 100644
--- a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/AndroidDebugBridge.java
+++ b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/AndroidDebugBridge.java
@@ -194,6 +194,7 @@
         HandleThread.register(monitorThread);
         HandleHeap.register(monitorThread);
         HandleWait.register(monitorThread);
+        HandleProfiling.register(monitorThread);
     }
 
     /**
diff --git a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/HandleHeap.java b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/HandleHeap.java
index 5752b86..5111638 100644
--- a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/HandleHeap.java
+++ b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/HandleHeap.java
@@ -32,6 +32,7 @@
     public static final int CHUNK_HPEN = type("HPEN");
     public static final int CHUNK_HPSG = type("HPSG");
     public static final int CHUNK_HPGC = type("HPGC");
+    public static final int CHUNK_HPDU = type("HPDU");
     public static final int CHUNK_REAE = type("REAE");
     public static final int CHUNK_REAQ = type("REAQ");
     public static final int CHUNK_REAL = type("REAL");
@@ -98,6 +99,8 @@
             client.update(Client.CHANGE_HEAP_DATA);
         } else if (type == CHUNK_HPSG) {
             handleHPSG(client, data);
+        } else if (type == CHUNK_HPDU) {
+            handleHPDU(client, data);
         } else if (type == CHUNK_REAQ) {
             handleREAQ(client, data);
             client.update(Client.CHANGE_HEAP_ALLOCATION_STATUS);
@@ -221,6 +224,44 @@
     }
 
     /**
+     * Sends an HPDU request to the client.
+     *
+     * We will get an HPDU response when the heap dump has completed.  On
+     * failure we get a generic failure response.
+     *
+     * @param fileName name of output file (on device)
+     */
+    public static void sendHPDU(Client client, String fileName)
+        throws IOException {
+        ByteBuffer rawBuf = allocBuffer(4 + fileName.length() * 2);
+        JdwpPacket packet = new JdwpPacket(rawBuf);
+        ByteBuffer buf = getChunkDataBuf(rawBuf);
+
+        buf.putInt(fileName.length());
+        putString(buf, fileName);
+
+        finishChunkPacket(packet, CHUNK_HPDU, buf.position());
+        Log.d("ddm-heap", "Sending " + name(CHUNK_HPDU) + " '" + fileName +"'");
+        client.sendAndConsume(packet, mInst);
+    }
+
+    /*
+     * Handle notification of completion of a HeaP DUmp.
+     */
+    private void handleHPDU(Client client, ByteBuffer data) {
+        byte result;
+
+        result = data.get();
+
+        if (result == 0) {
+            Log.i("ddm-heap", "Heap dump request has finished");
+            // TODO: stuff
+        } else {
+            Log.w("ddm-heap", "Heap dump request failed (check device log)");
+        }
+    }
+
+    /**
      * Sends a REAE (REcent Allocation Enable) request to the client.
      */
     public static void sendREAE(Client client, boolean enable)
diff --git a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/HandleHello.java b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/HandleHello.java
index 5ba5aeb..fb9697c 100644
--- a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/HandleHello.java
+++ b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/HandleHello.java
@@ -20,11 +20,12 @@
 import java.nio.ByteBuffer;
 
 /**
- * Handle the "hello" chunk (HELO).
+ * Handle the "hello" chunk (HELO) and feature discovery.
  */
 final class HandleHello extends ChunkHandler {
 
     public static final int CHUNK_HELO = ChunkHandler.type("HELO");
+    public static final int CHUNK_FEAT = ChunkHandler.type("FEAT");
 
     private static final HandleHello mInst = new HandleHello();
 
@@ -65,6 +66,8 @@
         if (type == CHUNK_HELO) {
             assert isReply;
             handleHELO(client, data);
+        } else if (type == CHUNK_FEAT) {
+            handleFEAT(client, data);
         } else {
             handleUnknownChunk(client, type, data, isReply, msgId);
         }
@@ -126,5 +129,37 @@
             + " ID=0x" + Integer.toHexString(packet.getId()));
         client.sendAndConsume(packet, mInst);
     }
+
+    /**
+     * Handle a reply to our FEAT request.
+     */
+    private static void handleFEAT(Client client, ByteBuffer data) {
+        int featureCount;
+        int i;
+
+        featureCount = data.getInt();
+        for (i = 0; i < featureCount; i++) {
+            int len = data.getInt();
+            String feature = getString(data, len);
+
+            Log.d("ddm-hello", "Feature: " + feature);
+        }
+    }
+
+    /**
+     * Send a FEAT request to the client.
+     */
+    public static void sendFEAT(Client client) throws IOException {
+        ByteBuffer rawBuf = allocBuffer(0);
+        JdwpPacket packet = new JdwpPacket(rawBuf);
+        ByteBuffer buf = getChunkDataBuf(rawBuf);
+
+        // no data
+
+        finishChunkPacket(packet, CHUNK_FEAT, buf.position());
+        Log.d("ddm-heap", "Sending " + name(CHUNK_FEAT));
+        client.sendAndConsume(packet, mInst);
+    }
+
 }
 
diff --git a/tools/ddms/libs/ddmlib/src/com/android/ddmlib/HandleProfiling.java b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/HandleProfiling.java
new file mode 100644
index 0000000..e8e8103
--- /dev/null
+++ b/tools/ddms/libs/ddmlib/src/com/android/ddmlib/HandleProfiling.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2009 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.ddmlib;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * Handle heap status updates.
+ */
+final class HandleProfiling extends ChunkHandler {
+
+    public static final int CHUNK_MPRS = type("MPRS");
+    public static final int CHUNK_MPRE = type("MPRE");
+    public static final int CHUNK_MPRQ = type("MPRQ");
+
+    private static final HandleProfiling mInst = new HandleProfiling();
+
+    private HandleProfiling() {}
+
+    /**
+     * Register for the packets we expect to get from the client.
+     */
+    public static void register(MonitorThread mt) {
+        mt.registerChunkHandler(CHUNK_MPRE, mInst);
+        mt.registerChunkHandler(CHUNK_MPRQ, mInst);
+    }
+
+    /**
+     * Client is ready.
+     */
+    @Override
+    public void clientReady(Client client) throws IOException {}
+
+    /**
+     * Client went away.
+     */
+    @Override
+    public void clientDisconnected(Client client) {}
+
+    /**
+     * Chunk handler entry point.
+     */
+    @Override
+    public void handleChunk(Client client, int type, ByteBuffer data,
+        boolean isReply, int msgId) {
+
+        Log.d("ddm-prof", "handling " + ChunkHandler.name(type));
+
+        if (type == CHUNK_MPRE) {
+            handleMPRE(client, data);
+        } else if (type == CHUNK_MPRQ) {
+            handleMPRQ(client, data);
+        } else {
+            handleUnknownChunk(client, type, data, isReply, msgId);
+        }
+    }
+
+    /**
+     * Send a MPRS (Method PRofiling Start) request to the client.
+     *
+     * @param fileName is the name of the file to which profiling data
+     *          will be written (on the device); it will have ".trace"
+     *          appended if necessary
+     * @param bufferSize is the desired buffer size in bytes (8MB is good)
+     * @param flags should be zero
+     */
+    public static void sendMPRS(Client client, String fileName, int bufferSize,
+        int flags) throws IOException {
+
+        ByteBuffer rawBuf = allocBuffer(3*4 + fileName.length() * 2);
+        JdwpPacket packet = new JdwpPacket(rawBuf);
+        ByteBuffer buf = getChunkDataBuf(rawBuf);
+
+        buf.putInt(bufferSize);
+        buf.putInt(flags);
+        buf.putInt(fileName.length());
+        putString(buf, fileName);
+
+        finishChunkPacket(packet, CHUNK_MPRS, buf.position());
+        Log.d("ddm-prof", "Sending " + name(CHUNK_MPRS) + " '" + fileName
+            + "', size=" + bufferSize + ", flags=" + flags);
+        client.sendAndConsume(packet, mInst);
+    }
+
+    /**
+     * Send a MPRE (Method PRofiling End) request to the client.
+     */
+    public static void sendMPRE(Client client) throws IOException {
+        ByteBuffer rawBuf = allocBuffer(0);
+        JdwpPacket packet = new JdwpPacket(rawBuf);
+        ByteBuffer buf = getChunkDataBuf(rawBuf);
+
+        // no data
+
+        finishChunkPacket(packet, CHUNK_MPRE, buf.position());
+        Log.d("ddm-prof", "Sending " + name(CHUNK_MPRE));
+        client.sendAndConsume(packet, mInst);
+    }
+
+    /**
+     * Handle notification that method profiling has finished writing
+     * data to disk.
+     */
+    private void handleMPRE(Client client, ByteBuffer data) {
+        byte result;
+
+        result = data.get();
+
+        if (result == 0) {
+            Log.i("ddm-prof", "Method profiling has finished");
+        } else {
+            Log.w("ddm-prof", "Method profiling has failed (check device log)");
+        }
+
+        // TODO: stuff
+    }
+
+    /**
+     * Send a MPRQ (Method PRofiling Query) request to the client.
+     */
+    public static void sendMPRQ(Client client) throws IOException {
+        ByteBuffer rawBuf = allocBuffer(0);
+        JdwpPacket packet = new JdwpPacket(rawBuf);
+        ByteBuffer buf = getChunkDataBuf(rawBuf);
+
+        // no data
+
+        finishChunkPacket(packet, CHUNK_MPRQ, buf.position());
+        Log.d("ddm-prof", "Sending " + name(CHUNK_MPRQ));
+        client.sendAndConsume(packet, mInst);
+    }
+
+    /**
+     * Receive response to query.
+     */
+    private void handleMPRQ(Client client, ByteBuffer data) {
+        byte result;
+
+        result = data.get();
+
+        if (result == 0) {
+            Log.i("ddm-prof", "Method profiling is not running");
+        } else {
+            Log.i("ddm-prof", "Method profiling is running");
+        }
+    }
+}
+
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml b/tools/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
index 19cd509..6022a20 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
@@ -98,7 +98,7 @@
       <wizard
             canFinishEarly="false"
             category="com.android.ide.eclipse.wizards.category"
-            class="com.android.ide.eclipse.adt.wizards.newxmlfile.NewXmlFileWizard"
+            class="com.android.ide.eclipse.editors.wizards.NewXmlFileWizard"
             finalPerspective="org.eclipse.jdt.ui.JavaPerspective"
             hasPages="true"
             icon="icons/android.png"
@@ -220,7 +220,7 @@
                value="com.android.ide.eclipse.adt.AndroidNature">
          </filter>
          <action
-               class="com.android.ide.eclipse.adt.wizards.actions.NewXmlFileWizardAction"
+               class="com.android.ide.eclipse.adt.project.NewXmlFileWizardAction"
                enablesFor="1"
                id="com.android.ide.eclipse.adt.project.NewXmlFileWizardAction"
                label="New Resource File..."