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..."