summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/ActivityTests/res/anim/slow_enter.xml30
-rw-r--r--tests/ActivityTests/res/anim/slow_exit.xml30
-rw-r--r--tests/ActivityTests/res/interpolator/slow_enter.xml22
-rw-r--r--tests/ActivityTests/res/values/themes.xml (renamed from tests/TileBenchmark/tests/AndroidManifest.xml)22
-rw-r--r--tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java17
-rw-r--r--tests/BiDiTests/res/layout/basic.xml6
-rw-r--r--tests/BiDiTests/res/values/strings.xml11
-rw-r--r--tests/BiDiTests/src/com/android/bidi/BiDiTestView.java6
-rw-r--r--tests/CoreTests/android/core/CharArrayWriterTest.java48
-rw-r--r--tests/CoreTests/android/core/ClassLoaderTest.java243
-rw-r--r--tests/CoreTests/android/core/ClassTest.java337
-rw-r--r--tests/CoreTests/android/core/MiscRegressionTest.java452
-rw-r--r--tests/CoreTests/android/core/RegexTest.java287
-rw-r--r--tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java2
-rw-r--r--tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardService.java14
-rw-r--r--tests/HwAccelerationTest/AndroidManifest.xml30
-rw-r--r--tests/HwAccelerationTest/res/values/strings.xml19
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/MatrixActivity.java56
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/PaintDrawFilterActivity.java64
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/PosTextActivity.java79
-rw-r--r--tests/RenderScriptTests/ComputePerf/src/com/example/android/rs/computeperf/ComputePerf.java26
-rw-r--r--tests/RenderScriptTests/ComputePerf/src/com/example/android/rs/computeperf/LaunchTest.java15
-rw-r--r--tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/simplemodel.rs12
-rw-r--r--tests/RenderScriptTests/PerfTest/res/menu/loader_menu.xml7
-rw-r--r--tests/RenderScriptTests/PerfTest/res/raw/singletexf.glsl8
-rw-r--r--tests/RenderScriptTests/PerfTest/res/values/strings.xml4
-rw-r--r--tests/RenderScriptTests/PerfTest/src/com/android/perftest/FillTest.java154
-rw-r--r--tests/RenderScriptTests/PerfTest/src/com/android/perftest/MeshTest.java170
-rw-r--r--tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBench.java27
-rw-r--r--tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchBaseTest.java26
-rw-r--r--tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java568
-rw-r--r--tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchView.java26
-rw-r--r--tests/RenderScriptTests/PerfTest/src/com/android/perftest/TextTest.java93
-rw-r--r--tests/RenderScriptTests/PerfTest/src/com/android/perftest/TorusTest.java272
-rw-r--r--tests/RenderScriptTests/PerfTest/src/com/android/perftest/UiTest.java337
-rw-r--r--tests/RenderScriptTests/PerfTest/src/com/android/perftest/fill_test.rs137
-rw-r--r--tests/RenderScriptTests/PerfTest/src/com/android/perftest/mesh_test.rs89
-rw-r--r--tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs763
-rw-r--r--tests/RenderScriptTests/PerfTest/src/com/android/perftest/subtest_def.rsh4
-rw-r--r--tests/RenderScriptTests/PerfTest/src/com/android/perftest/text_test.rs10
-rw-r--r--tests/RenderScriptTests/PerfTest/src/com/android/perftest/torus_test.rs20
-rw-r--r--tests/RenderScriptTests/PerfTest/src/com/android/perftest/ui_test.rs444
-rw-r--r--tests/RenderScriptTests/ShadersTest/src/com/android/shaderstest/shaderstest.rs12
-rw-r--r--tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java7
-rw-r--r--tests/RenderScriptTests/tests/src/com/android/rs/test/UT_atomic.java40
-rw-r--r--tests/RenderScriptTests/tests/src/com/android/rs/test/UT_constant.java57
-rw-r--r--tests/RenderScriptTests/tests/src/com/android/rs/test/UT_primitives.java3
-rw-r--r--tests/RenderScriptTests/tests/src/com/android/rs/test/UT_rstime.java1
-rw-r--r--tests/RenderScriptTests/tests/src/com/android/rs/test/UT_struct.java55
-rw-r--r--tests/RenderScriptTests/tests/src/com/android/rs/test/UT_vector.java2
-rw-r--r--tests/RenderScriptTests/tests/src/com/android/rs/test/UnitTest.java20
-rw-r--r--tests/RenderScriptTests/tests/src/com/android/rs/test/atomic.rs77
-rw-r--r--tests/RenderScriptTests/tests/src/com/android/rs/test/constant.rs19
-rw-r--r--tests/RenderScriptTests/tests/src/com/android/rs/test/rstime.rs2
-rw-r--r--tests/RenderScriptTests/tests/src/com/android/rs/test/struct.rs37
-rw-r--r--tests/TileBenchmark/Android.mk10
-rw-r--r--tests/TileBenchmark/AndroidManifest.xml4
-rw-r--r--tests/TileBenchmark/res/layout/main.xml80
-rw-r--r--tests/TileBenchmark/res/values/strings.xml16
-rw-r--r--tests/TileBenchmark/src/com/test/tilebenchmark/PerformanceTest.java304
-rw-r--r--tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackGraphs.java107
-rw-r--r--tests/TileBenchmark/src/com/test/tilebenchmark/ProfileActivity.java68
-rw-r--r--tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java123
-rw-r--r--tests/TileBenchmark/tests/Android.mk16
-rw-r--r--tests/TileBenchmark/tests/src/com/test/tilebenchmark/PerformanceTest.java167
-rw-r--r--tests/TtsTests/Android.mk28
-rw-r--r--tests/TtsTests/AndroidManifest.xml43
-rw-r--r--tests/TtsTests/src/com/android/speech/tts/MockableCheckVoiceData.java58
-rw-r--r--tests/TtsTests/src/com/android/speech/tts/MockableTextToSpeechService.java78
-rw-r--r--tests/TtsTests/src/com/android/speech/tts/TextToSpeechTests.java229
-rw-r--r--tests/WebViewTests/Android.mk27
-rw-r--r--tests/WebViewTests/AndroidManifest.xml32
-rw-r--r--tests/WebViewTests/res/layout/webview_layout.xml25
-rw-r--r--tests/WebViewTests/src/com/android/webviewtests/JavaBridgeArrayCoercionTest.java625
-rw-r--r--tests/WebViewTests/src/com/android/webviewtests/JavaBridgeArrayTest.java226
-rw-r--r--tests/WebViewTests/src/com/android/webviewtests/JavaBridgeBasicsTest.java396
-rw-r--r--tests/WebViewTests/src/com/android/webviewtests/JavaBridgeCoercionTest.java646
-rw-r--r--tests/WebViewTests/src/com/android/webviewtests/JavaBridgeFieldsTest.java100
-rw-r--r--tests/WebViewTests/src/com/android/webviewtests/JavaBridgeReturnValuesTest.java199
-rw-r--r--tests/WebViewTests/src/com/android/webviewtests/JavaBridgeTestBase.java117
-rw-r--r--tests/WebViewTests/src/com/android/webviewtests/WebViewStubActivity.java38
-rw-r--r--tests/touchlag/Android.mk14
-rw-r--r--tests/touchlag/touchlag.cpp294
83 files changed, 6465 insertions, 2924 deletions
diff --git a/tests/ActivityTests/res/anim/slow_enter.xml b/tests/ActivityTests/res/anim/slow_enter.xml
new file mode 100644
index 0000000..0309643
--- /dev/null
+++ b/tests/ActivityTests/res/anim/slow_enter.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false" >
+ <scale android:fromXScale="0.9" android:toXScale="1.5"
+ android:fromYScale="0.9" android:toYScale="1.5"
+ android:pivotX="50%" android:pivotY="50%"
+ android:interpolator="@interpolator/slow_enter"
+ android:duration="40000" />
+ <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+ android:interpolator="@android:interpolator/decelerate_cubic"
+ android:duration="1000" />
+</set>
diff --git a/tests/ActivityTests/res/anim/slow_exit.xml b/tests/ActivityTests/res/anim/slow_exit.xml
new file mode 100644
index 0000000..6cd3114
--- /dev/null
+++ b/tests/ActivityTests/res/anim/slow_exit.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false" >
+ <scale android:fromXScale="1.0" android:toXScale="0.9"
+ android:fromYScale="1.0" android:toYScale="0.9"
+ android:pivotX="50%" android:pivotY="50%"
+ android:interpolator="@android:interpolator/decelerate_quint"
+ android:duration="300" />
+ <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+ android:interpolator="@android:interpolator/decelerate_cubic"
+ android:duration="300"/>
+</set>
diff --git a/tests/ActivityTests/res/interpolator/slow_enter.xml b/tests/ActivityTests/res/interpolator/slow_enter.xml
new file mode 100644
index 0000000..ddab1aa
--- /dev/null
+++ b/tests/ActivityTests/res/interpolator/slow_enter.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<cycleInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:cycles="10" />
diff --git a/tests/TileBenchmark/tests/AndroidManifest.xml b/tests/ActivityTests/res/values/themes.xml
index 703b152..67f5938 100644
--- a/tests/TileBenchmark/tests/AndroidManifest.xml
+++ b/tests/ActivityTests/res/values/themes.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
+<!-- Copyright (C) 2011 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -14,14 +14,12 @@
limitations under the License.
-->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.test.tilebenchmark.tests">
-
- <application>
- <uses-library android:name="android.test.runner" />
- </application>
-
- <instrumentation android:name="android.test.InstrumentationTestRunner"
- android:targetPackage="com.test.tilebenchmark"
- android:label="Tests for WebView Tiles."/>
-</manifest>
+<resources>
+ <style name="SlowDialog" parent="@android:style/Theme.Holo.Dialog">
+ <item name="android:windowAnimationStyle">@style/SlowDialog</item>
+ </style>
+ <style name="SlowDialog">
+ <item name="android:windowEnterAnimation">@anim/slow_enter</item>
+ <item name="android:windowExitAnimation">@anim/slow_exit</item>
+ </style>
+</resources>
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
index 583c13c..ae42e29 100644
--- a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
+++ b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
@@ -22,6 +22,7 @@ import java.util.List;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityThread;
+import android.app.AlertDialog;
import android.app.Application;
import android.content.ActivityNotFoundException;
import android.os.Bundle;
@@ -35,6 +36,8 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.ScrollView;
import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
import android.view.View;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -101,6 +104,20 @@ public class ActivityTestMain extends Activity {
}
@Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ menu.add("Animate!").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+ @Override public boolean onMenuItemClick(MenuItem item) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(ActivityTestMain.this,
+ R.style.SlowDialog);
+ builder.setTitle("This is a title");
+ builder.show();
+ return true;
+ }
+ });
+ return true;
+ }
+
+ @Override
protected void onStart() {
super.onStart();
buildUi();
diff --git a/tests/BiDiTests/res/layout/basic.xml b/tests/BiDiTests/res/layout/basic.xml
index f503658..7d4d4db 100644
--- a/tests/BiDiTests/res/layout/basic.xml
+++ b/tests/BiDiTests/res/layout/basic.xml
@@ -19,6 +19,10 @@
android:layout_width="fill_parent"
android:layout_height="fill_parent">
+ <ScrollView
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
<LinearLayout android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
@@ -131,4 +135,6 @@
</LinearLayout>
+ </ScrollView>
+
</FrameLayout>
diff --git a/tests/BiDiTests/res/values/strings.xml b/tests/BiDiTests/res/values/strings.xml
index b1f5e50..233cd0d 100644
--- a/tests/BiDiTests/res/values/strings.xml
+++ b/tests/BiDiTests/res/values/strings.xml
@@ -24,11 +24,11 @@
<string name="button_before_text">Start</string>
<string name="button_requestlayout_text">Request Layout</string>
<string name="button_alert_dialog_text">AlertDialog</string>
- <string name="textview_text">This is a text for a TextView</string>
- <string name="textview_ltr_text">This is a text for a LTR TextView</string>
- <string name="textview_rtl_text">This is a text for a RTL TextView</string>
- <string name="textview_default_text">This is a text for a default TextView</string>
- <string name="textview_password_default_text">This is a text for a password TextView</string>
+ <string name="textview_text">TextView</string>
+ <string name="textview_ltr_text">LTR TextView</string>
+ <string name="textview_rtl_text">RTL TextView</string>
+ <string name="textview_default_text">Default TextView</string>
+ <string name="textview_password_default_text">Password TextView</string>
<string name="edittext_text">mmmmmmmmmmmmmmmmmmmmmmmm</string>
<string name="normal_text">Normal String</string>
<string name="normal_long_text">mmmmmmmmmmmmmmmmmmmmmmmm</string>
@@ -50,5 +50,6 @@
<string name="rtl">"والحق أن تترك ونص"</string>
<string name="composing">"\u0644\u0627"</string>
<string name="url">www.amazon.co.uk/gp/aw/h.html/275-8912818-8203452</string>
+ <string name="pointer_location" msgid="6084434787496938001">"ตำแหน่งของตัวชี้"</string>
</resources>
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestView.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestView.java
index 0126dea..0b1974a 100644
--- a/tests/BiDiTests/src/com/android/bidi/BiDiTestView.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestView.java
@@ -51,6 +51,7 @@ public class BiDiTestView extends View {
private String MIXED_TEXT_1;
private String HEBREW_TEXT;
private String RTL_TEXT;
+ private String THAI_TEXT;
private int currentTextSize;
@@ -82,6 +83,7 @@ public class BiDiTestView extends View {
MIXED_TEXT_1 = context.getString(R.string.mixed_text_1);
HEBREW_TEXT = context.getString(R.string.hebrew_text);
RTL_TEXT = context.getString(R.string.rtl);
+ THAI_TEXT = context.getString(R.string.pointer_location);
}
public void setCurrentTextSize(int size) {
@@ -134,6 +136,10 @@ public class BiDiTestView extends View {
// Test Hebrew
deltaX = testString(canvas, RTL_TEXT, ORIGIN, ORIGIN + 14 * currentTextSize,
false, false, Paint.DIRECTION_RTL, currentTextSize);
+
+ // Test Thai
+ deltaX = testString(canvas, THAI_TEXT, ORIGIN, ORIGIN + 16 * currentTextSize,
+ false, false, Paint.DIRECTION_LTR, currentTextSize);
}
private int testString(Canvas canvas, String text, int x, int y,
diff --git a/tests/CoreTests/android/core/CharArrayWriterTest.java b/tests/CoreTests/android/core/CharArrayWriterTest.java
deleted file mode 100644
index 0aae1e4..0000000
--- a/tests/CoreTests/android/core/CharArrayWriterTest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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 android.core;
-
-import junit.framework.TestCase;
-
-import java.io.CharArrayWriter;
-import android.test.suitebuilder.annotation.SmallTest;
-
-/**
- * Basic tests for CharArrayWriter.
- */
-public class CharArrayWriterTest extends TestCase {
-
- @SmallTest
- public void testCharArrayWriter() throws Exception {
- String str = "AbCdEfGhIjKlMnOpQrStUvWxYz";
- CharArrayWriter a = new CharArrayWriter();
- CharArrayWriter b = new CharArrayWriter();
-
- a.write(str, 0, 26);
- a.write('X');
- a.writeTo(b);
-
- assertEquals(27, a.size());
- assertEquals("AbCdEfGhIjKlMnOpQrStUvWxYzX", a.toString());
-
- b.write("alphabravodelta", 5, 5);
- b.append('X');
- assertEquals("AbCdEfGhIjKlMnOpQrStUvWxYzXbravoX", b.toString());
- b.append("omega");
- assertEquals("AbCdEfGhIjKlMnOpQrStUvWxYzXbravoXomega", b.toString());
- }
-}
diff --git a/tests/CoreTests/android/core/ClassLoaderTest.java b/tests/CoreTests/android/core/ClassLoaderTest.java
deleted file mode 100644
index 5e7f5a4..0000000
--- a/tests/CoreTests/android/core/ClassLoaderTest.java
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * 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 android.core;
-
-import junit.framework.TestCase;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-import android.test.suitebuilder.annotation.Suppress;
-
-/**
- * Test for basic ClassLoader functionality.
- */
-@Suppress
-public class ClassLoaderTest extends TestCase {
- /*
- package my.pkg;
- public class CLTest {
- public CLTest() {}
-
- public String test() { return "This is test 1"; }
- }
- */
- static private byte[] test1class = {
- (byte) 0xca, (byte) 0xfe, (byte) 0xba, (byte) 0xbe,
- (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x31,
- (byte) 0x00, (byte) 0x11, (byte) 0x0a, (byte) 0x00,
- (byte) 0x04, (byte) 0x00, (byte) 0x0d, (byte) 0x08,
- (byte) 0x00, (byte) 0x0e, (byte) 0x07, (byte) 0x00,
- (byte) 0x0f, (byte) 0x07, (byte) 0x00, (byte) 0x10,
- (byte) 0x01, (byte) 0x00, (byte) 0x06, (byte) 0x3c,
- (byte) 0x69, (byte) 0x6e, (byte) 0x69, (byte) 0x74,
- (byte) 0x3e, (byte) 0x01, (byte) 0x00, (byte) 0x03,
- (byte) 0x28, (byte) 0x29, (byte) 0x56, (byte) 0x01,
- (byte) 0x00, (byte) 0x04, (byte) 0x43, (byte) 0x6f,
- (byte) 0x64, (byte) 0x65, (byte) 0x01, (byte) 0x00,
- (byte) 0x0f, (byte) 0x4c, (byte) 0x69, (byte) 0x6e,
- (byte) 0x65, (byte) 0x4e, (byte) 0x75, (byte) 0x6d,
- (byte) 0x62, (byte) 0x65, (byte) 0x72, (byte) 0x54,
- (byte) 0x61, (byte) 0x62, (byte) 0x6c, (byte) 0x65,
- (byte) 0x01, (byte) 0x00, (byte) 0x04, (byte) 0x74,
- (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x01,
- (byte) 0x00, (byte) 0x14, (byte) 0x28, (byte) 0x29,
- (byte) 0x4c, (byte) 0x6a, (byte) 0x61, (byte) 0x76,
- (byte) 0x61, (byte) 0x2f, (byte) 0x6c, (byte) 0x61,
- (byte) 0x6e, (byte) 0x67, (byte) 0x2f, (byte) 0x53,
- (byte) 0x74, (byte) 0x72, (byte) 0x69, (byte) 0x6e,
- (byte) 0x67, (byte) 0x3b, (byte) 0x01, (byte) 0x00,
- (byte) 0x0a, (byte) 0x53, (byte) 0x6f, (byte) 0x75,
- (byte) 0x72, (byte) 0x63, (byte) 0x65, (byte) 0x46,
- (byte) 0x69, (byte) 0x6c, (byte) 0x65, (byte) 0x01,
- (byte) 0x00, (byte) 0x0b, (byte) 0x43, (byte) 0x4c,
- (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74,
- (byte) 0x2e, (byte) 0x6a, (byte) 0x61, (byte) 0x76,
- (byte) 0x61, (byte) 0x0c, (byte) 0x00, (byte) 0x05,
- (byte) 0x00, (byte) 0x06, (byte) 0x01, (byte) 0x00,
- (byte) 0x0e, (byte) 0x54, (byte) 0x68, (byte) 0x69,
- (byte) 0x73, (byte) 0x20, (byte) 0x69, (byte) 0x73,
- (byte) 0x20, (byte) 0x74, (byte) 0x65, (byte) 0x73,
- (byte) 0x74, (byte) 0x20, (byte) 0x31, (byte) 0x01,
- (byte) 0x00, (byte) 0x0d, (byte) 0x6d, (byte) 0x79,
- (byte) 0x2f, (byte) 0x70, (byte) 0x6b, (byte) 0x67,
- (byte) 0x2f, (byte) 0x43, (byte) 0x4c, (byte) 0x54,
- (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x01,
- (byte) 0x00, (byte) 0x10, (byte) 0x6a, (byte) 0x61,
- (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x6c,
- (byte) 0x61, (byte) 0x6e, (byte) 0x67, (byte) 0x2f,
- (byte) 0x4f, (byte) 0x62, (byte) 0x6a, (byte) 0x65,
- (byte) 0x63, (byte) 0x74, (byte) 0x00, (byte) 0x21,
- (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x04,
- (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
- (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x01,
- (byte) 0x00, (byte) 0x05, (byte) 0x00, (byte) 0x06,
- (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x07,
- (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x1d,
- (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x01,
- (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x05,
- (byte) 0x2a, (byte) 0xb7, (byte) 0x00, (byte) 0x01,
- (byte) 0xb1, (byte) 0x00, (byte) 0x00, (byte) 0x00,
- (byte) 0x01, (byte) 0x00, (byte) 0x08, (byte) 0x00,
- (byte) 0x00, (byte) 0x00, (byte) 0x06, (byte) 0x00,
- (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00,
- (byte) 0x04, (byte) 0x00, (byte) 0x01, (byte) 0x00,
- (byte) 0x09, (byte) 0x00, (byte) 0x0a, (byte) 0x00,
- (byte) 0x01, (byte) 0x00, (byte) 0x07, (byte) 0x00,
- (byte) 0x00, (byte) 0x00, (byte) 0x1b, (byte) 0x00,
- (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x00,
- (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x12,
- (byte) 0x02, (byte) 0xb0, (byte) 0x00, (byte) 0x00,
- (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x08,
- (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x06,
- (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00,
- (byte) 0x00, (byte) 0x06, (byte) 0x00, (byte) 0x01,
- (byte) 0x00, (byte) 0x0b, (byte) 0x00, (byte) 0x00,
- (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x0c
- };
-
- /*
- package my.pkg;
- public class CLTest {
- public CLTest() {}
-
- public String test() { return "This is test 2"; }
- }
- */
- static private byte[] test2class = {
- (byte) 0xca, (byte) 0xfe, (byte) 0xba, (byte) 0xbe,
- (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x31,
- (byte) 0x00, (byte) 0x11, (byte) 0x0a, (byte) 0x00,
- (byte) 0x04, (byte) 0x00, (byte) 0x0d, (byte) 0x08,
- (byte) 0x00, (byte) 0x0e, (byte) 0x07, (byte) 0x00,
- (byte) 0x0f, (byte) 0x07, (byte) 0x00, (byte) 0x10,
- (byte) 0x01, (byte) 0x00, (byte) 0x06, (byte) 0x3c,
- (byte) 0x69, (byte) 0x6e, (byte) 0x69, (byte) 0x74,
- (byte) 0x3e, (byte) 0x01, (byte) 0x00, (byte) 0x03,
- (byte) 0x28, (byte) 0x29, (byte) 0x56, (byte) 0x01,
- (byte) 0x00, (byte) 0x04, (byte) 0x43, (byte) 0x6f,
- (byte) 0x64, (byte) 0x65, (byte) 0x01, (byte) 0x00,
- (byte) 0x0f, (byte) 0x4c, (byte) 0x69, (byte) 0x6e,
- (byte) 0x65, (byte) 0x4e, (byte) 0x75, (byte) 0x6d,
- (byte) 0x62, (byte) 0x65, (byte) 0x72, (byte) 0x54,
- (byte) 0x61, (byte) 0x62, (byte) 0x6c, (byte) 0x65,
- (byte) 0x01, (byte) 0x00, (byte) 0x04, (byte) 0x74,
- (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x01,
- (byte) 0x00, (byte) 0x14, (byte) 0x28, (byte) 0x29,
- (byte) 0x4c, (byte) 0x6a, (byte) 0x61, (byte) 0x76,
- (byte) 0x61, (byte) 0x2f, (byte) 0x6c, (byte) 0x61,
- (byte) 0x6e, (byte) 0x67, (byte) 0x2f, (byte) 0x53,
- (byte) 0x74, (byte) 0x72, (byte) 0x69, (byte) 0x6e,
- (byte) 0x67, (byte) 0x3b, (byte) 0x01, (byte) 0x00,
- (byte) 0x0a, (byte) 0x53, (byte) 0x6f, (byte) 0x75,
- (byte) 0x72, (byte) 0x63, (byte) 0x65, (byte) 0x46,
- (byte) 0x69, (byte) 0x6c, (byte) 0x65, (byte) 0x01,
- (byte) 0x00, (byte) 0x0b, (byte) 0x43, (byte) 0x4c,
- (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74,
- (byte) 0x2e, (byte) 0x6a, (byte) 0x61, (byte) 0x76,
- (byte) 0x61, (byte) 0x0c, (byte) 0x00, (byte) 0x05,
- (byte) 0x00, (byte) 0x06, (byte) 0x01, (byte) 0x00,
- (byte) 0x0e, (byte) 0x54, (byte) 0x68, (byte) 0x69,
- (byte) 0x73, (byte) 0x20, (byte) 0x69, (byte) 0x73,
- (byte) 0x20, (byte) 0x74, (byte) 0x65, (byte) 0x73,
- (byte) 0x74, (byte) 0x20, (byte) 0x32, (byte) 0x01,
- (byte) 0x00, (byte) 0x0d, (byte) 0x6d, (byte) 0x79,
- (byte) 0x2f, (byte) 0x70, (byte) 0x6b, (byte) 0x67,
- (byte) 0x2f, (byte) 0x43, (byte) 0x4c, (byte) 0x54,
- (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x01,
- (byte) 0x00, (byte) 0x10, (byte) 0x6a, (byte) 0x61,
- (byte) 0x76, (byte) 0x61, (byte) 0x2f, (byte) 0x6c,
- (byte) 0x61, (byte) 0x6e, (byte) 0x67, (byte) 0x2f,
- (byte) 0x4f, (byte) 0x62, (byte) 0x6a, (byte) 0x65,
- (byte) 0x63, (byte) 0x74, (byte) 0x00, (byte) 0x21,
- (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x04,
- (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
- (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x01,
- (byte) 0x00, (byte) 0x05, (byte) 0x00, (byte) 0x06,
- (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x07,
- (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x1d,
- (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x01,
- (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x05,
- (byte) 0x2a, (byte) 0xb7, (byte) 0x00, (byte) 0x01,
- (byte) 0xb1, (byte) 0x00, (byte) 0x00, (byte) 0x00,
- (byte) 0x01, (byte) 0x00, (byte) 0x08, (byte) 0x00,
- (byte) 0x00, (byte) 0x00, (byte) 0x06, (byte) 0x00,
- (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00,
- (byte) 0x04, (byte) 0x00, (byte) 0x01, (byte) 0x00,
- (byte) 0x09, (byte) 0x00, (byte) 0x0a, (byte) 0x00,
- (byte) 0x01, (byte) 0x00, (byte) 0x07, (byte) 0x00,
- (byte) 0x00, (byte) 0x00, (byte) 0x1b, (byte) 0x00,
- (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x00,
- (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x12,
- (byte) 0x02, (byte) 0xb0, (byte) 0x00, (byte) 0x00,
- (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x08,
- (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x06,
- (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00,
- (byte) 0x00, (byte) 0x06, (byte) 0x00, (byte) 0x01,
- (byte) 0x00, (byte) 0x0b, (byte) 0x00, (byte) 0x00,
- (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x0c
- };
-
- /*
- * Custom class loader.
- */
- private class MyLoader extends ClassLoader {
- public MyLoader(byte[] data) {
- super();
- mData = data;
- }
-
- protected Class<?> findClass(String name) throws ClassNotFoundException {
- assertEquals("my.pkg.CLTest", name);
- return defineClass(name, mData, 0, mData.length);
- }
-
- byte[] mData;
- }
-
-
- /*
- * Simple test: manually load two class files that have the same class
- * name but different contents.
- */
- public void testClassLoader() throws Exception {
- Class test1, test2;
- MyLoader loader1 = new MyLoader(test1class);
- MyLoader loader2 = new MyLoader(test2class);
-
- test1 = loader1.loadClass("my.pkg.CLTest");
- test2 = loader2.loadClass("my.pkg.CLTest");
-
- methodTest(test1, "This is test 1");
- methodTest(test2, "This is test 2");
- }
-
- /*
- * Invoke the test() method and verify that the string returned
- * matches what we expect.
- */
- private static void methodTest(Class clazz, String expect)
- throws NoSuchMethodException, InstantiationException,
- IllegalAccessException, InvocationTargetException {
- Method meth = clazz.getMethod("test", (Class[]) null);
- Object obj = clazz.newInstance();
- Object result = meth.invoke(obj, (Object[]) null);
-
- assertEquals(result, expect);
- }
-}
-
diff --git a/tests/CoreTests/android/core/ClassTest.java b/tests/CoreTests/android/core/ClassTest.java
deleted file mode 100644
index cc1b4ca..0000000
--- a/tests/CoreTests/android/core/ClassTest.java
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- * 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 android.core;
-
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.widget.Button;
-import junit.framework.TestCase;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.HashSet;
-import java.util.Set;
-
-
-class ClassWithPrivateConstructor {
- private ClassWithPrivateConstructor() {
- }
-}
-
-public class ClassTest extends TestCase {
-
- @SmallTest
- public void testClass() throws Exception {
- // Now, never mind the fact that most of this stuff has to work
- // for the test harness to get this far....
-
- //System.out.println("Class.forName()");
- Class helloClass = Class.forName(ClassTest.class.getName());
-
- //System.out.println("Class.newInstance()");
- Object instance = helloClass.newInstance();
- assertNotNull(instance);
-
- //System.out.println("Class.forName() nonexisting class");
- try {
- Class.forName("this.class.DoesNotExist");
- fail("unexpected success");
- } catch (ClassNotFoundException ex) {
- // expected
- }
-
- //System.out.println("Class.newInstance() private constructor");
- try {
- Class.forName("android.core.ClassWithPrivateConstructor").newInstance();
- fail("unexpected success");
- } catch (IllegalAccessException ex) {
- // this is expected
- }
-
- //System.out.println("Class.getDeclaredMethod()");
-
- Method method = helloClass.getDeclaredMethod("method", (Class[]) null);
-
- method.invoke(new ClassTest(), (Object[]) null);
-
- //System.out.println("Class.getDeclaredMethod() w/ args");
-
- method = helloClass.getDeclaredMethod("methodWithArgs", Object.class);
-
- Object invokeArgs[] = new Object[1];
- invokeArgs[0] = "Hello";
- Object ret = method.invoke(new ClassTest(), invokeArgs);
- assertEquals(ret, invokeArgs[0]);
-
- //System.out.println("Class.getDeclaredMethod() -- private");
-
- method = helloClass.getDeclaredMethod("privateMethod", (Class[]) null);
-
- method.invoke(new ClassTest(), (Object[]) null);
- //fail("unexpected success");
- // TODO: I think this actually *should* succeed, because the
- // call to the private method is being made from the same class.
- // This needs to be replaced with a private call to a different
- // class.
-
- //System.out.println("Class.getSuperclass");
- Class objectClass = Class.forName("java.lang.Object");
- assertEquals(helloClass.getSuperclass().getSuperclass().getSuperclass(), objectClass);
-
- //System.out.println("Class.isAssignableFrom");
- assertTrue(objectClass.isAssignableFrom(helloClass));
- assertFalse(helloClass.isAssignableFrom(objectClass));
-
- //System.out.println("Class.getConstructor");
-
- Constructor constructor = helloClass.getConstructor((Class[]) null);
- assertNotNull(constructor);
-
- //System.out.println("Class.getModifiers");
-
- assertTrue(Modifier.isPublic(helloClass.getModifiers()));
- //System.out.println("Modifiers: " + Modifier.toString(helloClass.getModifiers()));
-
- //System.out.println("Class.getMethod");
-
- helloClass.getMethod("method", (Class[]) null);
-
- try {
- Class[] argTypes = new Class[1];
- argTypes[0] = helloClass;
- helloClass.getMethod("method", argTypes);
- fail("unexpected success");
- } catch (NoSuchMethodException ex) {
- // exception expected
- }
-
- // Test for public tracker issue 14
- SimpleClass obj = new SimpleClass();
- Field field = obj.getClass().getDeclaredField("str");
- field.set(obj, null);
- }
-
- public class SimpleClass {
- public String str;
- }
-
- public Object methodWithArgs(Object o) {
- return o;
- }
-
- boolean methodInvoked;
-
- public void method() {
- methodInvoked = true;
- }
-
- boolean privateMethodInvoked;
-
- public void privateMethod() {
- privateMethodInvoked = true;
- }
-
- // Regression for 1018067: Class.getMethods() returns the same method over
- // and over again from all base classes
- @MediumTest
- public void testClassGetMethodsNoDupes() {
- Method[] methods = Button.class.getMethods();
- Set<String> set = new HashSet<String>();
-
- for (int i = 0; i < methods.length; i++) {
- String signature = methods[i].toString();
-
- int par = signature.indexOf('(');
- int dot = signature.lastIndexOf('.', par);
-
- signature = signature.substring(dot + 1);
-
- assertFalse("Duplicate " + signature, set.contains(signature));
- set.add(signature);
- }
- }
-
- interface MyInterface {
- void foo();
- }
-
- interface MyOtherInterface extends MyInterface {
- void bar();
- }
-
- abstract class MyClass implements MyOtherInterface {
- public void gabba() {
- }
-
- public void hey() {
- }
- }
-
- // Check if we also reflect methods from interfaces
- @SmallTest
- public void testGetMethodsInterfaces() {
- Method[] methods = MyInterface.class.getMethods();
- assertTrue("Interface method must be there", hasMethod(methods, ".foo("));
-
- methods = MyOtherInterface.class.getMethods();
- assertTrue("Interface method must be there", hasMethod(methods, ".foo("));
- assertTrue("Interface method must be there", hasMethod(methods, ".bar("));
-
- methods = MyClass.class.getMethods();
- assertTrue("Interface method must be there", hasMethod(methods, ".foo("));
- assertTrue("Interface method must be there", hasMethod(methods, ".bar("));
-
- assertTrue("Declared method must be there", hasMethod(methods, ".gabba("));
- assertTrue("Declared method must be there", hasMethod(methods, ".hey("));
-
- assertTrue("Inherited method must be there", hasMethod(methods, ".toString("));
- }
-
- private boolean hasMethod(Method[] methods, String signature) {
- for (int i = 0; i < methods.length; i++) {
- if (methods[i].toString().contains(signature)) {
- return true;
- }
- }
-
- return false;
- }
-
- // Test for Class.getPackage();
- @SmallTest
- public void testClassGetPackage() {
- assertNotNull("Package must be non-null", getClass().getPackage());
- assertEquals("Package must have expected name", "android.core", getClass().getPackage().getName());
- assertEquals("Package must have expected title", "Unknown", getClass().getPackage().getSpecificationTitle());
-
- Package p = java.lang.Object.class.getPackage();
- assertNotNull("Package must be non-null", p);
- assertEquals("Package must have expected name", "java.lang", p.getName());
- assertSame("Package object must be same for each call", p, java.lang.Object.class.getPackage());
- }
-
- // Regression test for #1123708: Problem with getCanonicalName(),
- // getSimpleName(), and getPackage().
- //
- // A couple of interesting cases need to be checked: Top-level classes,
- // member classes, local classes, and anonymous classes. Also, boundary
- // cases with '$' in the class names are checked, since the '$' is used
- // as the separator between outer and inner class, so this might lead
- // to problems (it did in the previous implementation).
- //
- // Caution: Adding local or anonymous classes elsewhere in this
- // file might affect the test.
- private class MemberClass {
- // This space intentionally left blank.
- }
-
- private class Mi$o$oup {
- // This space intentionally left blank.
- }
-
- @SmallTest
- public void testVariousClassNames() {
- Class<?> clazz = this.getClass();
- String pkg = (clazz.getPackage() == null ? "" : clazz.getPackage().getName() + ".");
-
- // Simple, top-level class
-
- assertEquals("Top-level class name must be correct", pkg + "ClassTest", clazz.getName());
- assertEquals("Top-level class simple name must be correct", "ClassTest", clazz.getSimpleName());
- assertEquals("Top-level class canonical name must be correct", pkg + "ClassTest", clazz.getCanonicalName());
-
- clazz = MemberClass.class;
-
- assertEquals("Member class name must be correct", pkg + "ClassTest$MemberClass", clazz.getName());
- assertEquals("Member class simple name must be correct", "MemberClass", clazz.getSimpleName());
- assertEquals("Member class canonical name must be correct", pkg + "ClassTest.MemberClass", clazz.getCanonicalName());
-
- class LocalClass {
- // This space intentionally left blank.
- }
-
- clazz = LocalClass.class;
-
- assertEquals("Local class name must be correct", pkg + "ClassTest$1LocalClass", clazz.getName());
- assertEquals("Local class simple name must be correct", "LocalClass", clazz.getSimpleName());
- assertNull("Local class canonical name must be null", clazz.getCanonicalName());
-
- clazz = new Object() { }.getClass();
-
- assertEquals("Anonymous class name must be correct", pkg + "ClassTest$1", clazz.getName());
- assertEquals("Anonymous class simple name must be empty", "", clazz.getSimpleName());
- assertNull("Anonymous class canonical name must be null", clazz.getCanonicalName());
-
- // Weird special cases with dollar in name.
-
- clazz = Mou$$aka.class;
-
- assertEquals("Top-level class name must be correct", pkg + "Mou$$aka", clazz.getName());
- assertEquals("Top-level class simple name must be correct", "Mou$$aka", clazz.getSimpleName());
- assertEquals("Top-level class canonical name must be correct", pkg + "Mou$$aka", clazz.getCanonicalName());
-
- clazz = Mi$o$oup.class;
-
- assertEquals("Member class name must be correct", pkg + "ClassTest$Mi$o$oup", clazz.getName());
- assertEquals("Member class simple name must be correct", "Mi$o$oup", clazz.getSimpleName());
- assertEquals("Member class canonical name must be correct", pkg + "ClassTest.Mi$o$oup", clazz.getCanonicalName());
-
- class Ma$hedPotatoe$ {
- // This space intentionally left blank.
- }
-
- clazz = Ma$hedPotatoe$.class;
-
- assertEquals("Member class name must be correct", pkg + "ClassTest$1Ma$hedPotatoe$", clazz.getName());
- assertEquals("Member class simple name must be correct", "Ma$hedPotatoe$", clazz.getSimpleName());
- assertNull("Member class canonical name must be null", clazz.getCanonicalName());
- }
-
- @SmallTest
- public void testLocalMemberClass() {
- Class<?> clazz = this.getClass();
-
- assertFalse("Class must not be member", clazz.isMemberClass());
- assertFalse("Class must not be local", clazz.isLocalClass());
-
- clazz = MemberClass.class;
-
- assertTrue("Class must be member", clazz.isMemberClass());
- assertFalse("Class must not be local", clazz.isLocalClass());
-
- class OtherLocalClass {
- // This space intentionally left blank.
- }
-
- clazz = OtherLocalClass.class;
-
- assertFalse("Class must not be member", clazz.isMemberClass());
- assertTrue("Class must be local", clazz.isLocalClass());
-
- clazz = new Object() { }.getClass();
-
- assertFalse("Class must not be member", clazz.isMemberClass());
- assertFalse("Class must not be local", clazz.isLocalClass());
- }
-
-}
-
-class Mou$$aka {
- // This space intentionally left blank.
-}
diff --git a/tests/CoreTests/android/core/MiscRegressionTest.java b/tests/CoreTests/android/core/MiscRegressionTest.java
index 7734397..32995b5 100644
--- a/tests/CoreTests/android/core/MiscRegressionTest.java
+++ b/tests/CoreTests/android/core/MiscRegressionTest.java
@@ -16,56 +16,12 @@
package android.core;
-import junit.framework.Assert;
-import junit.framework.TestCase;
-
-import java.io.File;
-import java.io.InputStream;
-import java.io.ObjectInputStream;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.security.KeyStore;
-import java.security.cert.Certificate;
-import java.util.Arrays;
-import java.util.ConcurrentModificationException;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.Random;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-import java.util.logging.Logger;
-import java.util.zip.Deflater;
-import java.util.zip.Inflater;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.test.suitebuilder.annotation.LargeTest;
+import java.util.logging.Logger;
+import junit.framework.TestCase;
public class MiscRegressionTest extends TestCase {
- // Regression test for #857840: want JKS key store
- @SmallTest
- public void testDefaultKeystore() {
- String type = KeyStore.getDefaultType();
- Assert.assertEquals("Default keystore type must be Bouncy Castle", "BKS", type);
-
- try {
- KeyStore store = KeyStore.getInstance(KeyStore.getDefaultType());
- Assert.assertNotNull("Keystore must not be null", store);
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
-
- try {
- KeyStore store = KeyStore.getInstance("BKS");
- Assert.assertNotNull("Keystore must not be null", store);
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
- }
-
// Regression test for #951285: Suitable LogHandler should be chosen
// depending on the environment.
@MediumTest
@@ -78,408 +34,4 @@ public class MiscRegressionTest extends TestCase {
Logger.global.finer("This has logging Level.FINER, should become VERBOSE");
Logger.global.finest("This has logging Level.FINEST, should become VERBOSE");
}
-
- // Regression test for Issue 5697:
- // getContextClassLoader returns a non-application classloader
- // http://code.google.com/p/android/issues/detail?id=5697
- //
- @MediumTest
- public void testJavaContextClassLoader() throws Exception {
- Assert.assertNotNull("Must hava a Java context ClassLoader",
- Thread.currentThread().getContextClassLoader());
- }
-
- // Regression test for #1045939: Different output for Method.toString()
- @SmallTest
- public void testMethodToString() {
- try {
- Method m1 = Object.class.getMethod("notify", new Class[] { });
- Method m2 = Object.class.getMethod("toString", new Class[] { });
- Method m3 = Object.class.getMethod("wait", new Class[] { long.class, int.class });
- Method m4 = Object.class.getMethod("equals", new Class[] { Object.class });
- Method m5 = String.class.getMethod("valueOf", new Class[] { char[].class });
- Method m6 = Runtime.class.getMethod("exec", new Class[] { String[].class });
-
- assertEquals("Method.toString() must match expectations",
- "public final native void java.lang.Object.notify()",
- m1.toString());
-
- assertEquals("Method.toString() must match expectations",
- "public java.lang.String java.lang.Object.toString()",
- m2.toString());
-
- assertEquals("Method.toString() must match expectations",
- "public final native void java.lang.Object.wait(long,int) throws java.lang.InterruptedException",
- m3.toString());
-
- assertEquals("Method.toString() must match expectations",
- "public boolean java.lang.Object.equals(java.lang.Object)",
- m4.toString());
-
- assertEquals("Method.toString() must match expectations",
- "public static java.lang.String java.lang.String.valueOf(char[])",
- m5.toString());
-
- assertEquals("Method.toString() must match expectations",
- "public java.lang.Process java.lang.Runtime.exec(java.lang.String[]) throws java.io.IOException",
- m6.toString());
-
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
-
- }
-
- // Regression test for #1062200: Enum fails to deserialize. Actual problem
- // was that Class.isEnum() erroneously returned true for indirect
- // descendants of Enum.
- enum TrafficLights {
- RED,
- YELLOW {},
- GREEN {
- @SuppressWarnings("unused")
- int i;
- @SuppressWarnings("unused")
- void foobar() {}
- };
- }
-
- @SmallTest
- public void testClassIsEnum() {
- Class<?> trafficClass = TrafficLights.class;
-
- Class<?> redClass = TrafficLights.RED.getClass();
- Class<?> yellowClass = TrafficLights.YELLOW.getClass();
- Class<?> greenClass = TrafficLights.GREEN.getClass();
-
- Assert.assertSame("Classes must be equal", trafficClass, redClass);
- Assert.assertNotSame("Classes must be different", trafficClass, yellowClass);
- Assert.assertNotSame("Classes must be different", trafficClass, greenClass);
- Assert.assertNotSame("Classes must be different", yellowClass, greenClass);
-
- Assert.assertTrue("Must be an enum", trafficClass.isEnum());
- Assert.assertTrue("Must be an enum", redClass.isEnum());
- Assert.assertFalse("Must not be an enum", yellowClass.isEnum());
- Assert.assertFalse("Must not be an enum", greenClass.isEnum());
-
- Assert.assertNotNull("Must have enum constants", trafficClass.getEnumConstants());
- Assert.assertNull("Must not have enum constants", yellowClass.getEnumConstants());
- Assert.assertNull("Must not have enum constants", greenClass.getEnumConstants());
- }
-
- // Regression test for #1046174: JarEntry.getCertificates() is really slow.
- public void checkJarCertificates(File file) {
- try {
- JarFile jarFile = new JarFile(file);
- JarEntry je = jarFile.getJarEntry("AndroidManifest.xml");
- byte[] readBuffer = new byte[1024];
-
- long t0 = System.currentTimeMillis();
-
- // We must read the stream for the JarEntry to retrieve
- // its certificates.
- InputStream is = jarFile.getInputStream(je);
- while (is.read(readBuffer, 0, readBuffer.length) != -1) {
- // not using
- }
- is.close();
- Certificate[] certs = je != null ? je.getCertificates() : null;
-
- long t1 = System.currentTimeMillis();
- android.util.Log.d("TestHarness", "loadCertificates() took " + (t1 - t0) + " ms");
- if (certs == null) {
- android.util.Log.d("TestHarness", "We have no certificates");
- } else {
- android.util.Log.d("TestHarness", "We have " + certs.length + " certificates");
- }
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
- }
-
- @LargeTest
- public void testJarCertificates() {
- File[] files = new File("/system/app").listFiles();
- for (int i = 0; i < files.length; i++) {
- checkJarCertificates(files[i]);
- }
- }
-
- // Regression test for #1120750: Reflection for static long fields is broken
- private static final long MY_LONG = 5073258162644648461L;
-
- @SmallTest
- public void testLongFieldReflection() {
- try {
- Field field = getClass().getDeclaredField("MY_LONG");
- assertEquals(5073258162644648461L, field.getLong(null));
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
- }
-
- // Regression test for Harmony LinkedHashMap bug. Copied from core, just
- // to make sure it doesn't get lost.
- @SmallTest
- public void testLinkedHashMap() {
- // we want to test the LinkedHashMap in access ordering mode.
- LinkedHashMap map = new LinkedHashMap<String, String>(10, 0.75f, true);
-
- map.put("key1", "value1");
- map.put("key2", "value2");
- map.put("key3", "value3");
-
- Iterator iterator = map.keySet().iterator();
- String id = (String) iterator.next();
- map.get(id);
- try {
- iterator.next();
- // A LinkedHashMap is supposed to throw this Exception when a
- // iterator.next() Operation takes place after a get
- // Operation. This is because the get Operation is considered
- // a structural modification if the LinkedHashMap is in
- // access order mode.
- fail("expected ConcurrentModificationException was not thrown.");
- } catch(ConcurrentModificationException e) {
- // expected
- }
-
- LinkedHashMap mapClone = (LinkedHashMap) map.clone();
-
- iterator = map.keySet().iterator();
- id = (String) iterator.next();
- mapClone.get(id);
- try {
- iterator.next();
- } catch(ConcurrentModificationException e) {
- fail("expected ConcurrentModificationException was not thrown.");
- }
- }
-
- // Regression test for #1212257: Boot-time package scan is slow. Not
- // expected to fail. Please see log if you are interested in the results.
- @LargeTest
- public void testZipStressManifest() {
- android.util.Log.d("MiscRegressionTest", "ZIP stress test started");
-
- long time0 = System.currentTimeMillis();
-
- try {
- File[] files = new File("/system/app").listFiles();
-
- byte[] buffer = new byte[512];
-
- if (files != null) {
- for (int i = 0; i < files.length; i++) {
- android.util.Log.d("MiscRegressionTest",
- "ZIP stress test processing " + files[i] + "...");
-
- ZipFile zip = new ZipFile(files[i]);
-
- ZipEntry entry = zip.getEntry("AndroidManifest.xml");
- InputStream stream = zip.getInputStream(entry);
-
- int j = stream.read(buffer);
- while (j != -1) {
- j = stream.read(buffer);
- }
-
- stream.close();
- }
- }
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
-
- long time1 = System.currentTimeMillis();
-
- android.util.Log.d("MiscRegressionTest", "ZIP stress test finished, " +
- "time was " + (time1- time0) + "ms");
- }
-
- @LargeTest
- public void testZipStressAllFiles() {
- android.util.Log.d("MiscRegressionTest", "ZIP stress test started");
-
- long time0 = System.currentTimeMillis();
-
- try {
- File[] files = new File("/system/app").listFiles();
-
- byte[] buffer = new byte[512];
-
- if (files != null) {
- for (int i = 0; i < files.length; i++) {
- android.util.Log.d("MiscRegressionTest",
- "ZIP stress test processing " + files[i] + "...");
-
- ZipFile zip = new ZipFile(files[i]);
-
- Enumeration<? extends ZipEntry> entries = zip.entries();
- while (entries.hasMoreElements()) {
- InputStream stream = zip.getInputStream(entries.nextElement());
-
- int j = stream.read(buffer);
- while (j != -1) {
- j = stream.read(buffer);
- }
-
- stream.close();
- }
- }
- }
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
-
- long time1 = System.currentTimeMillis();
-
- android.util.Log.d("MiscRegressionTest", "ZIP stress test finished, " +
- "time was " + (time1- time0) + "ms");
- }
-
- @SmallTest
- public void testOsEncodingProperty() {
- long time0 = System.currentTimeMillis();
- String[] files = new File("/system/app").list();
- long time1 = System.currentTimeMillis();
- android.util.Log.d("MiscRegressionTest", "File.list() test finished, " +
- "time was " + (time1- time0) + "ms");
- }
-
- // -------------------------------------------------------------------------
- // Regression test for #1185084: Native memory allocated by
- // java.util.zip.Deflater in system_server. The fix reduced some internal
- // ZLIB buffers in size, so this test is trying to execute a lot of
- // deflating to ensure that things are still working properly.
- private void assertEquals(byte[] a, byte[] b) {
- assertEquals("Arrays must have same length", a.length, b.length);
-
- for (int i = 0; i < a.length; i++) {
- assertEquals("Array elements #" + i + " must be equal", a[i], b[i]);
- }
- }
-
- @LargeTest
- public void testZipDeflateInflateStress() {
-
- final int DATA_SIZE = 16384;
-
- Random random = new Random(42); // Seed makes test reproducible
-
- try {
- // Outer loop selects "mode" of test.
- for (int j = 1; j <=2 ; j++) {
-
- byte[] input = new byte[DATA_SIZE];
-
- if (j == 1) {
- // Totally random content
- random.nextBytes(input);
- } else {
- // Random contents with longer repetitions
- int pos = 0;
- while (pos < input.length) {
- byte what = (byte)random.nextInt(256);
- int howMany = random.nextInt(32);
- if (pos + howMany >= input.length) {
- howMany = input.length - pos;
- }
- Arrays.fill(input, pos, pos + howMany, what);
- pos += howMany;
- }
- }
-
- // Inner loop tries all 9 compression levels.
- for (int i = 1; i <= 9; i++) {
- android.util.Log.d("MiscRegressionTest", "ZipDeflateInflateStress test (" + j + "," + i + ")...");
-
- byte[] zipped = new byte[2 * DATA_SIZE]; // Just to make sure...
-
- Deflater deflater = new Deflater(i);
- deflater.setInput(input);
- deflater.finish();
-
- deflater.deflate(zipped);
-
- byte[] output = new byte[DATA_SIZE];
-
- Inflater inflater = new Inflater();
- inflater.setInput(zipped);
- inflater.finished();
-
- inflater.inflate(output);
-
- assertEquals(input, output);
- }
- }
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
- }
-
- // -------------------------------------------------------------------------
- // Regression test for #1252043: Thread.getStackTrace() is broken
- class MyThread extends Thread {
- public MyThread(String name) {
- super(name);
- }
-
- @Override
- public void run() {
- doSomething();
- }
-
- public void doSomething() {
- for (int i = 0; i < 20;) {
- try {
- Thread.sleep(100);
- } catch (InterruptedException ex) {
- }
- }
- }
- }
-
- class MyOtherThread extends Thread {
- public int visibleTraces;
-
- public MyOtherThread(ThreadGroup group, String name) {
- super(group, name);
- }
-
- @Override
- public void run() {
- visibleTraces = Thread.getAllStackTraces().size();
- }
- }
-
- @LargeTest
- public void testThreadGetStackTrace() {
- MyThread t1 = new MyThread("t1");
- t1.start();
-
- try {
- Thread.sleep(1000);
- } catch (InterruptedException ex) {
- }
-
- StackTraceElement[] traces = t1.getStackTrace();
- StackTraceElement trace = traces[traces.length - 2];
-
- // Expect to find MyThread.doSomething in the trace
- assertTrue("Must find MyThread.doSomething in trace",
- trace.getClassName().endsWith("$MyThread") &&
- trace.getMethodName().equals("doSomething"));
-
- ThreadGroup g1 = new ThreadGroup("1");
- MyOtherThread t2 = new MyOtherThread(g1, "t2");
- t2.start();
- try {
- t2.join();
- } catch (InterruptedException ex) {
- }
-
- // Expect to see the traces of all threads (not just t2)
- assertTrue("Must have traces for all threads", t2.visibleTraces > 1);
- }
}
diff --git a/tests/CoreTests/android/core/RegexTest.java b/tests/CoreTests/android/core/RegexTest.java
deleted file mode 100644
index 743afc1..0000000
--- a/tests/CoreTests/android/core/RegexTest.java
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * 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 android.core;
-
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.TestCase;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Tests basic functionality of Pattern and Matcher classes.
- */
-public class RegexTest extends TestCase {
-
- @SmallTest
- public void testMatches() throws Exception {
- /* Tests class Matcher */
-
- Pattern p = Pattern.compile("bcd");
- Matcher m = p.matcher("bcd");
- assertTrue("Should match.", m.matches());
-
- /* Pattern in the middle */
- p = Pattern.compile("bcd");
- m = p.matcher("abcdefg");
- assertFalse("Should not match.", m.matches());
-
- /* Pattern at the head */
- m = p.matcher("bcdefg");
- assertFalse("Should not match.", m.matches());
-
- /* Pattern at the tail */
- m = p.matcher("abcd");
- assertFalse("Should not match.", m.matches());
-
- /* Make sure matches() doesn't change after calls to find() */
- p = Pattern.compile(".*");
- m = p.matcher("abc");
- assertTrue(m.matches());
- assertTrue(m.find());
- assertTrue(m.matches());
-
- p = Pattern.compile(".");
- m = p.matcher("abc");
- assertFalse(m.matches());
- assertTrue(m.find());
- assertFalse(m.matches());
-
- /* Make sure matches() agrees after a reset() */
- m.reset("z");
- assertTrue(m.matches());
-
- m.reset("xyz");
- assertFalse(m.matches());
-
- /* Tests class Pattern */
-
- assertFalse("Erroneously matched partial string. " +
- "See http://b/issue?id=754601", Pattern.matches("er", "xer"));
- assertFalse("Erroneously matched partial string. " +
- "See http://b/issue?id=754601", Pattern.matches("xe", "xer"));
- assertTrue("Generic regex should match.",
- Pattern.matches(".*", "bcd"));
- assertTrue("Grouped regex should match.",
- Pattern.matches("(b(c(d)))", "bcd"));
- assertTrue("Grouped regex should match.",
- Pattern.matches("(b)(c)(d)", "bcd"));
- }
-
- @SmallTest
- public void testGroupCount() throws Exception {
- Pattern p = Pattern.compile(
- "\\b(?:\\+?1)?"
- + "(?:[ -\\.])?"
- + "\\(?(\\d{3})?\\)?"
- + "(?:[ -\\.\\/])?"
- + "(\\d{3})"
- + "(?:[ -\\.])?"
- + "(\\d{4})\\b"
- );
-
- Matcher m = p.matcher("1 (919) 555-1212");
-
- assertEquals("groupCount is incorrect, see http://b/issue?id=759412",
- 3, m.groupCount());
- }
-
- @SmallTest
- public void testGroups() throws Exception {
- Pattern p = Pattern.compile("(b)([c|d])(z*)");
- Matcher m = p.matcher("abcdefg");
-
- /* Must call find() first, otherwise group*() are undefined. */
- assertTrue(m.find());
-
- assertEquals(3, m.groupCount());
-
- assertEquals("bc", m.group(0));
- assertEquals("b", m.group(1));
- assertEquals("c", m.group(2));
- assertEquals("", m.group(3));
- }
-
- @SmallTest
- public void testFind() throws Exception {
- Pattern p = Pattern.compile(".");
- Matcher m = p.matcher("abc");
-
- assertTrue(m.find());
- assertEquals("a", m.group(0));
-
- assertTrue(m.find());
- assertEquals("b", m.group(0));
-
- assertTrue(m.find());
- assertEquals("c", m.group(0));
-
- assertFalse(m.find());
- }
-
- @SmallTest
- public void testReplaceAll() throws Exception {
- // Begins with non-matching text, ends with matching text
- Pattern p = Pattern.compile("a*b");
- Matcher m = p.matcher("fooaabfooaabfooabfoob");
-
- String r = m.replaceAll("-");
- assertEquals("foo-foo-foo-foo-", r);
-
- // Begins with matching text, ends with non-matching text
- p = Pattern.compile("a*b");
- m = p.matcher("aabfooaabfooabfoobfoo");
-
- r = m.replaceAll("-");
- assertEquals("-foo-foo-foo-foo", r);
- }
-
- @SmallTest
- public void testReplaceFirst() throws Exception {
- // Begins with non-matching text, ends with matching text
- Pattern p = Pattern.compile("a*b");
- Matcher m = p.matcher("fooaabfooaabfooabfoob");
-
- String r = m.replaceFirst("-");
- assertEquals("foo-fooaabfooabfoob", r);
-
- // Begins with matching text, ends with non-matching text
- p = Pattern.compile("a*b");
- m = p.matcher("aabfooaabfooabfoobfoo");
-
- r = m.replaceFirst("-");
- assertEquals("-fooaabfooabfoobfoo", r);
- }
-
- @SmallTest
- public void testSplit() throws Exception {
- Pattern p = Pattern.compile(":");
- String[] strings;
-
- strings = p.split("boo:and:foo");
- assertEquals(3, strings.length);
- assertEquals("boo", strings[0]);
- assertEquals("and", strings[1]);
- assertEquals("foo", strings[2]);
-
- strings = p.split("boo:and:foo", 2);
- assertEquals(2, strings.length);
- assertEquals("boo", strings[0]);
- assertEquals("and:foo", strings[1]);
-
- strings = p.split("boo:and:foo", 5);
- assertEquals(3, strings.length);
- assertEquals("boo", strings[0]);
- assertEquals("and", strings[1]);
- assertEquals("foo", strings[2]);
-
- strings = p.split("boo:and:foo", -2);
- assertEquals(3, strings.length);
- assertEquals("boo", strings[0]);
- assertEquals("and", strings[1]);
- assertEquals("foo", strings[2]);
-
- p = Pattern.compile("o");
-
- strings = p.split("boo:and:foo");
- assertEquals(3, strings.length);
- assertEquals("b", strings[0]);
- assertEquals("", strings[1]);
- assertEquals(":and:f", strings[2]);
-
- strings = p.split("boo:and:foo", 5);
- assertEquals(5, strings.length);
- assertEquals("b", strings[0]);
- assertEquals("", strings[1]);
- assertEquals(":and:f", strings[2]);
- assertEquals("", strings[3]);
- assertEquals("", strings[4]);
-
- strings = p.split("boo:and:foo", -2);
- assertEquals(5, strings.length);
- assertEquals("b", strings[0]);
- assertEquals("", strings[1]);
- assertEquals(":and:f", strings[2]);
- assertEquals("", strings[3]);
- assertEquals("", strings[4]);
-
- strings = p.split("boo:and:foo", 0);
- assertEquals(3, strings.length);
- assertEquals("b", strings[0]);
- assertEquals("", strings[1]);
- assertEquals(":and:f", strings[2]);
- }
-
- // -------------------------------------------------------------------
- // Regression test for #1172774: Bug in Regex.java
- // Regression test for #1216887: Regular expression match is very slow
- public static final Pattern TOP_LEVEL_DOMAIN_PATTERN = Pattern.compile(
- "((aero|arpa|asia|a[cdefgilmnoqrstuwxz])"
- + "|(biz|b[abdefghijmnorstvwyz])"
- + "|(cat|com|coop|c[acdfghiklmnoruvxyz])"
- + "|d[ejkmoz]"
- + "|(edu|e[cegrstu])"
- + "|f[ijkmor]"
- + "|(gov|g[abdefghilmnpqrstuwy])"
- + "|h[kmnrtu]"
- + "|(info|int|i[delmnoqrst])"
- + "|(jobs|j[emop])"
- + "|k[eghimnrwyz]"
- + "|l[abcikrstuvy]"
- + "|(mil|mobi|museum|m[acdghklmnopqrstuvwxyz])"
- + "|(name|net|n[acefgilopruz])"
- + "|(org|om)"
- + "|(pro|p[aefghklmnrstwy])"
- + "|qa"
- + "|r[eouw]"
- + "|s[abcdeghijklmnortuvyz]"
- + "|(tel|travel|t[cdfghjklmnoprtvwz])"
- + "|u[agkmsyz]"
- + "|v[aceginu]"
- + "|w[fs]"
- + "|y[etu]"
- + "|z[amw])");
-
- public static final Pattern EMAIL_ADDRESS_PATTERN = Pattern.compile(
- "[\\+a-zA-Z0-9\\.\\_\\%\\-]+\\@"
- + "(("
- + "[a-zA-Z0-9]\\.|"
- + "([a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9]\\.)+)"
- + TOP_LEVEL_DOMAIN_PATTERN
- + ")");
-
- @SmallTest
- public void testMonsterRegexCorrectness() {
- assertTrue(EMAIL_ADDRESS_PATTERN.matcher("a+b@gmail.com").matches());
- }
-
- @SmallTest
- public void testMonsterRegexPerformance() {
- android.util.Log.e("RegexTest", "RegEx performance test started.");
- long t0 = System.currentTimeMillis();
- Matcher m = EMAIL_ADDRESS_PATTERN.matcher("donot repeate@RC8jjjjjjjjjjjjjjj");
- assertFalse(m.find());
- long t1 = System.currentTimeMillis();
- android.util.Log.e("RegexTest", "RegEx performance test finished, " +
- "took " + (t1 - t0) + " ms.");
- }
-
- //
- // -------------------------------------------------------------------
-
-}
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java
index 5e2a9fd..b7d2c26 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java
@@ -141,7 +141,7 @@ public class FsUtils {
} else if (!path.startsWith(HTTP_LOCAL_TESTS_PREFIX)
&& !path.startsWith(HTTP_MEDIA_TESTS_PREFIX)
&& !path.startsWith(HTTP_WML_TESTS_PREFIX)) {
- url = "http://127.0.0.1:18000/" + path.substring(HTTP_TESTS_PREFIX.length());
+ url = "http://127.0.0.1:8000/" + path.substring(HTTP_TESTS_PREFIX.length());
} else {
url = "file://" + path;
}
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardService.java b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardService.java
index 7a277d7..25dd04fd 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardService.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardService.java
@@ -26,7 +26,7 @@ import android.util.Log;
public class ForwardService {
- private ForwardServer fs18000, fs8080, fs8443;
+ private ForwardServer fs8000, fs8080, fs8443;
private static ForwardService inst;
@@ -40,7 +40,7 @@ public class ForwardService {
private ForwardService() {
int addr = getForwardHostAddr();
if (addr != -1) {
- fs18000 = new ForwardServer(18000, addr, 8000);
+ fs8000 = new ForwardServer(8000, addr, 8000);
fs8080 = new ForwardServer(8080, addr, 8080);
fs8443 = new ForwardServer(8443, addr, 8443);
}
@@ -55,8 +55,8 @@ public class ForwardService {
public void startForwardService() {
try {
- if (fs18000 != null)
- fs18000.start();
+ if (fs8000 != null)
+ fs8000.start();
if (fs8080 != null)
fs8080.start();
if (fs8443 != null)
@@ -68,9 +68,9 @@ public class ForwardService {
}
public void stopForwardService() {
- if (fs18000 != null) {
- fs18000.stop();
- fs18000 = null;
+ if (fs8000 != null) {
+ fs8000.stop();
+ fs8000 = null;
}
if (fs8080 != null) {
fs8080.stop();
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 929b103..643cb8d 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -30,6 +30,17 @@
android:label="HwUi"
android:hardwareAccelerated="true">
+ <meta-data android:name="android.graphics.renderThread" android:value="true" />
+
+ <activity
+ android:name="PaintDrawFilterActivity"
+ android:label="_DrawFilter">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
<activity
android:name="DisplayListLayersActivity"
android:label="__DisplayListLayers">
@@ -38,6 +49,15 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
+
+ <activity
+ android:name="MatrixActivity"
+ android:label="_Matrix">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
<activity
android:name="TextFadeActivity"
@@ -466,6 +486,16 @@
</activity>
<activity
+ android:name="PosTextActivity"
+ android:label="_PosText"
+ android:theme="@android:style/Theme.NoTitleBar">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <activity
android:name="ListActivity"
android:label="__List">
<intent-filter>
diff --git a/tests/HwAccelerationTest/res/values/strings.xml b/tests/HwAccelerationTest/res/values/strings.xml
new file mode 100644
index 0000000..69e58aa
--- /dev/null
+++ b/tests/HwAccelerationTest/res/values/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+ <string name="complex_string">"ตำแหน่งของตัวชี้"</string>
+</resources>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MatrixActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/MatrixActivity.java
new file mode 100644
index 0000000..1906b9d
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/MatrixActivity.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class MatrixActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(new MatrixView(this));
+ }
+
+ static class MatrixView extends View {
+ MatrixView(Context c) {
+ super(c);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ canvas.drawRGB(255, 255, 255);
+
+ Log.d("Matrix", "m1=" + canvas.getMatrix());
+
+ canvas.save();
+ canvas.translate(10.0f, 10.0f);
+ Log.d("Matrix", "m2=" + canvas.getMatrix());
+ canvas.translate(20.0f, 20.0f);
+ Log.d("Matrix", "m3=" + canvas.getMatrix());
+ canvas.restore();
+ }
+ }
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PaintDrawFilterActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/PaintDrawFilterActivity.java
new file mode 100644
index 0000000..8523272
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/PaintDrawFilterActivity.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PaintFlagsDrawFilter;
+import android.os.Bundle;
+import android.view.View;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class PaintDrawFilterActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(new CustomTextView(this));
+ }
+
+ static class CustomTextView extends View {
+ private final Paint mMediumPaint;
+ private final PaintFlagsDrawFilter mDrawFilter;
+
+ CustomTextView(Context c) {
+ super(c);
+
+ mMediumPaint = new Paint();
+ mMediumPaint.setAntiAlias(true);
+ mMediumPaint.setColor(0xff000000);
+ mMediumPaint.setFakeBoldText(true);
+ mMediumPaint.setTextSize(24.0f);
+
+ mDrawFilter = new PaintFlagsDrawFilter(
+ Paint.FAKE_BOLD_TEXT_FLAG, Paint.UNDERLINE_TEXT_FLAG);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ canvas.drawRGB(255, 255, 255);
+
+ canvas.setDrawFilter(null);
+ canvas.drawText("Hello OpenGL renderer!", 100, 120, mMediumPaint);
+ canvas.setDrawFilter(mDrawFilter);
+ canvas.drawText("Hello OpenGL renderer!", 100, 220, mMediumPaint);
+ }
+ }
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PosTextActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/PosTextActivity.java
new file mode 100644
index 0000000..1c868d2
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/PosTextActivity.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.os.Bundle;
+import android.view.View;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class PosTextActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(new CustomTextView(this));
+ }
+
+ static class CustomTextView extends View {
+ private final Paint mLargePaint;
+ private final String mText;
+ private final float[] mPos;
+
+ CustomTextView(Context c) {
+ super(c);
+
+ mText = c.getResources().getString(R.string.complex_string);
+ mPos = new float[mText.length() * 2];
+ for (int i = 0; i < mPos.length; i += 2) {
+ mPos[i] = i * 30.0f;
+ mPos[i + 1] = i * 10.0f;
+ }
+
+ mLargePaint = new Paint();
+ mLargePaint.setAntiAlias(true);
+ mLargePaint.setTextSize(36.0f);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ canvas.drawRGB(255, 255, 255);
+
+ canvas.save();
+
+ canvas.drawLine(100.0f, 0.0f, 100.0f, getHeight(), mLargePaint);
+
+ canvas.translate(100.0f, 100.0f);
+ mLargePaint.setTextAlign(Paint.Align.LEFT);
+ canvas.drawPosText(mText, mPos, mLargePaint);
+
+ canvas.translate(0.0f, 50.0f);
+ mLargePaint.setTextAlign(Paint.Align.CENTER);
+ canvas.drawPosText(mText, mPos, mLargePaint);
+
+ canvas.translate(0.0f, 50.0f);
+ mLargePaint.setTextAlign(Paint.Align.RIGHT);
+ canvas.drawPosText(mText, mPos, mLargePaint);
+
+ canvas.restore();
+ }
+ }
+}
diff --git a/tests/RenderScriptTests/ComputePerf/src/com/example/android/rs/computeperf/ComputePerf.java b/tests/RenderScriptTests/ComputePerf/src/com/example/android/rs/computeperf/ComputePerf.java
index f7abe8b..5446f66 100644
--- a/tests/RenderScriptTests/ComputePerf/src/com/example/android/rs/computeperf/ComputePerf.java
+++ b/tests/RenderScriptTests/ComputePerf/src/com/example/android/rs/computeperf/ComputePerf.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2011-2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,10 +22,10 @@ import android.graphics.BitmapFactory;
import android.graphics.Bitmap;
import android.renderscript.RenderScript;
import android.renderscript.Allocation;
+import android.util.Log;
import android.widget.ImageView;
public class ComputePerf extends Activity {
-
private LaunchTest mLT;
private Mandelbrot mMandel;
private RenderScript mRS;
@@ -35,14 +35,28 @@ public class ComputePerf extends Activity {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
+ final int numTries = 100;
+
+ long timesXLW = 0;
+ long timesXYW = 0;
+
mRS = RenderScript.create(this);
mLT = new LaunchTest(mRS, getResources());
- mLT.run();
- mLT.run();
+ mLT.XLW();
+ mLT.XYW();
+ for (int i = 0; i < numTries; i++) {
+ timesXLW += mLT.XLW();
+ timesXYW += mLT.XYW();
+ }
+
+ timesXLW /= numTries;
+ timesXYW /= numTries;
+
+ // XLW and XYW running times should match pretty closely
+ Log.v("ComputePerf", "xlw launch test " + timesXLW + "ms");
+ Log.v("ComputePerf", "xyw launch test " + timesXYW + "ms");
mMandel = new Mandelbrot(mRS, getResources());
mMandel.run();
-
}
-
}
diff --git a/tests/RenderScriptTests/ComputePerf/src/com/example/android/rs/computeperf/LaunchTest.java b/tests/RenderScriptTests/ComputePerf/src/com/example/android/rs/computeperf/LaunchTest.java
index 0c29ce1..e2312ba 100644
--- a/tests/RenderScriptTests/ComputePerf/src/com/example/android/rs/computeperf/LaunchTest.java
+++ b/tests/RenderScriptTests/ComputePerf/src/com/example/android/rs/computeperf/LaunchTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2011-2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@ package com.example.android.rs.computeperf;
import android.content.res.Resources;
import android.renderscript.*;
-public class LaunchTest implements Runnable {
+public class LaunchTest {
private RenderScript mRS;
private Allocation mAllocationX;
private Allocation mAllocationXY;
@@ -40,18 +40,19 @@ public class LaunchTest implements Runnable {
mScript_xlw.bind_buf(mAllocationXY);
}
- public void run() {
+ public long XLW() {
long t = java.lang.System.currentTimeMillis();
mScript_xlw.forEach_root(mAllocationX);
mRS.finish();
t = java.lang.System.currentTimeMillis() - t;
- android.util.Log.v("ComputePerf", "xlw launch test ms " + t);
+ return t;
+ }
- t = java.lang.System.currentTimeMillis();
+ public long XYW() {
+ long t = java.lang.System.currentTimeMillis();
mScript_xyw.forEach_root(mAllocationXY);
mRS.finish();
t = java.lang.System.currentTimeMillis() - t;
- android.util.Log.v("ComputePerf", "xyw launch test ms " + t);
+ return t;
}
-
}
diff --git a/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/simplemodel.rs b/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/simplemodel.rs
index 8cec409..de2a0a7 100644
--- a/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/simplemodel.rs
+++ b/tests/RenderScriptTests/ModelViewer/src/com/android/modelviewer/simplemodel.rs
@@ -48,6 +48,14 @@ static float gZoom;
static float gLastX;
static float gLastY;
+static float3 toFloat3(float x, float y, float z) {
+ float3 f;
+ f.x = x;
+ f.y = y;
+ f.z = z;
+ return f;
+}
+
void onActionDown(float x, float y) {
gLastX = x;
gLastY = y;
@@ -104,8 +112,8 @@ void updateMeshInfo() {
rsgMeshComputeBoundingBox(info->mMesh,
&minX, &minY, &minZ,
&maxX, &maxY, &maxZ);
- info->bBoxMin = (minX, minY, minZ);
- info->bBoxMax = (maxX, maxY, maxZ);
+ info->bBoxMin = toFloat3(minX, minY, minZ);
+ info->bBoxMax = toFloat3(maxX, maxY, maxZ);
gLookAt += (info->bBoxMin + info->bBoxMax)*0.5f;
}
gLookAt = gLookAt / (float)size;
diff --git a/tests/RenderScriptTests/PerfTest/res/menu/loader_menu.xml b/tests/RenderScriptTests/PerfTest/res/menu/loader_menu.xml
index 8234677..59a251d 100644
--- a/tests/RenderScriptTests/PerfTest/res/menu/loader_menu.xml
+++ b/tests/RenderScriptTests/PerfTest/res/menu/loader_menu.xml
@@ -18,8 +18,11 @@
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:id="@+id/benchmark_mode"
- android:title="@string/benchmark_mode" />
+ <item android:id="@+id/benchmark_all"
+ android:title="@string/benchmark_all" />
+ <item android:id="@+id/benchmark_one"
+ android:title="@string/benchmark_one" />
<item android:id="@+id/debug_mode"
android:title="@string/debug_mode" />
</menu>
+
diff --git a/tests/RenderScriptTests/PerfTest/res/raw/singletexf.glsl b/tests/RenderScriptTests/PerfTest/res/raw/singletexf.glsl
new file mode 100644
index 0000000..83dfc7f
--- /dev/null
+++ b/tests/RenderScriptTests/PerfTest/res/raw/singletexf.glsl
@@ -0,0 +1,8 @@
+varying vec2 varTex0;
+
+void main() {
+ lowp vec3 col0 = texture2D(UNI_Tex0, varTex0).rgb;
+ gl_FragColor.xyz = col0;
+ gl_FragColor.w = 0.5;
+}
+
diff --git a/tests/RenderScriptTests/PerfTest/res/values/strings.xml b/tests/RenderScriptTests/PerfTest/res/values/strings.xml
index 627ac21..ce9819e 100644
--- a/tests/RenderScriptTests/PerfTest/res/values/strings.xml
+++ b/tests/RenderScriptTests/PerfTest/res/values/strings.xml
@@ -19,6 +19,8 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<skip />
- <string name="benchmark_mode">Benchmark Mode</string>
+ <string name="benchmark_all">Benchmark All</string>
+ <string name="benchmark_one">Benchmark One</string>
<string name="debug_mode">Debug Mode</string>
</resources>
+
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/FillTest.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/FillTest.java
new file mode 100644
index 0000000..ba70c71
--- /dev/null
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/FillTest.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.perftest;
+
+import android.os.Environment;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+
+
+import android.util.Log;
+
+
+public class FillTest implements RsBenchBaseTest{
+
+ private static final String TAG = "FillTest";
+ private RenderScriptGL mRS;
+ private Resources mRes;
+
+ // Custom shaders
+ private ProgramFragment mProgFragmentMultitex;
+ private ProgramFragment mProgFragmentSingletex;
+ private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
+ int mBenchmarkDimX;
+ int mBenchmarkDimY;
+
+ private ScriptC_fill_test mFillScript;
+ ScriptField_TestScripts_s.Item[] mTests;
+
+ private final String[] mNames = {
+ "Fill screen 10x singletexture",
+ "Fill screen 10x 3tex multitexture",
+ "Fill screen 10x blended singletexture",
+ "Fill screen 10x blended 3tex multitexture"
+ };
+
+ public FillTest() {
+ mOptionsARGB.inScaled = false;
+ mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888;
+ mBenchmarkDimX = 1280;
+ mBenchmarkDimY = 720;
+ }
+
+ void addTest(int index, int testId, int blend, int quadCount) {
+ mTests[index] = new ScriptField_TestScripts_s.Item();
+ mTests[index].testScript = mFillScript;
+ mTests[index].testName = Allocation.createFromString(mRS,
+ mNames[index],
+ Allocation.USAGE_SCRIPT);
+ mTests[index].debugName = RsBenchRS.createZeroTerminatedAlloc(mRS,
+ mNames[index],
+ Allocation.USAGE_SCRIPT);
+
+ ScriptField_FillTestData_s.Item dataItem = new ScriptField_FillTestData_s.Item();
+ dataItem.testId = testId;
+ dataItem.blend = blend;
+ dataItem.quadCount = quadCount;
+ ScriptField_FillTestData_s testData = new ScriptField_FillTestData_s(mRS, 1);
+ testData.set(dataItem, 0, true);
+ mTests[index].testData = testData.getAllocation();
+ }
+
+ public boolean init(RenderScriptGL rs, Resources res) {
+ mRS = rs;
+ mRes = res;
+ initCustomShaders();
+ initFillScript();
+ mTests = new ScriptField_TestScripts_s.Item[mNames.length];
+
+ int index = 0;
+
+ addTest(index++, 1 /*testId*/, 0 /*blend*/, 10 /*quadCount*/);
+ addTest(index++, 0 /*testId*/, 0 /*blend*/, 10 /*quadCount*/);
+ addTest(index++, 1 /*testId*/, 1 /*blend*/, 10 /*quadCount*/);
+ addTest(index++, 0 /*testId*/, 1 /*blend*/, 10 /*quadCount*/);
+
+ return true;
+ }
+
+ public ScriptField_TestScripts_s.Item[] getTests() {
+ return mTests;
+ }
+
+ public String[] getTestNames() {
+ return mNames;
+ }
+
+ private void initCustomShaders() {
+ ProgramFragment.Builder pfbCustom = new ProgramFragment.Builder(mRS);
+ pfbCustom.setShader(mRes, R.raw.multitexf);
+ for (int texCount = 0; texCount < 3; texCount ++) {
+ pfbCustom.addTexture(Program.TextureType.TEXTURE_2D);
+ }
+ mProgFragmentMultitex = pfbCustom.create();
+
+ pfbCustom = new ProgramFragment.Builder(mRS);
+ pfbCustom.setShader(mRes, R.raw.singletexf);
+ pfbCustom.addTexture(Program.TextureType.TEXTURE_2D);
+ mProgFragmentSingletex = pfbCustom.create();
+ }
+
+ private Allocation loadTextureARGB(int id) {
+ Bitmap b = BitmapFactory.decodeResource(mRes, id, mOptionsARGB);
+ return Allocation.createFromBitmap(mRS, b,
+ Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
+ Allocation.USAGE_GRAPHICS_TEXTURE);
+ }
+
+ private Allocation loadTextureRGB(int id) {
+ return Allocation.createFromBitmapResource(mRS, mRes, id,
+ Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
+ Allocation.USAGE_GRAPHICS_TEXTURE);
+ }
+
+ void initFillScript() {
+ mFillScript = new ScriptC_fill_test(mRS, mRes, R.raw.fill_test);
+
+ ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
+ ProgramVertexFixedFunction progVertex = pvb.create();
+ ProgramVertexFixedFunction.Constants PVA = new ProgramVertexFixedFunction.Constants(mRS);
+ ((ProgramVertexFixedFunction)progVertex).bindConstants(PVA);
+ Matrix4f proj = new Matrix4f();
+ proj.loadOrthoWindow(mBenchmarkDimX, mBenchmarkDimY);
+ PVA.setProjection(proj);
+ mFillScript.set_gProgVertex(progVertex);
+
+ mFillScript.set_gProgFragmentTexture(mProgFragmentSingletex);
+ mFillScript.set_gProgFragmentMultitex(mProgFragmentMultitex);
+ mFillScript.set_gProgStoreBlendNone(ProgramStore.BLEND_NONE_DEPTH_NONE(mRS));
+ mFillScript.set_gProgStoreBlendAlpha(ProgramStore.BLEND_ALPHA_DEPTH_NONE(mRS));
+
+ mFillScript.set_gLinearClamp(Sampler.CLAMP_LINEAR(mRS));
+ mFillScript.set_gLinearWrap(Sampler.WRAP_LINEAR(mRS));
+ mFillScript.set_gTexTorus(loadTextureRGB(R.drawable.torusmap));
+ mFillScript.set_gTexOpaque(loadTextureRGB(R.drawable.data));
+ mFillScript.set_gTexTransparent(loadTextureARGB(R.drawable.leaf));
+ mFillScript.set_gTexChecker(loadTextureRGB(R.drawable.checker));
+ }
+}
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/MeshTest.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/MeshTest.java
new file mode 100644
index 0000000..cdb4435
--- /dev/null
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/MeshTest.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.perftest;
+
+import android.os.Environment;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.renderscript.*;
+import android.renderscript.Element.DataKind;
+import android.renderscript.Element.DataType;
+import android.renderscript.Allocation.MipmapControl;
+import android.renderscript.Program.TextureType;
+import android.renderscript.RenderScript.RSMessageHandler;
+import android.renderscript.Mesh.Primitive;
+import android.renderscript.Matrix4f;
+import android.renderscript.ProgramVertexFixedFunction;
+
+import android.util.Log;
+
+
+public class MeshTest implements RsBenchBaseTest{
+
+ private static final String TAG = "MeshTest";
+ private RenderScriptGL mRS;
+ private Resources mRes;
+
+ int mBenchmarkDimX;
+ int mBenchmarkDimY;
+
+ private Mesh m10by10Mesh;
+ private Mesh m100by100Mesh;
+ private Mesh mWbyHMesh;
+
+ private ScriptC_mesh_test mGeoScript;
+
+ private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
+
+ ScriptField_TestScripts_s.Item[] mTests;
+
+ private final String[] mNames = {
+ "Full screen mesh 10 by 10",
+ "Full screen mesh 100 by 100",
+ "Full screen mesh W / 4 by H / 4"
+ };
+
+ public MeshTest() {
+ mBenchmarkDimX = 1280;
+ mBenchmarkDimY = 720;
+ }
+
+ void addTest(int index, int meshNum) {
+ mTests[index] = new ScriptField_TestScripts_s.Item();
+ mTests[index].testScript = mGeoScript;
+ mTests[index].testName = Allocation.createFromString(mRS,
+ mNames[index],
+ Allocation.USAGE_SCRIPT);
+ mTests[index].debugName = RsBenchRS.createZeroTerminatedAlloc(mRS,
+ mNames[index],
+ Allocation.USAGE_SCRIPT);
+
+ ScriptField_MeshTestData_s.Item dataItem = new ScriptField_MeshTestData_s.Item();
+ dataItem.meshNum = meshNum;
+ ScriptField_MeshTestData_s testData = new ScriptField_MeshTestData_s(mRS, 1);
+ testData.set(dataItem, 0, true);
+ mTests[index].testData = testData.getAllocation();
+ }
+
+ public boolean init(RenderScriptGL rs, Resources res) {
+ mRS = rs;
+ mRes = res;
+ initGeoScript();
+ mTests = new ScriptField_TestScripts_s.Item[mNames.length];
+
+ int index = 0;
+ addTest(index++, 0 /*meshNum*/);
+ addTest(index++, 1 /*meshNum*/);
+ addTest(index++, 2 /*meshNum*/);
+
+ return true;
+ }
+
+ public ScriptField_TestScripts_s.Item[] getTests() {
+ return mTests;
+ }
+
+ public String[] getTestNames() {
+ return mNames;
+ }
+
+ private Mesh getMbyNMesh(float width, float height, int wResolution, int hResolution) {
+
+ Mesh.TriangleMeshBuilder tmb = new Mesh.TriangleMeshBuilder(mRS,
+ 2, Mesh.TriangleMeshBuilder.TEXTURE_0);
+
+ for (int y = 0; y <= hResolution; y++) {
+ final float normalizedY = (float)y / hResolution;
+ final float yOffset = (normalizedY - 0.5f) * height;
+ for (int x = 0; x <= wResolution; x++) {
+ float normalizedX = (float)x / wResolution;
+ float xOffset = (normalizedX - 0.5f) * width;
+ tmb.setTexture((float)x % 2, (float)y % 2);
+ tmb.addVertex(xOffset, yOffset);
+ }
+ }
+
+ for (int y = 0; y < hResolution; y++) {
+ final int curY = y * (wResolution + 1);
+ final int belowY = (y + 1) * (wResolution + 1);
+ for (int x = 0; x < wResolution; x++) {
+ int curV = curY + x;
+ int belowV = belowY + x;
+ tmb.addTriangle(curV, belowV, curV + 1);
+ tmb.addTriangle(belowV, belowV + 1, curV + 1);
+ }
+ }
+
+ return tmb.create(true);
+ }
+
+ private Allocation loadTextureRGB(int id) {
+ return Allocation.createFromBitmapResource(mRS, mRes, id,
+ Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
+ Allocation.USAGE_GRAPHICS_TEXTURE);
+ }
+
+ void initGeoScript() {
+ mGeoScript = new ScriptC_mesh_test(mRS, mRes, R.raw.mesh_test);
+
+ ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
+ ProgramVertexFixedFunction progVertex = pvb.create();
+ ProgramVertexFixedFunction.Constants PVA = new ProgramVertexFixedFunction.Constants(mRS);
+ ((ProgramVertexFixedFunction)progVertex).bindConstants(PVA);
+ Matrix4f proj = new Matrix4f();
+ proj.loadOrthoWindow(mBenchmarkDimX, mBenchmarkDimY);
+ PVA.setProjection(proj);
+
+ mGeoScript.set_gProgVertex(progVertex);
+ ProgramFragmentFixedFunction.Builder texBuilder = new ProgramFragmentFixedFunction.Builder(mRS);
+ texBuilder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
+ ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
+ mGeoScript.set_gProgFragmentTexture(texBuilder.create());
+ mGeoScript.set_gProgStoreBlendNone(ProgramStore.BLEND_NONE_DEPTH_NONE(mRS));
+
+ mGeoScript.set_gLinearClamp(Sampler.CLAMP_LINEAR(mRS));
+ mGeoScript.set_gTexOpaque(loadTextureRGB(R.drawable.data));
+
+ m10by10Mesh = getMbyNMesh(mBenchmarkDimX, mBenchmarkDimY, 10, 10);
+ m100by100Mesh = getMbyNMesh(mBenchmarkDimX, mBenchmarkDimY, 100, 100);
+ mWbyHMesh= getMbyNMesh(mBenchmarkDimX, mBenchmarkDimY, mBenchmarkDimX/4, mBenchmarkDimY/4);
+
+ mGeoScript.set_g10by10Mesh(m10by10Mesh);
+ mGeoScript.set_g100by100Mesh(m100by100Mesh);
+ mGeoScript.set_gWbyHMesh(mWbyHMesh);
+ }
+}
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBench.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBench.java
index b336a4d..0dceafe 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBench.java
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBench.java
@@ -93,22 +93,41 @@ public class RsBench extends Activity {
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
- case R.id.benchmark_mode:
- mView.setBenchmarkMode();
+ case R.id.benchmark_all:
+ mView.setBenchmarkMode(-1);
+ mView.suspendRendering(false);
return true;
- case R.id.debug_mode:
+ case R.id.benchmark_one:
+ mView.suspendRendering(true);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Pick a Test");
builder.setItems(mView.getTestNames(),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
Toast.makeText(getApplicationContext(),
+ "Starting to benchmark: " + mView.getTestNames()[item],
+ Toast.LENGTH_SHORT).show();
+ mView.setBenchmarkMode(item);
+ mView.suspendRendering(false);
+ }
+ });
+ builder.show();
+ return true;
+ case R.id.debug_mode:
+ mView.suspendRendering(true);
+ AlertDialog.Builder debugBuilder = new AlertDialog.Builder(this);
+ debugBuilder.setTitle("Pick a Test");
+ debugBuilder.setItems(mView.getTestNames(),
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int item) {
+ Toast.makeText(getApplicationContext(),
"Switching to: " + mView.getTestNames()[item],
Toast.LENGTH_SHORT).show();
mView.setDebugMode(item);
+ mView.suspendRendering(false);
}
});
- builder.show();
+ debugBuilder.show();
return true;
default:
return super.onOptionsItemSelected(item);
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchBaseTest.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchBaseTest.java
new file mode 100644
index 0000000..a9e1777
--- /dev/null
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchBaseTest.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.perftest;
+import android.renderscript.*;
+import android.content.res.Resources;
+
+interface RsBenchBaseTest {
+ boolean init(RenderScriptGL rs, Resources res);
+
+ ScriptField_TestScripts_s.Item[] getTests();
+ String[] getTestNames();
+}
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java
index c375be5..4ac7dd5 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchRS.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2010-2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,16 +26,11 @@ import java.io.OutputStream;
import android.os.Environment;
import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
import android.renderscript.*;
import android.renderscript.Element.DataKind;
import android.renderscript.Element.DataType;
import android.renderscript.Allocation.MipmapControl;
import android.renderscript.Program.TextureType;
-import android.renderscript.ProgramStore.DepthFunc;
-import android.renderscript.ProgramStore.BlendSrcFunc;
-import android.renderscript.ProgramStore.BlendDstFunc;
import android.renderscript.RenderScript.RSMessageHandler;
import android.renderscript.Sampler.Value;
import android.renderscript.Mesh.Primitive;
@@ -48,10 +43,6 @@ import android.util.Log;
public class RsBenchRS {
private static final String TAG = "RsBenchRS";
- private static final String SAMPLE_TEXT = "Bench Test";
- private static final String LIST_TEXT =
- "This is a sample list of text to show in the list view";
- private static int PARTICLES_COUNT = 12000;
int mWidth;
int mHeight;
int mLoops;
@@ -68,10 +59,7 @@ public class RsBenchRS {
mRes = res;
mWidth = width;
mHeight = height;
- mOptionsARGB.inScaled = false;
- mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888;
mMode = 0;
- mMaxModes = 0;
mLoops = loops;
mCurrentLoop = 0;
mBenchmarkDimX = 1280;
@@ -84,10 +72,8 @@ public class RsBenchRS {
private Resources mRes;
private RenderScriptGL mRS;
- private ProgramStore mProgStoreBlendNoneDepth;
private ProgramStore mProgStoreBlendNone;
private ProgramStore mProgStoreBlendAlpha;
- private ProgramStore mProgStoreBlendAdd;
private ProgramFragment mProgFragmentTexture;
private ProgramFragment mProgFragmentColor;
@@ -96,58 +82,69 @@ public class RsBenchRS {
private ProgramVertexFixedFunction.Constants mPVA;
private ProgramVertexFixedFunction.Constants mPvProjectionAlloc;
- // Custom shaders
- private ProgramVertex mProgVertexCustom;
- private ProgramFragment mProgFragmentCustom;
- private ProgramFragment mProgFragmentMultitex;
- private ProgramVertex mProgVertexPixelLight;
- private ProgramVertex mProgVertexPixelLightMove;
- private ProgramFragment mProgFragmentPixelLight;
- private ScriptField_VertexShaderConstants_s mVSConst;
- private ScriptField_FragentShaderConstants_s mFSConst;
- private ScriptField_VertexShaderConstants3_s mVSConstPixel;
- private ScriptField_FragentShaderConstants3_s mFSConstPixel;
-
-
- private Allocation mTexTorus;
- private Allocation mTexOpaque;
- private Allocation mTexTransparent;
- private Allocation mTexChecker;
- private Allocation mTexGlobe;
-
- private Mesh m10by10Mesh;
- private Mesh m100by100Mesh;
- private Mesh mWbyHMesh;
- private Mesh mTorus;
- private Mesh mSingleMesh;
- private Mesh mParticlesMesh;
-
- Font mFontSans;
- Font mFontSerif;
- private Allocation mTextAlloc;
-
- private ScriptField_ListAllocs_s mTextureAllocs;
- private ScriptField_ListAllocs_s mSampleTextAllocs;
- private ScriptField_ListAllocs_s mSampleListViewAllocs;
- private ScriptField_VpConsts mPvStarAlloc;
-
-
private ScriptC_rsbench mScript;
- private ScriptC_text_test mTextScript;
- private ScriptC_torus_test mTorusScript;
- private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
+ ScriptField_TestScripts_s.Item[] mIndividualTests;
int mMode;
- int mMaxModes;
String[] mTestNames;
float[] mLocalTestResults;
- public void onActionDown(int x, int y) {
- mMode ++;
- mMode = mMode % mMaxModes;
- mScript.set_gDisplayMode(mMode);
+ static Allocation createZeroTerminatedAlloc(RenderScript rs,
+ String str,
+ int usage) {
+ byte[] allocArray = null;
+ try {
+ allocArray = str.getBytes("UTF-8");
+ byte[] allocArrayZero = new byte[allocArray.length + 1];
+ System.arraycopy(allocArray, 0, allocArrayZero, 0, allocArray.length);
+ allocArrayZero[allocArrayZero.length - 1] = '\0';
+ Allocation alloc = Allocation.createSized(rs, Element.U8(rs),
+ allocArrayZero.length, usage);
+ alloc.copyFrom(allocArrayZero);
+ return alloc;
+ }
+ catch (Exception e) {
+ throw new RSRuntimeException("Could not convert string to utf-8.");
+ }
+
+ }
+
+ void appendTests(RsBenchBaseTest testSet) {
+ ScriptField_TestScripts_s.Item[] newTests = testSet.getTests();
+ if (mIndividualTests != null) {
+ ScriptField_TestScripts_s.Item[] combined;
+ combined = new ScriptField_TestScripts_s.Item[newTests.length + mIndividualTests.length];
+ System.arraycopy(mIndividualTests, 0, combined, 0, mIndividualTests.length);
+ System.arraycopy(newTests, 0, combined, mIndividualTests.length, newTests.length);
+ mIndividualTests = combined;
+ } else {
+ mIndividualTests = newTests;
+ }
+
+ String[] newNames = testSet.getTestNames();
+ if (mTestNames != null) {
+ String[] combinedNames;
+ combinedNames = new String[newNames.length + mTestNames.length];
+ System.arraycopy(mTestNames, 0, combinedNames, 0, mTestNames.length);
+ System.arraycopy(newNames, 0, combinedNames, mTestNames.length, newNames.length);
+ mTestNames = combinedNames;
+ } else {
+ mTestNames = newNames;
+ }
+ }
+
+ void createTestAllocation() {
+ int numTests = mIndividualTests.length;
+ mLocalTestResults = new float[numTests];
+ ScriptField_TestScripts_s allTests;
+ allTests = new ScriptField_TestScripts_s(mRS, numTests);
+ for (int i = 0; i < numTests; i ++) {
+ allTests.set(mIndividualTests[i], i, false);
+ }
+ allTests.copyAll();
+ mScript.bind_gTestScripts(allTests);
}
private void saveTestResults() {
@@ -225,98 +222,6 @@ public class RsBenchRS {
}
}
- ProgramStore BLEND_ADD_DEPTH_NONE(RenderScript rs) {
- ProgramStore.Builder builder = new ProgramStore.Builder(rs);
- builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
- builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE);
- builder.setDitherEnabled(false);
- builder.setDepthMaskEnabled(false);
- return builder.create();
- }
-
- private Mesh getMbyNMesh(float width, float height, int wResolution, int hResolution) {
-
- Mesh.TriangleMeshBuilder tmb = new Mesh.TriangleMeshBuilder(mRS,
- 2, Mesh.TriangleMeshBuilder.TEXTURE_0);
-
- for (int y = 0; y <= hResolution; y++) {
- final float normalizedY = (float)y / hResolution;
- final float yOffset = (normalizedY - 0.5f) * height;
- for (int x = 0; x <= wResolution; x++) {
- float normalizedX = (float)x / wResolution;
- float xOffset = (normalizedX - 0.5f) * width;
- tmb.setTexture((float)x % 2, (float)y % 2);
- tmb.addVertex(xOffset, yOffset);
- }
- }
-
- for (int y = 0; y < hResolution; y++) {
- final int curY = y * (wResolution + 1);
- final int belowY = (y + 1) * (wResolution + 1);
- for (int x = 0; x < wResolution; x++) {
- int curV = curY + x;
- int belowV = belowY + x;
- tmb.addTriangle(curV, belowV, curV + 1);
- tmb.addTriangle(belowV, belowV + 1, curV + 1);
- }
- }
-
- return tmb.create(true);
- }
-
- /**
- * Create a mesh with a single quad for the given width and height.
- */
- private Mesh getSingleMesh(float width, float height) {
- Mesh.TriangleMeshBuilder tmb = new Mesh.TriangleMeshBuilder(mRS,
- 2, Mesh.TriangleMeshBuilder.TEXTURE_0);
- float xOffset = width/2;
- float yOffset = height/2;
- tmb.setTexture(0, 0);
- tmb.addVertex(-1.0f * xOffset, -1.0f * yOffset);
- tmb.setTexture(1, 0);
- tmb.addVertex(xOffset, -1.0f * yOffset);
- tmb.setTexture(1, 1);
- tmb.addVertex(xOffset, yOffset);
- tmb.setTexture(0, 1);
- tmb.addVertex(-1.0f * xOffset, yOffset);
- tmb.addTriangle(0, 3, 1);
- tmb.addTriangle(1, 3, 2);
- return tmb.create(true);
- }
-
- private void initProgramStore() {
- // Use stock the stock program store object
- mProgStoreBlendNoneDepth = ProgramStore.BLEND_NONE_DEPTH_TEST(mRS);
- mProgStoreBlendNone = ProgramStore.BLEND_NONE_DEPTH_NONE(mRS);
-
- // Create a custom program store
- ProgramStore.Builder builder = new ProgramStore.Builder(mRS);
- builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
- builder.setBlendFunc(ProgramStore.BlendSrcFunc.SRC_ALPHA,
- ProgramStore.BlendDstFunc.ONE_MINUS_SRC_ALPHA);
- builder.setDitherEnabled(false);
- builder.setDepthMaskEnabled(false);
- mProgStoreBlendAlpha = builder.create();
-
- mProgStoreBlendAdd = BLEND_ADD_DEPTH_NONE(mRS);
-
- mScript.set_gProgStoreBlendNoneDepth(mProgStoreBlendNoneDepth);
-
- mScript.set_gProgStoreBlendNone(mProgStoreBlendNone);
- mScript.set_gProgStoreBlendAlpha(mProgStoreBlendAlpha);
- mScript.set_gProgStoreBlendAdd(mProgStoreBlendAdd);
-
- // For GALAXY
- builder = new ProgramStore.Builder(mRS);
- builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ZERO);
- mRS.bindProgramStore(builder.create());
-
- builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE);
- mScript.set_gPSLights(builder.create());
-
- }
-
private void initProgramFragment() {
ProgramFragmentFixedFunction.Builder texBuilder = new ProgramFragmentFixedFunction.Builder(mRS);
@@ -329,64 +234,9 @@ public class RsBenchRS {
colBuilder.setVaryingColor(false);
mProgFragmentColor = colBuilder.create();
- mScript.set_gProgFragmentColor(mProgFragmentColor);
-
mScript.set_gProgFragmentTexture(mProgFragmentTexture);
-
-
-
- // For Galaxy live wallpaper drawing
- ProgramFragmentFixedFunction.Builder builder = new ProgramFragmentFixedFunction.Builder(mRS);
- builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
- ProgramFragmentFixedFunction.Builder.Format.RGB, 0);
- ProgramFragment pfb = builder.create();
- pfb.bindSampler(Sampler.WRAP_NEAREST(mRS), 0);
- mScript.set_gPFBackground(pfb);
-
- builder = new ProgramFragmentFixedFunction.Builder(mRS);
- builder.setPointSpriteTexCoordinateReplacement(true);
- builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.MODULATE,
- ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
- builder.setVaryingColor(true);
- ProgramFragment pfs = builder.create();
- pfs.bindSampler(Sampler.WRAP_LINEAR_MIP_LINEAR(mRS), 0);
- mScript.set_gPFStars(pfs);
-
}
- private Matrix4f getProjectionNormalized(int w, int h) {
- // range -1,1 in the narrow axis at z = 0.
- Matrix4f m1 = new Matrix4f();
- Matrix4f m2 = new Matrix4f();
-
- if(w > h) {
- float aspect = ((float)w) / h;
- m1.loadFrustum(-aspect,aspect, -1,1, 1,100);
- } else {
- float aspect = ((float)h) / w;
- m1.loadFrustum(-1,1, -aspect,aspect, 1,100);
- }
-
- m2.loadRotate(180, 0, 1, 0);
- m1.loadMultiply(m1, m2);
-
- m2.loadScale(-2, 2, 1);
- m1.loadMultiply(m1, m2);
-
- m2.loadTranslate(0, 0, 2);
- m1.loadMultiply(m1, m2);
- return m1;
- }
-
- private void updateProjectionMatrices() {
- Matrix4f projNorm = getProjectionNormalized(mBenchmarkDimX, mBenchmarkDimY);
- ScriptField_VpConsts.Item i = new ScriptField_VpConsts.Item();
- i.Proj = projNorm;
- i.MVP = projNorm;
- mPvStarAlloc.set(i, 0, true);
- mPvProjectionAlloc.setProjection(projNorm);
- }
-
private void initProgramVertex() {
ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
mProgVertex = pvb.create();
@@ -398,201 +248,6 @@ public class RsBenchRS {
mPVA.setProjection(proj);
mScript.set_gProgVertex(mProgVertex);
-
-
- // For galaxy live wallpaper
- mPvStarAlloc = new ScriptField_VpConsts(mRS, 1);
- mScript.bind_vpConstants(mPvStarAlloc);
- mPvProjectionAlloc = new ProgramVertexFixedFunction.Constants(mRS);
- updateProjectionMatrices();
-
- pvb = new ProgramVertexFixedFunction.Builder(mRS);
- ProgramVertex pvbp = pvb.create();
- ((ProgramVertexFixedFunction)pvbp).bindConstants(mPvProjectionAlloc);
- mScript.set_gPVBkProj(pvbp);
-
- ProgramVertex.Builder sb = new ProgramVertex.Builder(mRS);
- String t = "varying vec4 varColor;\n" +
- "varying vec2 varTex0;\n" +
- "void main() {\n" +
- " float dist = ATTRIB_position.y;\n" +
- " float angle = ATTRIB_position.x;\n" +
- " float x = dist * sin(angle);\n" +
- " float y = dist * cos(angle) * 0.892;\n" +
- " float p = dist * 5.5;\n" +
- " float s = cos(p);\n" +
- " float t = sin(p);\n" +
- " vec4 pos;\n" +
- " pos.x = t * x + s * y;\n" +
- " pos.y = s * x - t * y;\n" +
- " pos.z = ATTRIB_position.z;\n" +
- " pos.w = 1.0;\n" +
- " gl_Position = UNI_MVP * pos;\n" +
- " gl_PointSize = ATTRIB_color.a * 10.0;\n" +
- " varColor.rgb = ATTRIB_color.rgb;\n" +
- " varColor.a = 1.0;\n" +
- "}\n";
- sb.setShader(t);
- sb.addInput(mParticlesMesh.getVertexAllocation(0).getType().getElement());
- sb.addConstant(mPvStarAlloc.getType());
- ProgramVertex pvs = sb.create();
- pvs.bindConstants(mPvStarAlloc.getAllocation(), 0);
- mScript.set_gPVStars(pvs);
- }
-
- private void initCustomShaders() {
- mVSConst = new ScriptField_VertexShaderConstants_s(mRS, 1);
- mFSConst = new ScriptField_FragentShaderConstants_s(mRS, 1);
-
-
- mVSConstPixel = new ScriptField_VertexShaderConstants3_s(mRS, 1);
- mFSConstPixel = new ScriptField_FragentShaderConstants3_s(mRS, 1);
-
-
- // Initialize the shader builder
- ProgramVertex.Builder pvbCustom = new ProgramVertex.Builder(mRS);
- // Specify the resource that contains the shader string
- pvbCustom.setShader(mRes, R.raw.shaderv);
- // Use a script field to specify the input layout
- pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS));
- // Define the constant input layout
- pvbCustom.addConstant(mVSConst.getAllocation().getType());
- mProgVertexCustom = pvbCustom.create();
- // Bind the source of constant data
- mProgVertexCustom.bindConstants(mVSConst.getAllocation(), 0);
-
- ProgramFragment.Builder pfbCustom = new ProgramFragment.Builder(mRS);
- // Specify the resource that contains the shader string
- pfbCustom.setShader(mRes, R.raw.shaderf);
- // Tell the builder how many textures we have
- pfbCustom.addTexture(Program.TextureType.TEXTURE_2D);
- // Define the constant input layout
- pfbCustom.addConstant(mFSConst.getAllocation().getType());
- mProgFragmentCustom = pfbCustom.create();
- // Bind the source of constant data
- mProgFragmentCustom.bindConstants(mFSConst.getAllocation(), 0);
-
- pvbCustom = new ProgramVertex.Builder(mRS);
- pvbCustom.setShader(mRes, R.raw.shader2v);
- pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS));
- pvbCustom.addConstant(mVSConstPixel.getAllocation().getType());
- mProgVertexPixelLight = pvbCustom.create();
- mProgVertexPixelLight.bindConstants(mVSConstPixel.getAllocation(), 0);
-
- pvbCustom = new ProgramVertex.Builder(mRS);
- pvbCustom.setShader(mRes, R.raw.shader2movev);
- pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS));
- pvbCustom.addConstant(mVSConstPixel.getAllocation().getType());
- mProgVertexPixelLightMove = pvbCustom.create();
- mProgVertexPixelLightMove.bindConstants(mVSConstPixel.getAllocation(), 0);
-
- pfbCustom = new ProgramFragment.Builder(mRS);
- pfbCustom.setShader(mRes, R.raw.shader2f);
- pfbCustom.addTexture(Program.TextureType.TEXTURE_2D);
- pfbCustom.addConstant(mFSConstPixel.getAllocation().getType());
- mProgFragmentPixelLight = pfbCustom.create();
- mProgFragmentPixelLight.bindConstants(mFSConstPixel.getAllocation(), 0);
-
- pfbCustom = new ProgramFragment.Builder(mRS);
- pfbCustom.setShader(mRes, R.raw.multitexf);
- for (int texCount = 0; texCount < 3; texCount ++) {
- pfbCustom.addTexture(Program.TextureType.TEXTURE_2D);
- }
- mProgFragmentMultitex = pfbCustom.create();
-
-
- mScript.set_gProgFragmentMultitex(mProgFragmentMultitex);
- }
-
- private Allocation loadTextureRGB(int id) {
- return Allocation.createFromBitmapResource(mRS, mRes, id,
- Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
- Allocation.USAGE_GRAPHICS_TEXTURE);
- }
-
- private Allocation loadTextureARGB(int id) {
- Bitmap b = BitmapFactory.decodeResource(mRes, id, mOptionsARGB);
- return Allocation.createFromBitmap(mRS, b,
- Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
- Allocation.USAGE_GRAPHICS_TEXTURE);
- }
-
- private void loadImages() {
- mTexTorus = loadTextureRGB(R.drawable.torusmap);
- mTexOpaque = loadTextureRGB(R.drawable.data);
- mTexTransparent = loadTextureARGB(R.drawable.leaf);
- mTexChecker = loadTextureRGB(R.drawable.checker);
- mTexGlobe = loadTextureRGB(R.drawable.globe);
-
- mScript.set_gTexTorus(mTexTorus);
- mScript.set_gTexOpaque(mTexOpaque);
- mScript.set_gTexTransparent(mTexTransparent);
- mScript.set_gTexChecker(mTexChecker);
- mScript.set_gTexGlobe(mTexGlobe);
-
- // For Galaxy live wallpaper
- mScript.set_gTSpace(loadTextureRGB(R.drawable.space));
- mScript.set_gTLight1(loadTextureRGB(R.drawable.light1));
- mScript.set_gTFlares(loadTextureARGB(R.drawable.flares));
- }
-
- private void initFonts() {
- // Sans font by family name
- mFontSans = Font.create(mRS, mRes, "sans-serif", Font.Style.NORMAL, 8);
- mFontSerif = Font.create(mRS, mRes, "serif", Font.Style.NORMAL, 8);
- // Create fonts by family and style
-
- mTextAlloc = Allocation.createFromString(mRS, "String from allocation", Allocation.USAGE_SCRIPT);
-
- mScript.set_gFontSans(mFontSans);
- mScript.set_gFontSerif(mFontSerif);
- }
-
- private void createParticlesMesh() {
- ScriptField_Particle p = new ScriptField_Particle(mRS, PARTICLES_COUNT);
-
- final Mesh.AllocationBuilder meshBuilder = new Mesh.AllocationBuilder(mRS);
- meshBuilder.addVertexAllocation(p.getAllocation());
- final int vertexSlot = meshBuilder.getCurrentVertexTypeIndex();
- meshBuilder.addIndexSetType(Primitive.POINT);
- mParticlesMesh = meshBuilder.create();
-
- mScript.set_gParticlesMesh(mParticlesMesh);
- mScript.bind_Particles(p);
- }
-
- private void initMesh() {
- m10by10Mesh = getMbyNMesh(mBenchmarkDimX, mBenchmarkDimY, 10, 10);
- mScript.set_g10by10Mesh(m10by10Mesh);
- m100by100Mesh = getMbyNMesh(mBenchmarkDimX, mBenchmarkDimY, 100, 100);
- mScript.set_g100by100Mesh(m100by100Mesh);
- mWbyHMesh= getMbyNMesh(mBenchmarkDimX, mBenchmarkDimY, mBenchmarkDimX/4, mBenchmarkDimY/4);
- mScript.set_gWbyHMesh(mWbyHMesh);
- mSingleMesh = getSingleMesh(1, 1); // a unit size mesh
- mScript.set_gSingleMesh(mSingleMesh);
-
- FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.torus);
- FileA3D.IndexEntry entry = model.getIndexEntry(0);
- if (entry == null || entry.getEntryType() != FileA3D.EntryType.MESH) {
- Log.e("rs", "could not load model");
- } else {
- mTorus = (Mesh)entry.getObject();
- }
-
- createParticlesMesh();
- }
-
- private void initSamplers() {
- mScript.set_gLinearClamp(Sampler.CLAMP_LINEAR(mRS));
- mScript.set_gLinearWrap(Sampler.WRAP_LINEAR(mRS));
- mScript.set_gMipLinearWrap(Sampler.WRAP_LINEAR_MIP_LINEAR(mRS));
- mScript.set_gNearestClamp(Sampler.CLAMP_NEAREST(mRS));
- }
-
- private void initProgramRaster() {
- mScript.set_gCullBack(ProgramRaster.CULL_BACK(mRS));
- mScript.set_gCullFront(ProgramRaster.CULL_FRONT(mRS));
- mScript.set_gCullNone(ProgramRaster.CULL_NONE(mRS));
}
private int strlen(byte[] array) {
@@ -603,78 +258,30 @@ public class RsBenchRS {
return count;
}
- private void prepareTestData() {
- mTestNames = new String[mMaxModes];
- mLocalTestResults = new float[mMaxModes];
- int scratchSize = 1024;
- Allocation scratch = Allocation.createSized(mRS, Element.U8(mRS), scratchSize);
- byte[] tmp = new byte[scratchSize];
- mScript.bind_gStringBuffer(scratch);
- for (int i = 0; i < mMaxModes; i ++) {
- mScript.invoke_getTestName(i);
- scratch.copyTo(tmp);
- int len = strlen(tmp);
- mTestNames[i] = new String(tmp, 0, len);
- }
- }
-
public void setDebugMode(int num) {
mScript.invoke_setDebugMode(num);
}
- public void setBenchmarkMode() {
- mScript.invoke_setBenchmarkMode();
+ public void setBenchmarkMode(int benchNum) {
+ mScript.invoke_setBenchmarkMode(benchNum);
}
- void initTextScript() {
- mTextScript = new ScriptC_text_test(mRS, mRes, R.raw.text_test);
- mTextScript.set_gFontSans(mFontSans);
- mTextScript.set_gFontSerif(mFontSerif);
- }
-
- void initTorusScript() {
- mTorusScript = new ScriptC_torus_test(mRS, mRes, R.raw.torus_test);
- mTorusScript.set_gCullFront(ProgramRaster.CULL_FRONT(mRS));
- mTorusScript.set_gCullBack(ProgramRaster.CULL_BACK(mRS));
- mTorusScript.set_gLinearClamp(Sampler.CLAMP_LINEAR(mRS));
- mTorusScript.set_gTorusMesh(mTorus);
- mTorusScript.set_gTexTorus(mTexTorus);
- mTorusScript.set_gProgVertexCustom(mProgVertexCustom);
- mTorusScript.set_gProgFragmentCustom(mProgFragmentCustom);
- mTorusScript.set_gProgVertexPixelLight(mProgVertexPixelLight);
- mTorusScript.set_gProgVertexPixelLightMove(mProgVertexPixelLightMove);
- mTorusScript.set_gProgFragmentPixelLight(mProgFragmentPixelLight);
- mTorusScript.bind_gVSConstPixel(mVSConstPixel);
- mTorusScript.bind_gFSConstPixel(mFSConstPixel);
- mTorusScript.bind_gVSConstants(mVSConst);
- mTorusScript.bind_gFSConstants(mFSConst);
- mTorusScript.set_gProgVertex(mProgVertex);
- mTorusScript.set_gProgFragmentTexture(mProgFragmentTexture);
- mTorusScript.set_gProgFragmentColor(mProgFragmentColor);
- mTorusScript.set_gProgStoreBlendNoneDepth(mProgStoreBlendNoneDepth);
+ public void pause(boolean pause) {
+ mScript.set_gPauseRendering(pause);
}
private void initRS() {
mScript = new ScriptC_rsbench(mRS, mRes, R.raw.rsbench);
-
+ mRS.bindRootScript(mScript);
mRS.setMessageHandler(mRsMessage);
- mMaxModes = mScript.get_gMaxModes();
mScript.set_gMaxLoops(mLoops);
- prepareTestData();
-
- initSamplers();
- initMesh();
initProgramVertex();
- initProgramStore();
initProgramFragment();
- initFonts();
- loadImages();
- initProgramRaster();
- initCustomShaders();
+ mScript.set_gFontSerif(Font.create(mRS, mRes, "serif", Font.Style.NORMAL, 8));
Type.Builder b = new Type.Builder(mRS, Element.RGBA_8888(mRS));
b.setX(mBenchmarkDimX).setY(mBenchmarkDimY);
@@ -692,41 +299,30 @@ public class RsBenchRS {
b.create(),
Allocation.USAGE_GRAPHICS_RENDER_TARGET);
mScript.set_gRenderBufferDepth(offscreen);
+ mScript.set_gLinearClamp(Sampler.CLAMP_LINEAR(mRS));
- mTextureAllocs = new ScriptField_ListAllocs_s(mRS, 100);
- for (int i = 0; i < 100; i++) {
- ScriptField_ListAllocs_s.Item texElem = new ScriptField_ListAllocs_s.Item();
- texElem.item = loadTextureRGB(R.drawable.globe);
- mTextureAllocs.set(texElem, i, false);
+ RsBenchBaseTest test = new TextTest();
+ if (test.init(mRS, mRes)) {
+ appendTests(test);
}
- mTextureAllocs.copyAll();
- mScript.bind_gTexList100(mTextureAllocs);
-
- mSampleTextAllocs = new ScriptField_ListAllocs_s(mRS, 100);
- for (int i = 0; i < 100; i++) {
- ScriptField_ListAllocs_s.Item textElem = new ScriptField_ListAllocs_s.Item();
- textElem.item = Allocation.createFromString(mRS, SAMPLE_TEXT, Allocation.USAGE_SCRIPT);
- mSampleTextAllocs.set(textElem, i, false);
+ test = new FillTest();
+ if (test.init(mRS, mRes)) {
+ appendTests(test);
}
- mSampleTextAllocs.copyAll();
- mScript.bind_gSampleTextList100(mSampleTextAllocs);
-
- mSampleListViewAllocs = new ScriptField_ListAllocs_s(mRS, 1000);
- for (int i = 0; i < 1000; i++) {
- ScriptField_ListAllocs_s.Item textElem = new ScriptField_ListAllocs_s.Item();
- textElem.item = Allocation.createFromString(mRS, LIST_TEXT, Allocation.USAGE_SCRIPT);
- mSampleListViewAllocs.set(textElem, i, false);
+ test = new MeshTest();
+ if (test.init(mRS, mRes)) {
+ appendTests(test);
}
- mSampleListViewAllocs.copyAll();
- mScript.bind_gListViewText(mSampleListViewAllocs);
-
- initTextScript();
- initTorusScript();
-
- mScript.set_gFontScript(mTextScript);
- mScript.set_gTorusScript(mTorusScript);
- mScript.set_gDummyAlloc(Allocation.createSized(mRS, Element.I32(mRS), 1));
+ test = new TorusTest();
+ if (test.init(mRS, mRes)) {
+ appendTests(test);
+ }
+ test = new UiTest();
+ if (test.init(mRS, mRes)) {
+ appendTests(test);
+ }
+ createTestAllocation();
- mRS.bindRootScript(mScript);
+ mScript.set_gLoadComplete(true);
}
}
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchView.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchView.java
index 61aa3e1..124071e 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchView.java
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/RsBenchView.java
@@ -71,24 +71,6 @@ public class RsBenchView extends RSSurfaceView {
}
}
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- return super.onKeyDown(keyCode, event);
- }
-
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- boolean ret = false;
- int act = ev.getAction();
- if (act == ev.ACTION_DOWN) {
- mRender.onActionDown((int)ev.getX(), (int)ev.getY());
- ret = true;
- }
-
- return ret;
- }
-
/**
* Set the total number of loops the benchmark tests will run
* before the test results are collected.
@@ -106,8 +88,12 @@ public class RsBenchView extends RSSurfaceView {
return mRender.testIsFinished();
}
- void setBenchmarkMode() {
- mRender.setBenchmarkMode();
+ void setBenchmarkMode(int benchNum) {
+ mRender.setBenchmarkMode(benchNum);
+ }
+
+ void suspendRendering(boolean pause) {
+ mRender.pause(pause);
}
void setDebugMode(int num) {
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/TextTest.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/TextTest.java
new file mode 100644
index 0000000..3ca2792
--- /dev/null
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/TextTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.perftest;
+
+import android.os.Environment;
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.util.DisplayMetrics;
+
+import android.util.Log;
+
+
+public class TextTest implements RsBenchBaseTest{
+
+ private static final String TAG = "TextTest";
+ private RenderScriptGL mRS;
+ private Resources mRes;
+
+ private ScriptC_text_test mTextScript;
+ ScriptField_TestScripts_s.Item[] mTests;
+
+ private final String[] mNames = {
+ "Fill screen with text 1 time",
+ "Fill screen with text 3 times",
+ "Fill screen with text 5 times"
+ };
+
+ public TextTest() {
+ }
+
+ void addTest(int index, int fillNum) {
+ mTests[index] = new ScriptField_TestScripts_s.Item();
+ mTests[index].testScript = mTextScript;
+ mTests[index].testName = Allocation.createFromString(mRS,
+ mNames[index],
+ Allocation.USAGE_SCRIPT);
+ mTests[index].debugName = RsBenchRS.createZeroTerminatedAlloc(mRS,
+ mNames[index],
+ Allocation.USAGE_SCRIPT);
+
+ ScriptField_TextTestData_s.Item dataItem = new ScriptField_TextTestData_s.Item();
+ dataItem.fillNum = fillNum;
+ ScriptField_TextTestData_s testData = new ScriptField_TextTestData_s(mRS, 1);
+ testData.set(dataItem, 0, true);
+ mTests[index].testData = testData.getAllocation();
+ }
+
+ public boolean init(RenderScriptGL rs, Resources res) {
+ mRS = rs;
+ mRes = res;
+ initTextScript();
+ mTests = new ScriptField_TestScripts_s.Item[mNames.length];
+
+ int index = 0;
+ addTest(index++, 1 /*fillNum*/);
+ addTest(index++, 3 /*fillNum*/);
+ addTest(index++, 5 /*fillNum*/);
+
+ return true;
+ }
+
+ public ScriptField_TestScripts_s.Item[] getTests() {
+ return mTests;
+ }
+
+ public String[] getTestNames() {
+ return mNames;
+ }
+
+ void initTextScript() {
+ DisplayMetrics metrics = mRes.getDisplayMetrics();
+
+ mTextScript = new ScriptC_text_test(mRS, mRes, R.raw.text_test);
+ mTextScript.set_gFontSans(Font.create(mRS, mRes, "sans-serif",
+ Font.Style.NORMAL, 8.0f / metrics.density));
+ mTextScript.set_gFontSerif(Font.create(mRS, mRes, "serif",
+ Font.Style.NORMAL, 8.0f / metrics.density));
+ }
+}
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/TorusTest.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/TorusTest.java
new file mode 100644
index 0000000..5c9ecd5
--- /dev/null
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/TorusTest.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.perftest;
+
+import android.os.Environment;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.renderscript.*;
+import android.renderscript.Element.DataKind;
+import android.renderscript.Element.DataType;
+import android.renderscript.Allocation.MipmapControl;
+import android.renderscript.Program.TextureType;
+import android.renderscript.RenderScript.RSMessageHandler;
+import android.renderscript.Mesh.Primitive;
+import android.renderscript.Matrix4f;
+import android.renderscript.ProgramVertexFixedFunction;
+
+import android.util.Log;
+
+
+public class TorusTest implements RsBenchBaseTest{
+
+ private static final String TAG = "TorusTest";
+ private RenderScriptGL mRS;
+ private Resources mRes;
+
+ private ProgramStore mProgStoreBlendNoneDepth;
+ private ProgramStore mProgStoreBlendNone;
+ private ProgramStore mProgStoreBlendAlpha;
+
+ private ProgramFragment mProgFragmentTexture;
+ private ProgramFragment mProgFragmentColor;
+
+ private ProgramVertex mProgVertex;
+ private ProgramVertexFixedFunction.Constants mPVA;
+ private ProgramVertexFixedFunction.Constants mPvProjectionAlloc;
+
+ // Custom shaders
+ private ProgramVertex mProgVertexCustom;
+ private ProgramFragment mProgFragmentCustom;
+ private ProgramFragment mProgFragmentMultitex;
+ private ProgramVertex mProgVertexPixelLight;
+ private ProgramVertex mProgVertexPixelLightMove;
+ private ProgramFragment mProgFragmentPixelLight;
+ private ScriptField_VertexShaderConstants_s mVSConst;
+ private ScriptField_FragentShaderConstants_s mFSConst;
+ private ScriptField_VertexShaderConstants3_s mVSConstPixel;
+ private ScriptField_FragentShaderConstants3_s mFSConstPixel;
+
+ private Allocation mTexTorus;
+ private Mesh mTorus;
+
+ private ScriptC_torus_test mTorusScript;
+
+ private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
+
+ ScriptField_TestScripts_s.Item[] mTests;
+
+ private final String[] mNames = {
+ "Geo test 25.6k flat color",
+ "Geo test 51.2k flat color",
+ "Geo test 204.8k small tries flat color",
+ "Geo test 25.6k single texture",
+ "Geo test 51.2k single texture",
+ "Geo test 204.8k small tries single texture",
+ "Geo test 25.6k geo heavy vertex",
+ "Geo test 51.2k geo heavy vertex",
+ "Geo test 204.8k geo raster load heavy vertex",
+ "Geo test 25.6k heavy fragment",
+ "Geo test 51.2k heavy fragment",
+ "Geo test 204.8k small tries heavy fragment",
+ "Geo test 25.6k heavy fragment heavy vertex",
+ "Geo test 51.2k heavy fragment heavy vertex",
+ "Geo test 204.8k small tries heavy fragment heavy vertex"
+ };
+
+ public TorusTest() {
+ }
+
+ void addTest(int index, int testId, int user1, int user2) {
+ mTests[index] = new ScriptField_TestScripts_s.Item();
+ mTests[index].testScript = mTorusScript;
+ mTests[index].testName = Allocation.createFromString(mRS,
+ mNames[index],
+ Allocation.USAGE_SCRIPT);
+ mTests[index].debugName = RsBenchRS.createZeroTerminatedAlloc(mRS,
+ mNames[index],
+ Allocation.USAGE_SCRIPT);
+
+ ScriptField_TorusTestData_s.Item dataItem = new ScriptField_TorusTestData_s.Item();
+ dataItem.testId = testId;
+ dataItem.user1 = user1;
+ dataItem.user2 = user2;
+ ScriptField_TorusTestData_s testData = new ScriptField_TorusTestData_s(mRS, 1);
+ testData.set(dataItem, 0, true);
+ mTests[index].testData = testData.getAllocation();
+ }
+
+ public boolean init(RenderScriptGL rs, Resources res) {
+ mRS = rs;
+ mRes = res;
+ initCustomShaders();
+ loadImages();
+ initMesh();
+ initTorusScript();
+ mTests = new ScriptField_TestScripts_s.Item[mNames.length];
+
+ int index = 0;
+ addTest(index++, 0, 0 /*useTexture*/, 1 /*numMeshes*/);
+ addTest(index++, 0, 0 /*useTexture*/, 2 /*numMeshes*/);
+ addTest(index++, 0, 0 /*useTexture*/, 8 /*numMeshes*/);
+ addTest(index++, 0, 1 /*useTexture*/, 1 /*numMeshes*/);
+ addTest(index++, 0, 1 /*useTexture*/, 2 /*numMeshes*/);
+ addTest(index++, 0, 1 /*useTexture*/, 8 /*numMeshes*/);
+
+ // Secont test
+ addTest(index++, 1, 1 /*numMeshes*/, 0 /*unused*/);
+ addTest(index++, 1, 2 /*numMeshes*/, 0 /*unused*/);
+ addTest(index++, 1, 8 /*numMeshes*/, 0 /*unused*/);
+
+ // Third test
+ addTest(index++, 2, 1 /*numMeshes*/, 0 /*heavyVertex*/);
+ addTest(index++, 2, 2 /*numMeshes*/, 0 /*heavyVertex*/);
+ addTest(index++, 2, 8 /*numMeshes*/, 0 /*heavyVertex*/);
+ addTest(index++, 2, 1 /*numMeshes*/, 1 /*heavyVertex*/);
+ addTest(index++, 2, 2 /*numMeshes*/, 1 /*heavyVertex*/);
+ addTest(index++, 2, 8 /*numMeshes*/, 1 /*heavyVertex*/);
+
+ return true;
+ }
+
+ public ScriptField_TestScripts_s.Item[] getTests() {
+ return mTests;
+ }
+
+ public String[] getTestNames() {
+ return mNames;
+ }
+
+ private void initCustomShaders() {
+ mVSConst = new ScriptField_VertexShaderConstants_s(mRS, 1);
+ mFSConst = new ScriptField_FragentShaderConstants_s(mRS, 1);
+
+ mVSConstPixel = new ScriptField_VertexShaderConstants3_s(mRS, 1);
+ mFSConstPixel = new ScriptField_FragentShaderConstants3_s(mRS, 1);
+
+ // Initialize the shader builder
+ ProgramVertex.Builder pvbCustom = new ProgramVertex.Builder(mRS);
+ // Specify the resource that contains the shader string
+ pvbCustom.setShader(mRes, R.raw.shaderv);
+ // Use a script field to specify the input layout
+ pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS));
+ // Define the constant input layout
+ pvbCustom.addConstant(mVSConst.getAllocation().getType());
+ mProgVertexCustom = pvbCustom.create();
+ // Bind the source of constant data
+ mProgVertexCustom.bindConstants(mVSConst.getAllocation(), 0);
+
+ ProgramFragment.Builder pfbCustom = new ProgramFragment.Builder(mRS);
+ // Specify the resource that contains the shader string
+ pfbCustom.setShader(mRes, R.raw.shaderf);
+ // Tell the builder how many textures we have
+ pfbCustom.addTexture(Program.TextureType.TEXTURE_2D);
+ // Define the constant input layout
+ pfbCustom.addConstant(mFSConst.getAllocation().getType());
+ mProgFragmentCustom = pfbCustom.create();
+ // Bind the source of constant data
+ mProgFragmentCustom.bindConstants(mFSConst.getAllocation(), 0);
+
+ pvbCustom = new ProgramVertex.Builder(mRS);
+ pvbCustom.setShader(mRes, R.raw.shader2v);
+ pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS));
+ pvbCustom.addConstant(mVSConstPixel.getAllocation().getType());
+ mProgVertexPixelLight = pvbCustom.create();
+ mProgVertexPixelLight.bindConstants(mVSConstPixel.getAllocation(), 0);
+
+ pvbCustom = new ProgramVertex.Builder(mRS);
+ pvbCustom.setShader(mRes, R.raw.shader2movev);
+ pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS));
+ pvbCustom.addConstant(mVSConstPixel.getAllocation().getType());
+ mProgVertexPixelLightMove = pvbCustom.create();
+ mProgVertexPixelLightMove.bindConstants(mVSConstPixel.getAllocation(), 0);
+
+ pfbCustom = new ProgramFragment.Builder(mRS);
+ pfbCustom.setShader(mRes, R.raw.shader2f);
+ pfbCustom.addTexture(Program.TextureType.TEXTURE_2D);
+ pfbCustom.addConstant(mFSConstPixel.getAllocation().getType());
+ mProgFragmentPixelLight = pfbCustom.create();
+ mProgFragmentPixelLight.bindConstants(mFSConstPixel.getAllocation(), 0);
+
+ pfbCustom = new ProgramFragment.Builder(mRS);
+ pfbCustom.setShader(mRes, R.raw.multitexf);
+ for (int texCount = 0; texCount < 3; texCount ++) {
+ pfbCustom.addTexture(Program.TextureType.TEXTURE_2D);
+ }
+ mProgFragmentMultitex = pfbCustom.create();
+
+ ProgramFragmentFixedFunction.Builder colBuilder = new ProgramFragmentFixedFunction.Builder(mRS);
+ colBuilder.setVaryingColor(false);
+ mProgFragmentColor = colBuilder.create();
+
+ ProgramFragmentFixedFunction.Builder texBuilder = new ProgramFragmentFixedFunction.Builder(mRS);
+ texBuilder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
+ ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
+ mProgFragmentTexture = texBuilder.create();
+
+ ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
+ mProgVertex = pvb.create();
+ ProgramVertexFixedFunction.Constants PVA = new ProgramVertexFixedFunction.Constants(mRS);
+ ((ProgramVertexFixedFunction)mProgVertex).bindConstants(PVA);
+ Matrix4f proj = new Matrix4f();
+ proj.loadOrthoWindow(1280, 720);
+ PVA.setProjection(proj);
+ }
+
+ private Allocation loadTextureRGB(int id) {
+ return Allocation.createFromBitmapResource(mRS, mRes, id,
+ Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
+ Allocation.USAGE_GRAPHICS_TEXTURE);
+ }
+
+ private void loadImages() {
+ mTexTorus = loadTextureRGB(R.drawable.torusmap);
+ }
+
+ private void initMesh() {
+ FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.torus);
+ FileA3D.IndexEntry entry = model.getIndexEntry(0);
+ if (entry == null || entry.getEntryType() != FileA3D.EntryType.MESH) {
+ Log.e("rs", "could not load model");
+ } else {
+ mTorus = (Mesh)entry.getObject();
+ }
+ }
+
+ void initTorusScript() {
+ mTorusScript = new ScriptC_torus_test(mRS, mRes, R.raw.torus_test);
+ mTorusScript.set_gCullFront(ProgramRaster.CULL_FRONT(mRS));
+ mTorusScript.set_gCullBack(ProgramRaster.CULL_BACK(mRS));
+ mTorusScript.set_gLinearClamp(Sampler.CLAMP_LINEAR(mRS));
+ mTorusScript.set_gTorusMesh(mTorus);
+ mTorusScript.set_gTexTorus(mTexTorus);
+ mTorusScript.set_gProgVertexCustom(mProgVertexCustom);
+ mTorusScript.set_gProgFragmentCustom(mProgFragmentCustom);
+ mTorusScript.set_gProgVertexPixelLight(mProgVertexPixelLight);
+ mTorusScript.set_gProgVertexPixelLightMove(mProgVertexPixelLightMove);
+ mTorusScript.set_gProgFragmentPixelLight(mProgFragmentPixelLight);
+ mTorusScript.bind_gVSConstPixel(mVSConstPixel);
+ mTorusScript.bind_gFSConstPixel(mFSConstPixel);
+ mTorusScript.bind_gVSConstants(mVSConst);
+ mTorusScript.bind_gFSConstants(mFSConst);
+ mTorusScript.set_gProgVertex(mProgVertex);
+ mTorusScript.set_gProgFragmentTexture(mProgFragmentTexture);
+ mTorusScript.set_gProgFragmentColor(mProgFragmentColor);
+ mTorusScript.set_gProgStoreBlendNoneDepth(mProgStoreBlendNoneDepth);
+ }
+}
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/UiTest.java b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/UiTest.java
new file mode 100644
index 0000000..c8b58b2
--- /dev/null
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/UiTest.java
@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.perftest;
+
+import android.os.Environment;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.renderscript.*;
+import android.renderscript.Element.DataKind;
+import android.renderscript.Element.DataType;
+import android.renderscript.Allocation.MipmapControl;
+import android.renderscript.Program.TextureType;
+import android.renderscript.ProgramStore.DepthFunc;
+import android.renderscript.ProgramStore.BlendSrcFunc;
+import android.renderscript.ProgramStore.BlendDstFunc;
+import android.renderscript.RenderScript.RSMessageHandler;
+import android.renderscript.Mesh.Primitive;
+import android.renderscript.Matrix4f;
+import android.renderscript.ProgramVertexFixedFunction;
+
+import android.util.Log;
+
+
+public class UiTest implements RsBenchBaseTest{
+
+ private static final String TAG = "UiTest";
+ private static final String SAMPLE_TEXT = "Bench Test";
+ private static final String LIST_TEXT =
+ "This is a sample list of text to show in the list view";
+ private static int PARTICLES_COUNT = 12000;
+
+ private RenderScriptGL mRS;
+ private Resources mRes;
+
+ Font mFontSans;
+
+ private ScriptField_ListAllocs_s mTextureAllocs;
+ private ScriptField_ListAllocs_s mSampleTextAllocs;
+ private ScriptField_ListAllocs_s mSampleListViewAllocs;
+ private ScriptField_VpConsts mPvStarAlloc;
+ private ProgramVertexFixedFunction.Constants mPvProjectionAlloc;
+
+ private Mesh mSingleMesh;
+ private Mesh mParticlesMesh;
+
+ private ScriptC_ui_test mUiScript;
+
+ private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
+
+ ScriptField_TestScripts_s.Item[] mTests;
+
+ private final String[] mNames = {
+ "UI test with icon display 10 by 10",
+ "UI test with icon display 100 by 100",
+ "UI test with image and text display 3 pages",
+ "UI test with image and text display 5 pages",
+ "UI test with list view",
+ "UI test with live wallpaper"
+ };
+
+ public UiTest() {
+ }
+
+ void addTest(int index, int testId, int user1, int user2, int user3) {
+ mTests[index] = new ScriptField_TestScripts_s.Item();
+ mTests[index].testScript = mUiScript;
+ mTests[index].testName = Allocation.createFromString(mRS,
+ mNames[index],
+ Allocation.USAGE_SCRIPT);
+ mTests[index].debugName = RsBenchRS.createZeroTerminatedAlloc(mRS,
+ mNames[index],
+ Allocation.USAGE_SCRIPT);
+
+ ScriptField_UiTestData_s.Item dataItem = new ScriptField_UiTestData_s.Item();
+ dataItem.testId = testId;
+ dataItem.user1 = user1;
+ dataItem.user2 = user2;
+ dataItem.user3 = user3;
+ ScriptField_UiTestData_s testData = new ScriptField_UiTestData_s(mRS, 1);
+ testData.set(dataItem, 0, true);
+ mTests[index].testData = testData.getAllocation();
+ }
+
+ public boolean init(RenderScriptGL rs, Resources res) {
+ mRS = rs;
+ mRes = res;
+ mFontSans = Font.create(mRS, mRes, "sans-serif", Font.Style.NORMAL, 8);
+ mSingleMesh = getSingleMesh(1, 1); // a unit size mesh
+
+ initUiScript();
+ mTests = new ScriptField_TestScripts_s.Item[mNames.length];
+
+ int index = 0;
+
+ addTest(index++, 0, 0 /*meshMode*/, 0 /*unused*/, 0 /*unused*/);
+ addTest(index++, 0, 1 /*meshMode*/, 0 /*unused*/, 0 /*unused*/);
+ addTest(index++, 1, 7 /*wResolution*/, 5 /*hResolution*/, 0 /*meshMode*/);
+ addTest(index++, 1, 7 /*wResolution*/, 5 /*hResolution*/, 1 /*meshMode*/);
+ addTest(index++, 2, 0 /*unused*/, 0 /*unused*/, 0 /*unused*/);
+ addTest(index++, 3, 7 /*wResolution*/, 5 /*hResolution*/, 0 /*unused*/);
+
+ return true;
+ }
+
+ public ScriptField_TestScripts_s.Item[] getTests() {
+ return mTests;
+ }
+
+ public String[] getTestNames() {
+ return mNames;
+ }
+
+ private Allocation loadTextureRGB(int id) {
+ return Allocation.createFromBitmapResource(mRS, mRes, id,
+ Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
+ Allocation.USAGE_GRAPHICS_TEXTURE);
+ }
+
+ private Allocation loadTextureARGB(int id) {
+ Bitmap b = BitmapFactory.decodeResource(mRes, id, mOptionsARGB);
+ return Allocation.createFromBitmap(mRS, b,
+ Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
+ Allocation.USAGE_GRAPHICS_TEXTURE);
+ }
+
+ private void createParticlesMesh() {
+ ScriptField_Particle p = new ScriptField_Particle(mRS, PARTICLES_COUNT);
+
+ final Mesh.AllocationBuilder meshBuilder = new Mesh.AllocationBuilder(mRS);
+ meshBuilder.addVertexAllocation(p.getAllocation());
+ final int vertexSlot = meshBuilder.getCurrentVertexTypeIndex();
+ meshBuilder.addIndexSetType(Primitive.POINT);
+ mParticlesMesh = meshBuilder.create();
+
+ mUiScript.set_gParticlesMesh(mParticlesMesh);
+ mUiScript.bind_Particles(p);
+ }
+
+ /**
+ * Create a mesh with a single quad for the given width and height.
+ */
+ private Mesh getSingleMesh(float width, float height) {
+ Mesh.TriangleMeshBuilder tmb = new Mesh.TriangleMeshBuilder(mRS,
+ 2, Mesh.TriangleMeshBuilder.TEXTURE_0);
+ float xOffset = width/2;
+ float yOffset = height/2;
+ tmb.setTexture(0, 0);
+ tmb.addVertex(-1.0f * xOffset, -1.0f * yOffset);
+ tmb.setTexture(1, 0);
+ tmb.addVertex(xOffset, -1.0f * yOffset);
+ tmb.setTexture(1, 1);
+ tmb.addVertex(xOffset, yOffset);
+ tmb.setTexture(0, 1);
+ tmb.addVertex(-1.0f * xOffset, yOffset);
+ tmb.addTriangle(0, 3, 1);
+ tmb.addTriangle(1, 3, 2);
+ return tmb.create(true);
+ }
+
+ private Matrix4f getProjectionNormalized(int w, int h) {
+ // range -1,1 in the narrow axis at z = 0.
+ Matrix4f m1 = new Matrix4f();
+ Matrix4f m2 = new Matrix4f();
+
+ if(w > h) {
+ float aspect = ((float)w) / h;
+ m1.loadFrustum(-aspect,aspect, -1,1, 1,100);
+ } else {
+ float aspect = ((float)h) / w;
+ m1.loadFrustum(-1,1, -aspect,aspect, 1,100);
+ }
+
+ m2.loadRotate(180, 0, 1, 0);
+ m1.loadMultiply(m1, m2);
+
+ m2.loadScale(-2, 2, 1);
+ m1.loadMultiply(m1, m2);
+
+ m2.loadTranslate(0, 0, 2);
+ m1.loadMultiply(m1, m2);
+ return m1;
+ }
+
+ private void updateProjectionMatrices() {
+ Matrix4f projNorm = getProjectionNormalized(1280, 720);
+ ScriptField_VpConsts.Item i = new ScriptField_VpConsts.Item();
+ i.Proj = projNorm;
+ i.MVP = projNorm;
+ mPvStarAlloc.set(i, 0, true);
+ mPvProjectionAlloc.setProjection(projNorm);
+ }
+
+ void initUiScript() {
+ mUiScript = new ScriptC_ui_test(mRS, mRes, R.raw.ui_test);
+
+ ProgramFragmentFixedFunction.Builder colBuilder = new ProgramFragmentFixedFunction.Builder(mRS);
+ colBuilder.setVaryingColor(false);
+ ProgramFragmentFixedFunction.Builder texBuilder = new ProgramFragmentFixedFunction.Builder(mRS);
+ texBuilder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
+ ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
+
+ ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
+ ProgramVertexFixedFunction progVertex = pvb.create();
+ ProgramVertexFixedFunction.Constants PVA = new ProgramVertexFixedFunction.Constants(mRS);
+ ((ProgramVertexFixedFunction)progVertex).bindConstants(PVA);
+ Matrix4f proj = new Matrix4f();
+ proj.loadOrthoWindow(1280, 720);
+ PVA.setProjection(proj);
+
+ mUiScript.set_gProgVertex(progVertex);
+ mUiScript.set_gProgFragmentColor(colBuilder.create());
+ mUiScript.set_gProgFragmentTexture(texBuilder.create());
+ mUiScript.set_gProgStoreBlendAlpha(ProgramStore.BLEND_ALPHA_DEPTH_NONE(mRS));
+
+ mUiScript.set_gLinearClamp(Sampler.CLAMP_LINEAR(mRS));
+
+ mUiScript.set_gTexTorus(loadTextureRGB(R.drawable.torusmap));
+ mUiScript.set_gTexOpaque(loadTextureRGB(R.drawable.data));
+ mUiScript.set_gTexGlobe(loadTextureRGB(R.drawable.globe));
+ mUiScript.set_gSingleMesh(mSingleMesh);
+
+ // For GALAXY
+ ProgramStore.Builder psb = new ProgramStore.Builder(mRS);
+ psb.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ZERO);
+ mRS.bindProgramStore(psb.create());
+
+ psb.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE);
+ mUiScript.set_gPSLights(psb.create());
+
+ // For Galaxy live wallpaper drawing
+ ProgramFragmentFixedFunction.Builder builder = new ProgramFragmentFixedFunction.Builder(mRS);
+ builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
+ ProgramFragmentFixedFunction.Builder.Format.RGB, 0);
+ ProgramFragment pfb = builder.create();
+ pfb.bindSampler(Sampler.WRAP_NEAREST(mRS), 0);
+ mUiScript.set_gPFBackground(pfb);
+
+ builder = new ProgramFragmentFixedFunction.Builder(mRS);
+ builder.setPointSpriteTexCoordinateReplacement(true);
+ builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.MODULATE,
+ ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
+ builder.setVaryingColor(true);
+ ProgramFragment pfs = builder.create();
+ pfs.bindSampler(Sampler.WRAP_LINEAR_MIP_LINEAR(mRS), 0);
+ mUiScript.set_gPFStars(pfs);
+
+ mTextureAllocs = new ScriptField_ListAllocs_s(mRS, 100);
+ for (int i = 0; i < 100; i++) {
+ ScriptField_ListAllocs_s.Item texElem = new ScriptField_ListAllocs_s.Item();
+ texElem.item = loadTextureRGB(R.drawable.globe);
+ mTextureAllocs.set(texElem, i, false);
+ }
+ mTextureAllocs.copyAll();
+ mUiScript.bind_gTexList100(mTextureAllocs);
+
+ mSampleTextAllocs = new ScriptField_ListAllocs_s(mRS, 100);
+ for (int i = 0; i < 100; i++) {
+ ScriptField_ListAllocs_s.Item textElem = new ScriptField_ListAllocs_s.Item();
+ textElem.item = Allocation.createFromString(mRS, SAMPLE_TEXT, Allocation.USAGE_SCRIPT);
+ mSampleTextAllocs.set(textElem, i, false);
+ }
+ mSampleTextAllocs.copyAll();
+ mUiScript.bind_gSampleTextList100(mSampleTextAllocs);
+
+ mSampleListViewAllocs = new ScriptField_ListAllocs_s(mRS, 1000);
+ for (int i = 0; i < 1000; i++) {
+ ScriptField_ListAllocs_s.Item textElem = new ScriptField_ListAllocs_s.Item();
+ textElem.item = Allocation.createFromString(mRS, LIST_TEXT, Allocation.USAGE_SCRIPT);
+ mSampleListViewAllocs.set(textElem, i, false);
+ }
+ mSampleListViewAllocs.copyAll();
+ mUiScript.bind_gListViewText(mSampleListViewAllocs);
+
+ // For galaxy live wallpaper
+ mPvStarAlloc = new ScriptField_VpConsts(mRS, 1);
+ mUiScript.bind_vpConstants(mPvStarAlloc);
+ mPvProjectionAlloc = new ProgramVertexFixedFunction.Constants(mRS);
+ updateProjectionMatrices();
+
+ pvb = new ProgramVertexFixedFunction.Builder(mRS);
+ ProgramVertex pvbp = pvb.create();
+ ((ProgramVertexFixedFunction)pvbp).bindConstants(mPvProjectionAlloc);
+ mUiScript.set_gPVBkProj(pvbp);
+
+ createParticlesMesh();
+
+ ProgramVertex.Builder sb = new ProgramVertex.Builder(mRS);
+ String t = "varying vec4 varColor;\n" +
+ "varying vec2 varTex0;\n" +
+ "void main() {\n" +
+ " float dist = ATTRIB_position.y;\n" +
+ " float angle = ATTRIB_position.x;\n" +
+ " float x = dist * sin(angle);\n" +
+ " float y = dist * cos(angle) * 0.892;\n" +
+ " float p = dist * 5.5;\n" +
+ " float s = cos(p);\n" +
+ " float t = sin(p);\n" +
+ " vec4 pos;\n" +
+ " pos.x = t * x + s * y;\n" +
+ " pos.y = s * x - t * y;\n" +
+ " pos.z = ATTRIB_position.z;\n" +
+ " pos.w = 1.0;\n" +
+ " gl_Position = UNI_MVP * pos;\n" +
+ " gl_PointSize = ATTRIB_color.a * 10.0;\n" +
+ " varColor.rgb = ATTRIB_color.rgb;\n" +
+ " varColor.a = 1.0;\n" +
+ "}\n";
+ sb.setShader(t);
+ sb.addInput(mParticlesMesh.getVertexAllocation(0).getType().getElement());
+ sb.addConstant(mPvStarAlloc.getType());
+ ProgramVertex pvs = sb.create();
+ pvs.bindConstants(mPvStarAlloc.getAllocation(), 0);
+ mUiScript.set_gPVStars(pvs);
+
+ // For Galaxy live wallpaper
+ mUiScript.set_gTSpace(loadTextureRGB(R.drawable.space));
+ mUiScript.set_gTLight1(loadTextureRGB(R.drawable.light1));
+ mUiScript.set_gTFlares(loadTextureARGB(R.drawable.flares));
+
+ mUiScript.set_gFontSans(mFontSans);
+ }
+}
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/fill_test.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/fill_test.rs
new file mode 100644
index 0000000..23832d3
--- /dev/null
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/fill_test.rs
@@ -0,0 +1,137 @@
+// Copyright (C) 2011 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.perftest)
+
+#include "rs_graphics.rsh"
+#include "subtest_def.rsh"
+
+rs_program_vertex gProgVertex;
+rs_program_fragment gProgFragmentTexture;
+rs_program_fragment gProgFragmentMultitex;
+
+rs_program_store gProgStoreBlendNone;
+rs_program_store gProgStoreBlendAlpha;
+
+rs_allocation gTexOpaque;
+rs_allocation gTexTorus;
+rs_allocation gTexTransparent;
+rs_allocation gTexChecker;
+
+rs_sampler gLinearClamp;
+rs_sampler gLinearWrap;
+
+typedef struct FillTestData_s {
+ int testId;
+ int blend;
+ int quadCount;
+} FillTestData;
+FillTestData *gData;
+
+static float gDt = 0.0f;
+
+void init() {
+}
+
+static int gRenderSurfaceW = 1280;
+static int gRenderSurfaceH = 720;
+
+static void bindProgramVertexOrtho() {
+ // Default vertex shader
+ rsgBindProgramVertex(gProgVertex);
+ // Setup the projection matrix
+ rs_matrix4x4 proj;
+ rsMatrixLoadOrtho(&proj, 0, gRenderSurfaceW, gRenderSurfaceH, 0, -500, 500);
+ rsgProgramVertexLoadProjectionMatrix(&proj);
+}
+
+static void displaySingletexFill(bool blend, int quadCount) {
+ bindProgramVertexOrtho();
+ rs_matrix4x4 matrix;
+ rsMatrixLoadIdentity(&matrix);
+ rsgProgramVertexLoadModelMatrix(&matrix);
+
+ // Fragment shader with texture
+ if (!blend) {
+ rsgBindProgramStore(gProgStoreBlendNone);
+ } else {
+ rsgBindProgramStore(gProgStoreBlendAlpha);
+ }
+ rsgBindProgramFragment(gProgFragmentTexture);
+ rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
+ rsgBindTexture(gProgFragmentTexture, 0, gTexOpaque);
+
+ for (int i = 0; i < quadCount; i ++) {
+ float startX = 5 * i, startY = 5 * i;
+ float width = gRenderSurfaceW - startX, height = gRenderSurfaceH - startY;
+ rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
+ startX, startY + height, 0, 0, 1,
+ startX + width, startY + height, 0, 1, 1,
+ startX + width, startY, 0, 1, 0);
+ }
+}
+
+static void displayMultitextureSample(bool blend, int quadCount) {
+ bindProgramVertexOrtho();
+ rs_matrix4x4 matrix;
+ rsMatrixLoadIdentity(&matrix);
+ rsgProgramVertexLoadModelMatrix(&matrix);
+
+ // Fragment shader with texture
+ if (!blend) {
+ rsgBindProgramStore(gProgStoreBlendNone);
+ } else {
+ rsgBindProgramStore(gProgStoreBlendAlpha);
+ }
+ rsgBindProgramFragment(gProgFragmentMultitex);
+ rsgBindSampler(gProgFragmentMultitex, 0, gLinearClamp);
+ rsgBindSampler(gProgFragmentMultitex, 1, gLinearWrap);
+ rsgBindSampler(gProgFragmentMultitex, 2, gLinearClamp);
+ rsgBindTexture(gProgFragmentMultitex, 0, gTexChecker);
+ rsgBindTexture(gProgFragmentMultitex, 1, gTexTorus);
+ rsgBindTexture(gProgFragmentMultitex, 2, gTexTransparent);
+
+ for (int i = 0; i < quadCount; i ++) {
+ float startX = 10 * i, startY = 10 * i;
+ float width = gRenderSurfaceW - startX, height = gRenderSurfaceH - startY;
+ rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
+ startX, startY + height, 0, 0, 1,
+ startX + width, startY + height, 0, 1, 1,
+ startX + width, startY, 0, 1, 0);
+ }
+}
+
+
+void root(const void *v_in, void *v_out, const void *usrData, uint32_t x, uint32_t y) {
+ TestData *testData = (TestData*)usrData;
+ gRenderSurfaceW = testData->renderSurfaceW;
+ gRenderSurfaceH = testData->renderSurfaceH;
+ gDt = testData->dt;
+
+ gData = (FillTestData*)v_in;
+
+ switch(gData->testId) {
+ case 0:
+ displayMultitextureSample(gData->blend == 1 ? true : false, gData->quadCount);
+ break;
+ case 1:
+ displaySingletexFill(gData->blend == 1 ? true : false, gData->quadCount);
+ break;
+ default:
+ rsDebug("Wrong test number", 0);
+ break;
+ }
+}
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/mesh_test.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/mesh_test.rs
new file mode 100644
index 0000000..d7e4857
--- /dev/null
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/mesh_test.rs
@@ -0,0 +1,89 @@
+// Copyright (C) 2011 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.perftest)
+
+#include "rs_graphics.rsh"
+#include "shader_def.rsh"
+#include "subtest_def.rsh"
+
+rs_program_vertex gProgVertex;
+rs_program_fragment gProgFragmentTexture;
+
+rs_program_store gProgStoreBlendNone;
+
+rs_allocation gTexOpaque;
+
+rs_mesh g10by10Mesh;
+rs_mesh g100by100Mesh;
+rs_mesh gWbyHMesh;
+
+rs_sampler gLinearClamp;
+static int gRenderSurfaceW;
+static int gRenderSurfaceH;
+
+static float gDt = 0;
+
+typedef struct MeshTestData_s {
+ int meshNum;
+} MeshTestData;
+MeshTestData *gData;
+
+void init() {
+}
+
+static void bindProgramVertexOrtho() {
+ // Default vertex shader
+ rsgBindProgramVertex(gProgVertex);
+ // Setup the projection matrix
+ rs_matrix4x4 proj;
+ rsMatrixLoadOrtho(&proj, 0, gRenderSurfaceW, gRenderSurfaceH, 0, -500, 500);
+ rsgProgramVertexLoadProjectionMatrix(&proj);
+}
+
+static void displayMeshSamples(int meshNum) {
+
+ bindProgramVertexOrtho();
+ rs_matrix4x4 matrix;
+ rsMatrixLoadTranslate(&matrix, gRenderSurfaceW/2, gRenderSurfaceH/2, 0);
+ rsgProgramVertexLoadModelMatrix(&matrix);
+
+ // Fragment shader with texture
+ rsgBindProgramStore(gProgStoreBlendNone);
+ rsgBindProgramFragment(gProgFragmentTexture);
+ rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
+
+ rsgBindTexture(gProgFragmentTexture, 0, gTexOpaque);
+
+ if (meshNum == 0) {
+ rsgDrawMesh(g10by10Mesh);
+ } else if (meshNum == 1) {
+ rsgDrawMesh(g100by100Mesh);
+ } else if (meshNum == 2) {
+ rsgDrawMesh(gWbyHMesh);
+ }
+}
+
+void root(const void *v_in, void *v_out, const void *usrData, uint32_t x, uint32_t y) {
+ TestData *testData = (TestData*)usrData;
+ gRenderSurfaceW = testData->renderSurfaceW;
+ gRenderSurfaceH = testData->renderSurfaceH;
+ gDt = testData->dt;
+
+ gData = (MeshTestData*)v_in;
+
+ displayMeshSamples(gData->meshNum);
+}
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
index db97835..27e5b11 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/rsbench.rs
@@ -1,4 +1,4 @@
-// Copyright (C) 2009 The Android Open Source Project
+// Copyright (C) 2010-2011 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -24,104 +24,34 @@
const int RS_MSG_TEST_DONE = 100;
const int RS_MSG_RESULTS_READY = 101;
-const int gMaxModes = 31;
-int gMaxLoops;
-
-// Parameters for galaxy live wallpaper
-rs_allocation gTSpace;
-rs_allocation gTLight1;
-rs_allocation gTFlares;
-rs_mesh gParticlesMesh;
-
-rs_program_fragment gPFBackground;
-rs_program_fragment gPFStars;
-rs_program_vertex gPVStars;
-rs_program_vertex gPVBkProj;
-rs_program_store gPSLights;
-
-float gXOffset = 0.5f;
-
-#define ELLIPSE_RATIO 0.892f
-#define PI 3.1415f
-#define TWO_PI 6.283f
-#define ELLIPSE_TWIST 0.023333333f
-
-static float angle = 50.f;
-static int gOldWidth;
-static int gOldHeight;
-static int gWidth;
-static int gHeight;
-static float gSpeed[12000];
-static int gGalaxyRadius = 300;
-static rs_allocation gParticlesBuffer;
-
-typedef struct __attribute__((packed, aligned(4))) Particle {
- uchar4 color;
- float3 position;
-} Particle_t;
-Particle_t *Particles;
-
-typedef struct VpConsts {
- rs_matrix4x4 Proj;
- rs_matrix4x4 MVP;
-} VpConsts_t;
-VpConsts_t *vpConstants;
-// End of parameters for galaxy live wallpaper
-
-// Allocation to send test names back to java
-char *gStringBuffer = 0;
+static const int gMaxModes = 64;
+int gMaxLoops = 1;
+int gDisplayMode = 1;
+
// Allocation to write the results into
static float gResultBuffer[gMaxModes];
-rs_program_vertex gProgVertex;
-rs_program_fragment gProgFragmentColor;
-rs_program_fragment gProgFragmentTexture;
-
-rs_program_store gProgStoreBlendNoneDepth;
-rs_program_store gProgStoreBlendNone;
-rs_program_store gProgStoreBlendAlpha;
-rs_program_store gProgStoreBlendAdd;
-
-rs_allocation gTexOpaque;
-rs_allocation gTexTorus;
-rs_allocation gTexTransparent;
-rs_allocation gTexChecker;
-rs_allocation gTexGlobe;
-
-typedef struct ListAllocs_s {
- rs_allocation item;
-} ListAllocs;
-
-ListAllocs *gTexList100;
-ListAllocs *gSampleTextList100;
-ListAllocs *gListViewText;
-
-rs_mesh g10by10Mesh;
-rs_mesh g100by100Mesh;
-rs_mesh gWbyHMesh;
-rs_mesh gSingleMesh;
-
-rs_font gFontSans;
rs_font gFontSerif;
-
-int gDisplayMode;
-
rs_sampler gLinearClamp;
-rs_sampler gLinearWrap;
-rs_sampler gMipLinearWrap;
-rs_sampler gNearestClamp;
-rs_program_raster gCullBack;
-rs_program_raster gCullFront;
-rs_program_raster gCullNone;
+rs_program_vertex gProgVertex;
+rs_program_fragment gProgFragmentTexture;
+
+rs_allocation gRenderBufferColor;
+rs_allocation gRenderBufferDepth;
-// Export these out to easily set the inputs to shader
VertexShaderInputs *gVSInputs;
-rs_program_fragment gProgFragmentMultitex;
+typedef struct TestScripts_s {
+ rs_allocation testData;
+ rs_allocation testName;
+ rs_allocation debugName;
+ rs_script testScript;
+} TestScripts;
+TestScripts *gTestScripts;
-rs_allocation gRenderBufferColor;
-rs_allocation gRenderBufferDepth;
+bool gLoadComplete = false;
+bool gPauseRendering = false;
static float gDt = 0;
@@ -131,158 +61,17 @@ void init() {
static int gRenderSurfaceW;
static int gRenderSurfaceH;
-/**
- * Methods to draw the galaxy live wall paper
- */
-static float mapf(float minStart, float minStop, float maxStart, float maxStop, float value) {
- return maxStart + (maxStart - maxStop) * ((value - minStart) / (minStop - minStart));
-}
-
-/**
- * Helper function to generate the stars.
- */
-static float randomGauss() {
- float x1;
- float x2;
- float w = 2.f;
-
- while (w >= 1.0f) {
- x1 = rsRand(2.0f) - 1.0f;
- x2 = rsRand(2.0f) - 1.0f;
- w = x1 * x1 + x2 * x2;
- }
-
- w = sqrt(-2.0f * log(w) / w);
- return x1 * w;
+static void fillSurfaceParams(TestData *testData) {
+ testData->renderSurfaceW = gRenderSurfaceW;
+ testData->renderSurfaceH = gRenderSurfaceH;
+ testData->dt = gDt;
}
-/**
- * Generates the properties for a given star.
- */
-static void createParticle(Particle_t *part, int idx, float scale) {
- float d = fabs(randomGauss()) * gGalaxyRadius * 0.5f + rsRand(64.0f);
- float id = d / gGalaxyRadius;
- float z = randomGauss() * 0.4f * (1.0f - id);
- float p = -d * ELLIPSE_TWIST;
-
- if (d < gGalaxyRadius * 0.33f) {
- part->color.x = (uchar) (220 + id * 35);
- part->color.y = 220;
- part->color.z = 220;
- } else {
- part->color.x = 180;
- part->color.y = 180;
- part->color.z = (uchar) clamp(140.f + id * 115.f, 140.f, 255.f);
- }
- // Stash point size * 10 in Alpha
- part->color.w = (uchar) (rsRand(1.2f, 2.1f) * 60);
-
- if (d > gGalaxyRadius * 0.15f) {
- z *= 0.6f * (1.0f - id);
- } else {
- z *= 0.72f;
- }
-
- // Map to the projection coordinates (viewport.x = -1.0 -> 1.0)
- d = mapf(-4.0f, gGalaxyRadius + 4.0f, 0.0f, scale, d);
-
- part->position.x = rsRand(TWO_PI);
- part->position.y = d;
- gSpeed[idx] = rsRand(0.0015f, 0.0025f) * (0.5f + (scale / d)) * 0.8f;
-
- part->position.z = z / 5.0f;
-}
-
-/**
- * Initialize all the starts, called from Java
- */
-void initParticles() {
- Particle_t *part = Particles;
- float scale = gGalaxyRadius / (gWidth * 0.5f);
- int count = rsAllocationGetDimX(gParticlesBuffer);
- for (int i = 0; i < count; i ++) {
- createParticle(part, i, scale);
- part++;
- }
-}
-
-static void drawSpace() {
- rsgBindProgramFragment(gPFBackground);
- rsgBindTexture(gPFBackground, 0, gTSpace);
- rsgDrawQuadTexCoords(
- 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
- gWidth, 0.0f, 0.0f, 2.0f, 1.0f,
- gWidth, gHeight, 0.0f, 2.0f, 0.0f,
- 0.0f, gHeight, 0.0f, 0.0f, 0.0f);
-}
-
-static void drawLights() {
- rsgBindProgramVertex(gPVBkProj);
- rsgBindProgramFragment(gPFBackground);
- rsgBindTexture(gPFBackground, 0, gTLight1);
-
- float scale = 512.0f / gWidth;
- float x = -scale - scale * 0.05f;
- float y = -scale;
-
- scale *= 2.0f;
-
- rsgDrawQuad(x, y, 0.0f,
- x + scale * 1.1f, y, 0.0f,
- x + scale * 1.1f, y + scale, 0.0f,
- x, y + scale, 0.0f);
-}
-
-static void drawParticles(float offset) {
- float a = offset * angle;
- float absoluteAngle = fabs(a);
-
- rs_matrix4x4 matrix;
- rsMatrixLoadTranslate(&matrix, 0.0f, 0.0f, 10.0f - 6.0f * absoluteAngle / 50.0f);
- if (gHeight > gWidth) {
- rsMatrixScale(&matrix, 6.6f, 6.0f, 1.0f);
- } else {
- rsMatrixScale(&matrix, 12.6f, 12.0f, 1.0f);
- }
- rsMatrixRotate(&matrix, absoluteAngle, 1.0f, 0.0f, 0.0f);
- rsMatrixRotate(&matrix, a, 0.0f, 0.4f, 0.1f);
- rsMatrixLoad(&vpConstants->MVP, &vpConstants->Proj);
- rsMatrixMultiply(&vpConstants->MVP, &matrix);
- rsgAllocationSyncAll(rsGetAllocation(vpConstants));
-
- rsgBindProgramVertex(gPVStars);
- rsgBindProgramFragment(gPFStars);
- rsgBindProgramStore(gPSLights);
- rsgBindTexture(gPFStars, 0, gTFlares);
-
- Particle_t *vtx = Particles;
- int count = rsAllocationGetDimX(gParticlesBuffer);
- for (int i = 0; i < count; i++) {
- vtx->position.x = vtx->position.x + gSpeed[i];
- vtx++;
- }
-
- rsgDrawMesh(gParticlesMesh);
-}
-/* end of methods for drawing galaxy */
-
static void setupOffscreenTarget() {
rsgBindColorTarget(gRenderBufferColor, 0);
rsgBindDepthTarget(gRenderBufferDepth);
}
-rs_script gFontScript;
-rs_script gTorusScript;
-rs_allocation gDummyAlloc;
-
-static void displayFontSamples(int fillNum) {
- TestData testData;
- testData.renderSurfaceW = gRenderSurfaceW;
- testData.renderSurfaceH = gRenderSurfaceH;
- testData.user = fillNum;
- rsForEach(gFontScript, gDummyAlloc, gDummyAlloc, &testData, sizeof(testData));
-}
-
static void bindProgramVertexOrtho() {
// Default vertex shader
rsgBindProgramVertex(gProgVertex);
@@ -292,302 +81,31 @@ static void bindProgramVertexOrtho() {
rsgProgramVertexLoadProjectionMatrix(&proj);
}
-static void displaySingletexFill(bool blend, int quadCount) {
- bindProgramVertexOrtho();
- rs_matrix4x4 matrix;
- rsMatrixLoadIdentity(&matrix);
- rsgProgramVertexLoadModelMatrix(&matrix);
-
- // Fragment shader with texture
- if (!blend) {
- rsgBindProgramStore(gProgStoreBlendNone);
- } else {
- rsgBindProgramStore(gProgStoreBlendAlpha);
- }
- rsgBindProgramFragment(gProgFragmentTexture);
- rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
- rsgBindTexture(gProgFragmentTexture, 0, gTexOpaque);
-
- for (int i = 0; i < quadCount; i ++) {
- float startX = 5 * i, startY = 5 * i;
- float width = gRenderSurfaceW - startX, height = gRenderSurfaceH - startY;
- rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
- startX, startY + height, 0, 0, 1,
- startX + width, startY + height, 0, 1, 1,
- startX + width, startY, 0, 1, 0);
- }
-}
-
-static void displayMeshSamples(int meshNum) {
-
- bindProgramVertexOrtho();
- rs_matrix4x4 matrix;
- rsMatrixLoadTranslate(&matrix, gRenderSurfaceW/2, gRenderSurfaceH/2, 0);
- rsgProgramVertexLoadModelMatrix(&matrix);
-
- // Fragment shader with texture
- rsgBindProgramStore(gProgStoreBlendNone);
- rsgBindProgramFragment(gProgFragmentTexture);
- rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
-
- rsgBindTexture(gProgFragmentTexture, 0, gTexOpaque);
-
- if (meshNum == 0) {
- rsgDrawMesh(g10by10Mesh);
- } else if (meshNum == 1) {
- rsgDrawMesh(g100by100Mesh);
- } else if (meshNum == 2) {
- rsgDrawMesh(gWbyHMesh);
- }
-}
-
-// Display sample images in a mesh with different texture
-static void displayIcons(int meshMode) {
- bindProgramVertexOrtho();
-
- // Fragment shader with texture
- rsgBindProgramStore(gProgStoreBlendAlpha);
- rsgBindProgramFragment(gProgFragmentTexture);
- rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
- rsgBindTexture(gProgFragmentTexture, 0, gTexTorus);
- rsgDrawQuadTexCoords(
- 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, gRenderSurfaceH, 0.0f, 0.0f, 1.0f,
- gRenderSurfaceW, gRenderSurfaceH, 0.0f, 1.0f, 1.0f,
- gRenderSurfaceW, 0.0f, 0.0f, 1.0f, 0.0f);
-
- int meshCount = (int)pow(10.0f, (float)(meshMode + 1));
-
- float wSize = gRenderSurfaceW/(float)meshCount;
- float hSize = gRenderSurfaceH/(float)meshCount;
- rs_matrix4x4 matrix;
- rsMatrixLoadScale(&matrix, wSize, hSize, 1.0);
-
- float yPos = 0;
- float yPad = hSize / 2;
- float xPad = wSize / 2;
- for (int y = 0; y < meshCount; y++) {
- yPos = y * hSize + yPad;
- float xPos = 0;
- for (int x = 0; x < meshCount; x++) {
- xPos = x * wSize + xPad;
- rs_matrix4x4 transMatrix;
- rsMatrixLoadTranslate(&transMatrix, xPos, yPos, 0);
- rsMatrixMultiply(&transMatrix, &matrix);
- rsgProgramVertexLoadModelMatrix(&transMatrix);
- int i = (x + y * meshCount) % 100;
- rsgBindTexture(gProgFragmentTexture, 0, gTexList100[i].item);
- rsgDrawMesh(gSingleMesh);
- }
- }
-}
-
-// Draw meshes in a single page with top left corner coordinates (xStart, yStart)
-static void drawMeshInPage(float xStart, float yStart, int wResolution, int hResolution) {
- // Draw wResolution * hResolution meshes in one page
- float wMargin = 100.0f;
- float hMargin = 100.0f;
- float xPad = 50.0f;
- float yPad = 20.0f;
- float size = 100.0f; // size of images
-
- // font info
- rs_font font = gFontSans;
- rsgBindFont(font);
- rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
-
- // Measure text size
- int left = 0, right = 0, top = 0, bottom = 0;
- rsgMeasureText(gSampleTextList100[0].item, &left, &right, &top, &bottom);
- float textHeight = (float)(top - bottom);
- float textWidth = (float)(right - left);
-
- rs_matrix4x4 matrix;
- rsMatrixLoadScale(&matrix, size, size, 1.0);
-
- for (int y = 0; y < hResolution; y++) {
- float yPos = yStart + hMargin + y * size + y * yPad;
- for (int x = 0; x < wResolution; x++) {
- float xPos = xStart + wMargin + x * size + x * xPad;
-
- rs_matrix4x4 transMatrix;
- rsMatrixLoadTranslate(&transMatrix, xPos + size/2, yPos + size/2, 0);
- rsMatrixMultiply(&transMatrix, &matrix); // scale the mesh
- rsgProgramVertexLoadModelMatrix(&transMatrix);
-
- int i = (y * wResolution + x) % 100;
- rsgBindTexture(gProgFragmentTexture, 0, gTexList100[i].item);
- rsgDrawMesh(gSingleMesh);
- rsgDrawText(gSampleTextList100[i].item, xPos, yPos + size + yPad/2 + textHeight);
- }
- }
-}
-
-// Display both images and text as shown in launcher and homepage
-// meshMode will decide how many pages we draw
-// meshMode = 0: draw 3 pages of meshes
-// meshMode = 1: draw 5 pages of meshes
-static void displayImageWithText(int wResolution, int hResolution, int meshMode) {
- bindProgramVertexOrtho();
-
- // Fragment shader with texture
- rsgBindProgramStore(gProgStoreBlendAlpha);
- rsgBindProgramFragment(gProgFragmentTexture);
- rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
-
- drawMeshInPage(0, 0, wResolution, hResolution);
- drawMeshInPage(-1.0f*gRenderSurfaceW, 0, wResolution, hResolution);
- drawMeshInPage(1.0f*gRenderSurfaceW, 0, wResolution, hResolution);
- if (meshMode == 1) {
- // draw another two pages of meshes
- drawMeshInPage(-2.0f*gRenderSurfaceW, 0, wResolution, hResolution);
- drawMeshInPage(2.0f*gRenderSurfaceW, 0, wResolution, hResolution);
- }
-}
-
-// Display a list of text as the list view
-static void displayListView() {
- // set text color
- rsgFontColor(0.9f, 0.9f, 0.9f, 1.0f);
- rsgBindFont(gFontSans);
-
- // get the size of the list
- rs_allocation textAlloc;
- textAlloc = rsGetAllocation(gListViewText);
- int allocSize = rsAllocationGetDimX(textAlloc);
-
- int listItemHeight = 80;
- int yOffset = listItemHeight;
-
- // set the color for the list divider
- rsgBindProgramFragment(gProgFragmentColor);
- rsgProgramFragmentConstantColor(gProgFragmentColor, 1.0, 1.0, 1.0, 1);
-
- // draw the list with divider
- for (int i = 0; i < allocSize; i++) {
- if (yOffset - listItemHeight > gRenderSurfaceH) {
- break;
- }
- rsgDrawRect(0, yOffset - 1, gRenderSurfaceW, yOffset, 0);
- rsgDrawText(gListViewText[i].item, 20, yOffset - 10);
- yOffset += listItemHeight;
- }
-}
-
-static void drawGalaxy() {
- rsgClearColor(0.f, 0.f, 0.f, 1.f);
- gParticlesBuffer = rsGetAllocation(Particles);
- rsgBindProgramFragment(gPFBackground);
-
- gWidth = rsgGetWidth();
- gHeight = rsgGetHeight();
- if ((gWidth != gOldWidth) || (gHeight != gOldHeight)) {
- initParticles();
- gOldWidth = gWidth;
- gOldHeight = gHeight;
- }
-
- float offset = mix(-1.0f, 1.0f, gXOffset);
- drawSpace();
- drawParticles(offset);
- drawLights();
-}
-
-// Display images and text with live wallpaper in the background
-static void displayLiveWallPaper(int wResolution, int hResolution) {
- bindProgramVertexOrtho();
-
- drawGalaxy();
-
- rsgBindProgramVertex(gProgVertex);
- rsgBindProgramStore(gProgStoreBlendAlpha);
- rsgBindProgramFragment(gProgFragmentTexture);
- rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
-
- drawMeshInPage(0, 0, wResolution, hResolution);
- drawMeshInPage(-1.0f*gRenderSurfaceW, 0, wResolution, hResolution);
- drawMeshInPage(1.0f*gRenderSurfaceW, 0, wResolution, hResolution);
- drawMeshInPage(-2.0f*gRenderSurfaceW, 0, wResolution, hResolution);
- drawMeshInPage(2.0f*gRenderSurfaceW, 0, wResolution, hResolution);
-}
-
-// Quick hack to get some geometry numbers
-static void displaySimpleGeoSamples(bool useTexture, int numMeshes) {
+static void runSubTest(int index) {
TestData testData;
- testData.renderSurfaceW = gRenderSurfaceW;
- testData.renderSurfaceH = gRenderSurfaceH;
- testData.dt = gDt;
- testData.user = 0;
- testData.user1 = useTexture ? 1 : 0;
- testData.user2 = numMeshes;
- rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData, sizeof(testData));
-}
+ fillSurfaceParams(&testData);
-static void displayCustomShaderSamples(int numMeshes) {
- TestData testData;
- testData.renderSurfaceW = gRenderSurfaceW;
- testData.renderSurfaceH = gRenderSurfaceH;
- testData.dt = gDt;
- testData.user = 1;
- testData.user1 = numMeshes;
- rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData, sizeof(testData));
+ rs_allocation null_alloc;
+ rsForEach(gTestScripts[index].testScript,
+ gTestScripts[index].testData,
+ null_alloc,
+ &testData,
+ sizeof(testData));
}
-static void displayPixelLightSamples(int numMeshes, bool heavyVertex) {
- TestData testData;
- testData.renderSurfaceW = gRenderSurfaceW;
- testData.renderSurfaceH = gRenderSurfaceH;
- testData.dt = gDt;
- testData.user = 2;
- testData.user1 = numMeshes;
- testData.user2 = heavyVertex ? 1 : 0;
- rsForEach(gTorusScript, gDummyAlloc, gDummyAlloc, &testData, sizeof(testData));
-}
-
-static void displayMultitextureSample(bool blend, int quadCount) {
- bindProgramVertexOrtho();
- rs_matrix4x4 matrix;
- rsMatrixLoadIdentity(&matrix);
- rsgProgramVertexLoadModelMatrix(&matrix);
-
- // Fragment shader with texture
- if (!blend) {
- rsgBindProgramStore(gProgStoreBlendNone);
- } else {
- rsgBindProgramStore(gProgStoreBlendAlpha);
- }
- rsgBindProgramFragment(gProgFragmentMultitex);
- rsgBindSampler(gProgFragmentMultitex, 0, gLinearClamp);
- rsgBindSampler(gProgFragmentMultitex, 1, gLinearWrap);
- rsgBindSampler(gProgFragmentMultitex, 2, gLinearClamp);
- rsgBindTexture(gProgFragmentMultitex, 0, gTexChecker);
- rsgBindTexture(gProgFragmentMultitex, 1, gTexTorus);
- rsgBindTexture(gProgFragmentMultitex, 2, gTexTransparent);
-
- for (int i = 0; i < quadCount; i ++) {
- float startX = 10 * i, startY = 10 * i;
- float width = gRenderSurfaceW - startX, height = gRenderSurfaceH - startY;
- rsgDrawQuadTexCoords(startX, startY, 0, 0, 0,
- startX, startY + height, 0, 0, 1,
- startX + width, startY + height, 0, 1, 1,
- startX + width, startY, 0, 1, 0);
- }
-}
static bool checkInit() {
- static int countdown = 5;
+ static int countdown = 3;
// Perform all the uploads so we only measure rendered time
if(countdown > 1) {
- displayFontSamples(5);
- displaySingletexFill(true, 3);
- displayMeshSamples(0);
- displayMeshSamples(1);
- displayMeshSamples(2);
- displayMultitextureSample(true, 5);
- displayPixelLightSamples(1, false);
- displayPixelLightSamples(1, true);
+ int testCount = rsAllocationGetDimX(rsGetAllocation(gTestScripts));
+ for(int i = 0; i < testCount; i ++) {
+ rsgClearColor(0.2f, 0.2f, 0.2f, 0.0f);
+ runSubTest(i);
+ rsgFinish();
+ }
countdown --;
rsgClearColor(0.2f, 0.2f, 0.2f, 0.0f);
@@ -606,43 +124,11 @@ static bool checkInit() {
}
static int benchMode = 0;
+static bool benchmarkSingleTest = false;
+static int benchSubMode = 0;
static int runningLoops = 0;
static bool sendMsgFlag = false;
-static const char *testNames[] = {
- "Fill screen with text 1 time",
- "Fill screen with text 3 times",
- "Fill screen with text 5 times",
- "Geo test 25.6k flat color",
- "Geo test 51.2k flat color",
- "Geo test 204.8k small tries flat color",
- "Geo test 25.6k single texture",
- "Geo test 51.2k single texture",
- "Geo test 204.8k small tries single texture",
- "Full screen mesh 10 by 10",
- "Full screen mesh 100 by 100",
- "Full screen mesh W / 4 by H / 4",
- "Geo test 25.6k geo heavy vertex",
- "Geo test 51.2k geo heavy vertex",
- "Geo test 204.8k geo raster load heavy vertex",
- "Fill screen 10x singletexture",
- "Fill screen 10x 3tex multitexture",
- "Fill screen 10x blended singletexture",
- "Fill screen 10x blended 3tex multitexture",
- "Geo test 25.6k heavy fragment",
- "Geo test 51.2k heavy fragment",
- "Geo test 204.8k small tries heavy fragment",
- "Geo test 25.6k heavy fragment heavy vertex",
- "Geo test 51.2k heavy fragment heavy vertex",
- "Geo test 204.8k small tries heavy fragment heavy vertex",
- "UI test with icon display 10 by 10",
- "UI test with icon display 100 by 100",
- "UI test with image and text display 3 pages",
- "UI test with image and text display 5 pages",
- "UI test with list view",
- "UI test with live wallpaper",
-};
-
static bool gIsDebugMode = false;
void setDebugMode(int testNumber) {
gIsDebugMode = true;
@@ -650,122 +136,17 @@ void setDebugMode(int testNumber) {
rsgClearAllRenderTargets();
}
-void setBenchmarkMode() {
+void setBenchmarkMode(int testNumber) {
gIsDebugMode = false;
- benchMode = 0;
- runningLoops = 0;
-}
-
-
-void getTestName(int testIndex) {
- int bufferLen = rsAllocationGetDimX(rsGetAllocation(gStringBuffer));
- if (testIndex >= gMaxModes) {
- return;
- }
- uint charIndex = 0;
- while (testNames[testIndex][charIndex] != '\0' && charIndex < bufferLen) {
- gStringBuffer[charIndex] = testNames[testIndex][charIndex];
- charIndex ++;
+ if (testNumber == -1) {
+ benchmarkSingleTest = false;
+ benchMode = 0;
+ } else {
+ benchmarkSingleTest = true;
+ benchMode = testNumber;
}
- gStringBuffer[charIndex] = '\0';
-}
-static void runTest(int index) {
- switch (index) {
- case 0:
- displayFontSamples(1);
- break;
- case 1:
- displayFontSamples(3);
- break;
- case 2:
- displayFontSamples(5);
- break;
- case 3:
- displaySimpleGeoSamples(false, 1);
- break;
- case 4:
- displaySimpleGeoSamples(false, 2);
- break;
- case 5:
- displaySimpleGeoSamples(false, 8);
- break;
- case 6:
- displaySimpleGeoSamples(true, 1);
- break;
- case 7:
- displaySimpleGeoSamples(true, 2);
- break;
- case 8:
- displaySimpleGeoSamples(true, 8);
- break;
- case 9:
- displayMeshSamples(0);
- break;
- case 10:
- displayMeshSamples(1);
- break;
- case 11:
- displayMeshSamples(2);
- break;
- case 12:
- displayCustomShaderSamples(1);
- break;
- case 13:
- displayCustomShaderSamples(2);
- break;
- case 14:
- displayCustomShaderSamples(10);
- break;
- case 15:
- displaySingletexFill(false, 10);
- break;
- case 16:
- displayMultitextureSample(false, 10);
- break;
- case 17:
- displaySingletexFill(true, 10);
- break;
- case 18:
- displayMultitextureSample(true, 10);
- break;
- case 19:
- displayPixelLightSamples(1, false);
- break;
- case 20:
- displayPixelLightSamples(2, false);
- break;
- case 21:
- displayPixelLightSamples(8, false);
- break;
- case 22:
- displayPixelLightSamples(1, true);
- break;
- case 23:
- displayPixelLightSamples(2, true);
- break;
- case 24:
- displayPixelLightSamples(8, true);
- break;
- case 25:
- displayIcons(0);
- break;
- case 26:
- displayIcons(1);
- break;
- case 27:
- displayImageWithText(7, 5, 0);
- break;
- case 28:
- displayImageWithText(7, 5, 1);
- break;
- case 29:
- displayListView();
- break;
- case 30:
- displayLiveWallPaper(7, 5);
- break;
- }
+ runningLoops = 0;
}
static void drawOffscreenResult(int posX, int posY, int width, int height) {
@@ -803,7 +184,7 @@ static void benchmark() {
rsgClearColor(0.1f, 0.1f, 0.1f, 1.0f);
rsgClearDepth(1.0f);
- runTest(benchMode);
+ runSubTest(benchMode);
rsgClearAllRenderTargets();
gRenderSurfaceW = rsgGetWidth();
gRenderSurfaceH = rsgGetHeight();
@@ -816,25 +197,34 @@ static void benchmark() {
int64_t end = rsUptimeMillis();
float fps = (float)(frameCount) / ((float)(end - start)*0.001f);
- rsDebug(testNames[benchMode], fps);
+ const char *testName = rsGetElementAt(gTestScripts[benchMode].debugName, 0);
+ rsDebug(testName, fps);
+
gResultBuffer[benchMode] = fps;
- drawOffscreenResult(0, 0,
- gRenderSurfaceW / 2,
- gRenderSurfaceH / 2);
- const char* text = testNames[benchMode];
+ int bufferW = rsAllocationGetDimX(gRenderBufferColor);
+ int bufferH = rsAllocationGetDimY(gRenderBufferColor);
+
+ int quadW = gRenderSurfaceW / 2;
+ int quadH = (quadW * bufferH) / bufferW;
+ drawOffscreenResult(0, 0, quadW, quadH);
+
int left = 0, right = 0, top = 0, bottom = 0;
uint width = rsgGetWidth();
uint height = rsgGetHeight();
rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f);
rsgBindFont(gFontSerif);
- rsgMeasureText(text, &left, &right, &top, &bottom);
+ rsgMeasureText(gTestScripts[benchMode].testName, &left, &right, &top, &bottom);
rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
- rsgDrawText(text, 2 -left, height - 2 + bottom);
+ rsgDrawText(gTestScripts[benchMode].testName, 2 -left, height - 2 + bottom);
- benchMode ++;
+ if (benchmarkSingleTest) {
+ return;
+ }
- if (benchMode == gMaxModes) {
- rsSendToClientBlocking(RS_MSG_RESULTS_READY, gResultBuffer, gMaxModes*sizeof(float));
+ benchMode ++;
+ int testCount = rsAllocationGetDimX(rsGetAllocation(gTestScripts));
+ if (benchMode == testCount) {
+ rsSendToClientBlocking(RS_MSG_RESULTS_READY, gResultBuffer, testCount*sizeof(float));
benchMode = 0;
runningLoops++;
if ((gMaxLoops > 0) && (runningLoops > gMaxLoops) && !sendMsgFlag) {
@@ -844,14 +234,11 @@ static void benchmark() {
sendMsgFlag = true;
}
}
-
}
static void debug() {
gDt = rsGetDt();
-
- rsgFinish();
- runTest(benchMode);
+ runSubTest(benchMode);
}
int root(void) {
@@ -859,10 +246,22 @@ int root(void) {
gRenderSurfaceH = rsgGetHeight();
rsgClearColor(0.2f, 0.2f, 0.2f, 1.0f);
rsgClearDepth(1.0f);
+
+ if (!gLoadComplete) {
+ rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f);
+ rsgBindFont(gFontSerif);
+ rsgDrawText("Loading", 50, 50);
+ return 0;
+ }
+
if(!checkInit()) {
return 1;
}
+ if (gPauseRendering) {
+ rsgDrawText("Paused", 50, 50);
+ return 30;
+ }
if (gIsDebugMode) {
debug();
} else {
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/subtest_def.rsh b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/subtest_def.rsh
index b635373..43658b1 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/subtest_def.rsh
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/subtest_def.rsh
@@ -20,9 +20,5 @@ typedef struct TestData_s {
int renderSurfaceW;
int renderSurfaceH;
float dt;
- int user;
- int user1;
- int user2;
- int user3;
} TestData;
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/text_test.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/text_test.rs
index 0df6b35..7f10019 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/text_test.rs
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/text_test.rs
@@ -22,6 +22,11 @@
rs_font gFontSans;
rs_font gFontSerif;
+typedef struct TextTestData_s {
+ int fillNum;
+} TextTestData;
+TextTestData *gData;
+
void init() {
}
@@ -78,5 +83,8 @@ void root(const void *v_in, void *v_out, const void *usrData, uint32_t x, uint32
TestData *testData = (TestData*)usrData;
gRenderSurfaceW = testData->renderSurfaceW;
gRenderSurfaceH = testData->renderSurfaceH;
- displayFontSamples(testData->user);
+
+ gData = (TextTestData*)v_in;
+
+ displayFontSamples(gData->fillNum);
}
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/torus_test.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/torus_test.rs
index 26d5680..853a05d 100644
--- a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/torus_test.rs
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/torus_test.rs
@@ -47,6 +47,13 @@ rs_program_vertex gProgVertexPixelLight;
rs_program_vertex gProgVertexPixelLightMove;
rs_program_fragment gProgFragmentPixelLight;
+typedef struct TorusTestData_s {
+ int testId;
+ int user1;
+ int user2;
+} TorusTestData;
+TorusTestData *gData;
+
static float gDt = 0.0f;
static int gRenderSurfaceW;
@@ -269,15 +276,20 @@ void root(const void *v_in, void *v_out, const void *usrData, uint32_t x, uint32
gRenderSurfaceH = testData->renderSurfaceH;
gDt = testData->dt;
- switch(testData->user) {
+ gData = (TorusTestData*)v_in;
+
+ switch(gData->testId) {
case 0:
- displaySimpleGeoSamples(testData->user1 == 1 ? true : false, testData->user2);
+ displaySimpleGeoSamples(gData->user1 == 1 ? true : false, gData->user2);
break;
case 1:
- displayCustomShaderSamples(testData->user1);
+ displayCustomShaderSamples(gData->user1);
break;
case 2:
- displayPixelLightSamples(testData->user1, testData->user2 == 1 ? true : false);
+ displayPixelLightSamples(gData->user1, gData->user2 == 1 ? true : false);
+ break;
+ default:
+ rsDebug("Wrong test number", gData->testId);
break;
}
}
diff --git a/tests/RenderScriptTests/PerfTest/src/com/android/perftest/ui_test.rs b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/ui_test.rs
new file mode 100644
index 0000000..5089092
--- /dev/null
+++ b/tests/RenderScriptTests/PerfTest/src/com/android/perftest/ui_test.rs
@@ -0,0 +1,444 @@
+// Copyright (C) 2011 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.perftest)
+
+#include "rs_graphics.rsh"
+#include "shader_def.rsh"
+#include "subtest_def.rsh"
+
+// Parameters for galaxy live wallpaper
+rs_allocation gTSpace;
+rs_allocation gTLight1;
+rs_allocation gTFlares;
+rs_mesh gParticlesMesh;
+
+rs_program_fragment gPFBackground;
+rs_program_fragment gPFStars;
+rs_program_vertex gPVStars;
+rs_program_vertex gPVBkProj;
+rs_program_store gPSLights;
+
+float gXOffset = 0.5f;
+
+#define ELLIPSE_RATIO 0.892f
+#define PI 3.1415f
+#define TWO_PI 6.283f
+#define ELLIPSE_TWIST 0.023333333f
+
+static float angle = 50.f;
+static int gOldWidth;
+static int gOldHeight;
+static int gWidth;
+static int gHeight;
+static float gSpeed[12000];
+static int gGalaxyRadius = 300;
+static rs_allocation gParticlesBuffer;
+
+typedef struct __attribute__((packed, aligned(4))) Particle {
+ uchar4 color;
+ float3 position;
+} Particle_t;
+Particle_t *Particles;
+
+typedef struct VpConsts {
+ rs_matrix4x4 Proj;
+ rs_matrix4x4 MVP;
+} VpConsts_t;
+VpConsts_t *vpConstants;
+// End of parameters for galaxy live wallpaper
+
+rs_program_vertex gProgVertex;
+rs_program_fragment gProgFragmentColor;
+rs_program_fragment gProgFragmentTexture;
+
+rs_program_store gProgStoreBlendAlpha;
+
+rs_allocation gTexOpaque;
+rs_allocation gTexTorus;
+rs_allocation gTexGlobe;
+
+typedef struct ListAllocs_s {
+ rs_allocation item;
+} ListAllocs;
+
+ListAllocs *gTexList100;
+ListAllocs *gSampleTextList100;
+ListAllocs *gListViewText;
+
+rs_mesh gSingleMesh;
+
+rs_font gFontSans;
+
+rs_sampler gLinearClamp;
+
+typedef struct UiTestData_s {
+ int testId;
+ int user1;
+ int user2;
+ int user3;
+} UiTestData;
+UiTestData *gData;
+
+static float gDt = 0;
+
+
+void init() {
+}
+
+static int gRenderSurfaceW;
+static int gRenderSurfaceH;
+
+static void bindProgramVertexOrtho() {
+ // Default vertex shader
+ rsgBindProgramVertex(gProgVertex);
+ // Setup the projection matrix
+ rs_matrix4x4 proj;
+ rsMatrixLoadOrtho(&proj, 0, gRenderSurfaceW, gRenderSurfaceH, 0, -500, 500);
+ rsgProgramVertexLoadProjectionMatrix(&proj);
+}
+
+/**
+ * Methods to draw the galaxy live wall paper
+ */
+static float mapf(float minStart, float minStop, float maxStart, float maxStop, float value) {
+ return maxStart + (maxStart - maxStop) * ((value - minStart) / (minStop - minStart));
+}
+
+/**
+ * Helper function to generate the stars.
+ */
+static float randomGauss() {
+ float x1;
+ float x2;
+ float w = 2.f;
+
+ while (w >= 1.0f) {
+ x1 = rsRand(2.0f) - 1.0f;
+ x2 = rsRand(2.0f) - 1.0f;
+ w = x1 * x1 + x2 * x2;
+ }
+
+ w = sqrt(-2.0f * log(w) / w);
+ return x1 * w;
+}
+
+/**
+ * Generates the properties for a given star.
+ */
+static void createParticle(Particle_t *part, int idx, float scale) {
+ float d = fabs(randomGauss()) * gGalaxyRadius * 0.5f + rsRand(64.0f);
+ float id = d / gGalaxyRadius;
+ float z = randomGauss() * 0.4f * (1.0f - id);
+ float p = -d * ELLIPSE_TWIST;
+
+ if (d < gGalaxyRadius * 0.33f) {
+ part->color.x = (uchar) (220 + id * 35);
+ part->color.y = 220;
+ part->color.z = 220;
+ } else {
+ part->color.x = 180;
+ part->color.y = 180;
+ part->color.z = (uchar) clamp(140.f + id * 115.f, 140.f, 255.f);
+ }
+ // Stash point size * 10 in Alpha
+ part->color.w = (uchar) (rsRand(1.2f, 2.1f) * 60);
+
+ if (d > gGalaxyRadius * 0.15f) {
+ z *= 0.6f * (1.0f - id);
+ } else {
+ z *= 0.72f;
+ }
+
+ // Map to the projection coordinates (viewport.x = -1.0 -> 1.0)
+ d = mapf(-4.0f, gGalaxyRadius + 4.0f, 0.0f, scale, d);
+
+ part->position.x = rsRand(TWO_PI);
+ part->position.y = d;
+ gSpeed[idx] = rsRand(0.0015f, 0.0025f) * (0.5f + (scale / d)) * 0.8f;
+
+ part->position.z = z / 5.0f;
+}
+
+/**
+ * Initialize all the starts, called from Java
+ */
+void initParticles() {
+ Particle_t *part = Particles;
+ float scale = gGalaxyRadius / (gWidth * 0.5f);
+ int count = rsAllocationGetDimX(gParticlesBuffer);
+ for (int i = 0; i < count; i ++) {
+ createParticle(part, i, scale);
+ part++;
+ }
+}
+
+static void drawSpace() {
+ rsgBindProgramFragment(gPFBackground);
+ rsgBindTexture(gPFBackground, 0, gTSpace);
+ rsgDrawQuadTexCoords(
+ 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
+ gWidth, 0.0f, 0.0f, 2.0f, 1.0f,
+ gWidth, gHeight, 0.0f, 2.0f, 0.0f,
+ 0.0f, gHeight, 0.0f, 0.0f, 0.0f);
+}
+
+static void drawLights() {
+ rsgBindProgramVertex(gPVBkProj);
+ rsgBindProgramFragment(gPFBackground);
+ rsgBindTexture(gPFBackground, 0, gTLight1);
+
+ float scale = 512.0f / gWidth;
+ float x = -scale - scale * 0.05f;
+ float y = -scale;
+
+ scale *= 2.0f;
+
+ rsgDrawQuad(x, y, 0.0f,
+ x + scale * 1.1f, y, 0.0f,
+ x + scale * 1.1f, y + scale, 0.0f,
+ x, y + scale, 0.0f);
+}
+
+static void drawParticles(float offset) {
+ float a = offset * angle;
+ float absoluteAngle = fabs(a);
+
+ rs_matrix4x4 matrix;
+ rsMatrixLoadTranslate(&matrix, 0.0f, 0.0f, 10.0f - 6.0f * absoluteAngle / 50.0f);
+ if (gHeight > gWidth) {
+ rsMatrixScale(&matrix, 6.6f, 6.0f, 1.0f);
+ } else {
+ rsMatrixScale(&matrix, 12.6f, 12.0f, 1.0f);
+ }
+ rsMatrixRotate(&matrix, absoluteAngle, 1.0f, 0.0f, 0.0f);
+ rsMatrixRotate(&matrix, a, 0.0f, 0.4f, 0.1f);
+ rsMatrixLoad(&vpConstants->MVP, &vpConstants->Proj);
+ rsMatrixMultiply(&vpConstants->MVP, &matrix);
+ rsgAllocationSyncAll(rsGetAllocation(vpConstants));
+
+ rsgBindProgramVertex(gPVStars);
+ rsgBindProgramFragment(gPFStars);
+ rsgBindProgramStore(gPSLights);
+ rsgBindTexture(gPFStars, 0, gTFlares);
+
+ Particle_t *vtx = Particles;
+ int count = rsAllocationGetDimX(gParticlesBuffer);
+ for (int i = 0; i < count; i++) {
+ vtx->position.x = vtx->position.x + gSpeed[i];
+ vtx++;
+ }
+
+ rsgDrawMesh(gParticlesMesh);
+}
+/* end of methods for drawing galaxy */
+
+// Display sample images in a mesh with different texture
+static void displayIcons(int meshMode) {
+ bindProgramVertexOrtho();
+
+ // Fragment shader with texture
+ rsgBindProgramStore(gProgStoreBlendAlpha);
+ rsgBindProgramFragment(gProgFragmentTexture);
+ rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
+ rsgBindTexture(gProgFragmentTexture, 0, gTexTorus);
+ rsgDrawQuadTexCoords(
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, gRenderSurfaceH, 0.0f, 0.0f, 1.0f,
+ gRenderSurfaceW, gRenderSurfaceH, 0.0f, 1.0f, 1.0f,
+ gRenderSurfaceW, 0.0f, 0.0f, 1.0f, 0.0f);
+
+ int meshCount = (int)pow(10.0f, (float)(meshMode + 1));
+
+ float wSize = gRenderSurfaceW/(float)meshCount;
+ float hSize = gRenderSurfaceH/(float)meshCount;
+ rs_matrix4x4 matrix;
+ rsMatrixLoadScale(&matrix, wSize, hSize, 1.0);
+
+ float yPos = 0;
+ float yPad = hSize / 2;
+ float xPad = wSize / 2;
+ for (int y = 0; y < meshCount; y++) {
+ yPos = y * hSize + yPad;
+ float xPos = 0;
+ for (int x = 0; x < meshCount; x++) {
+ xPos = x * wSize + xPad;
+ rs_matrix4x4 transMatrix;
+ rsMatrixLoadTranslate(&transMatrix, xPos, yPos, 0);
+ rsMatrixMultiply(&transMatrix, &matrix);
+ rsgProgramVertexLoadModelMatrix(&transMatrix);
+ int i = (x + y * meshCount) % 100;
+ rsgBindTexture(gProgFragmentTexture, 0, gTexList100[i].item);
+ rsgDrawMesh(gSingleMesh);
+ }
+ }
+}
+
+// Draw meshes in a single page with top left corner coordinates (xStart, yStart)
+static void drawMeshInPage(float xStart, float yStart, int wResolution, int hResolution) {
+ // Draw wResolution * hResolution meshes in one page
+ float wMargin = 100.0f;
+ float hMargin = 100.0f;
+ float xPad = 50.0f;
+ float yPad = 20.0f;
+ float size = 100.0f; // size of images
+
+ // font info
+ rs_font font = gFontSans;
+ rsgBindFont(font);
+ rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
+
+ // Measure text size
+ int left = 0, right = 0, top = 0, bottom = 0;
+ rsgMeasureText(gSampleTextList100[0].item, &left, &right, &top, &bottom);
+ float textHeight = (float)(top - bottom);
+ float textWidth = (float)(right - left);
+
+ rs_matrix4x4 matrix;
+ rsMatrixLoadScale(&matrix, size, size, 1.0);
+
+ for (int y = 0; y < hResolution; y++) {
+ float yPos = yStart + hMargin + y * size + y * yPad;
+ for (int x = 0; x < wResolution; x++) {
+ float xPos = xStart + wMargin + x * size + x * xPad;
+
+ rs_matrix4x4 transMatrix;
+ rsMatrixLoadTranslate(&transMatrix, xPos + size/2, yPos + size/2, 0);
+ rsMatrixMultiply(&transMatrix, &matrix); // scale the mesh
+ rsgProgramVertexLoadModelMatrix(&transMatrix);
+
+ int i = (y * wResolution + x) % 100;
+ rsgBindTexture(gProgFragmentTexture, 0, gTexList100[i].item);
+ rsgDrawMesh(gSingleMesh);
+ rsgDrawText(gSampleTextList100[i].item, xPos, yPos + size + yPad/2 + textHeight);
+ }
+ }
+}
+
+// Display both images and text as shown in launcher and homepage
+// meshMode will decide how many pages we draw
+// meshMode = 0: draw 3 pages of meshes
+// meshMode = 1: draw 5 pages of meshes
+static void displayImageWithText(int wResolution, int hResolution, int meshMode) {
+ bindProgramVertexOrtho();
+
+ // Fragment shader with texture
+ rsgBindProgramStore(gProgStoreBlendAlpha);
+ rsgBindProgramFragment(gProgFragmentTexture);
+ rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
+
+ drawMeshInPage(0, 0, wResolution, hResolution);
+ drawMeshInPage(-1.0f*gRenderSurfaceW, 0, wResolution, hResolution);
+ drawMeshInPage(1.0f*gRenderSurfaceW, 0, wResolution, hResolution);
+ if (meshMode == 1) {
+ // draw another two pages of meshes
+ drawMeshInPage(-2.0f*gRenderSurfaceW, 0, wResolution, hResolution);
+ drawMeshInPage(2.0f*gRenderSurfaceW, 0, wResolution, hResolution);
+ }
+}
+
+// Display a list of text as the list view
+static void displayListView() {
+ // set text color
+ rsgFontColor(0.9f, 0.9f, 0.9f, 1.0f);
+ rsgBindFont(gFontSans);
+
+ // get the size of the list
+ rs_allocation textAlloc;
+ textAlloc = rsGetAllocation(gListViewText);
+ int allocSize = rsAllocationGetDimX(textAlloc);
+
+ int listItemHeight = 80;
+ int yOffset = listItemHeight;
+
+ // set the color for the list divider
+ rsgBindProgramFragment(gProgFragmentColor);
+ rsgProgramFragmentConstantColor(gProgFragmentColor, 1.0, 1.0, 1.0, 1);
+
+ // draw the list with divider
+ for (int i = 0; i < allocSize; i++) {
+ if (yOffset - listItemHeight > gRenderSurfaceH) {
+ break;
+ }
+ rsgDrawRect(0, yOffset - 1, gRenderSurfaceW, yOffset, 0);
+ rsgDrawText(gListViewText[i].item, 20, yOffset - 10);
+ yOffset += listItemHeight;
+ }
+}
+
+static void drawGalaxy() {
+ rsgClearColor(0.f, 0.f, 0.f, 1.f);
+ gParticlesBuffer = rsGetAllocation(Particles);
+ rsgBindProgramFragment(gPFBackground);
+
+ gWidth = rsgGetWidth();
+ gHeight = rsgGetHeight();
+ if ((gWidth != gOldWidth) || (gHeight != gOldHeight)) {
+ initParticles();
+ gOldWidth = gWidth;
+ gOldHeight = gHeight;
+ }
+
+ float offset = mix(-1.0f, 1.0f, gXOffset);
+ drawSpace();
+ drawParticles(offset);
+ drawLights();
+}
+
+// Display images and text with live wallpaper in the background
+static void displayLiveWallPaper(int wResolution, int hResolution) {
+ bindProgramVertexOrtho();
+
+ drawGalaxy();
+
+ rsgBindProgramVertex(gProgVertex);
+ rsgBindProgramStore(gProgStoreBlendAlpha);
+ rsgBindProgramFragment(gProgFragmentTexture);
+ rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp);
+
+ drawMeshInPage(0, 0, wResolution, hResolution);
+ drawMeshInPage(-1.0f*gRenderSurfaceW, 0, wResolution, hResolution);
+ drawMeshInPage(1.0f*gRenderSurfaceW, 0, wResolution, hResolution);
+ drawMeshInPage(-2.0f*gRenderSurfaceW, 0, wResolution, hResolution);
+ drawMeshInPage(2.0f*gRenderSurfaceW, 0, wResolution, hResolution);
+}
+
+void root(const void *v_in, void *v_out, const void *usrData, uint32_t x, uint32_t y) {
+ TestData *testData = (TestData*)usrData;
+ gRenderSurfaceW = testData->renderSurfaceW;
+ gRenderSurfaceH = testData->renderSurfaceH;
+ gDt = testData->dt;
+
+ gData = (UiTestData*)v_in;
+
+ switch(gData->testId) {
+ case 0:
+ displayIcons(gData->user1);
+ break;
+ case 1:
+ displayImageWithText(gData->user1, gData->user2, gData->user3);
+ break;
+ case 2:
+ displayListView();
+ break;
+ case 3:
+ displayLiveWallPaper(gData->user1, gData->user2);
+ break;
+ default:
+ rsDebug("Wrong test number", 0);
+ break;
+ }
+}
diff --git a/tests/RenderScriptTests/ShadersTest/src/com/android/shaderstest/shaderstest.rs b/tests/RenderScriptTests/ShadersTest/src/com/android/shaderstest/shaderstest.rs
index 53f10f9..ae32e3a 100644
--- a/tests/RenderScriptTests/ShadersTest/src/com/android/shaderstest/shaderstest.rs
+++ b/tests/RenderScriptTests/ShadersTest/src/com/android/shaderstest/shaderstest.rs
@@ -57,6 +57,14 @@ static float gZoom;
static float gLastX;
static float gLastY;
+static float3 toFloat3(float x, float y, float z) {
+ float3 f;
+ f.x = x;
+ f.y = y;
+ f.z = z;
+ return f;
+}
+
void onActionDown(float x, float y) {
gLastX = x;
gLastY = y;
@@ -112,8 +120,8 @@ void updateMeshInfo() {
rsgMeshComputeBoundingBox(info->mMesh,
&minX, &minY, &minZ,
&maxX, &maxY, &maxZ);
- info->bBoxMin = (minX, minY, minZ);
- info->bBoxMax = (maxX, maxY, maxZ);
+ info->bBoxMin = toFloat3(minX, minY, minZ);
+ info->bBoxMax = toFloat3(maxX, maxY, maxZ);
gLookAt += (info->bBoxMin + info->bBoxMax)*0.5f;
}
gLookAt = gLookAt / (float)size;
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java
index c038478..2293678 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2011 The Android Open Source Project
+ * Copyright (C) 2008-2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -65,6 +65,7 @@ public class RSTestCore {
unitTests = new ArrayList<UnitTest>();
unitTests.add(new UT_primitives(this, mRes, mCtx));
+ unitTests.add(new UT_constant(this, mRes, mCtx));
unitTests.add(new UT_vector(this, mRes, mCtx));
unitTests.add(new UT_rsdebug(this, mRes, mCtx));
unitTests.add(new UT_rstime(this, mRes, mCtx));
@@ -72,6 +73,8 @@ public class RSTestCore {
unitTests.add(new UT_alloc(this, mRes, mCtx));
unitTests.add(new UT_refcount(this, mRes, mCtx));
unitTests.add(new UT_foreach(this, mRes, mCtx));
+ unitTests.add(new UT_atomic(this, mRes, mCtx));
+ unitTests.add(new UT_struct(this, mRes, mCtx));
unitTests.add(new UT_math(this, mRes, mCtx));
unitTests.add(new UT_fp_mad(this, mRes, mCtx));
/*
@@ -91,7 +94,7 @@ public class RSTestCore {
for (int i = 0; i < uta.length; i++) {
ScriptField_ListAllocs_s.Item listElem = new ScriptField_ListAllocs_s.Item();
listElem.text = Allocation.createFromString(mRS, uta[i].name, Allocation.USAGE_SCRIPT);
- listElem.result = uta[i].result;
+ listElem.result = uta[i].getResult();
mListAllocs.set(listElem, i, false);
uta[i].setItem(listElem);
}
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_atomic.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_atomic.java
new file mode 100644
index 0000000..267c5b2
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_atomic.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_atomic extends UnitTest {
+ private Resources mRes;
+
+ protected UT_atomic(RSTestCore rstc, Resources res, Context ctx) {
+ super(rstc, "Atomics", ctx);
+ mRes = res;
+ }
+
+ public void run() {
+ RenderScript pRS = RenderScript.create(mCtx);
+ ScriptC_atomic s = new ScriptC_atomic(pRS, mRes, R.raw.atomic);
+ pRS.setMessageHandler(mRsMessage);
+ s.invoke_atomic_test();
+ pRS.finish();
+ waitForMessage();
+ pRS.destroy();
+ }
+}
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_constant.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_constant.java
new file mode 100644
index 0000000..adda5a3
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_constant.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_constant extends UnitTest {
+ private Resources mRes;
+
+ protected UT_constant(RSTestCore rstc, Resources res, Context ctx) {
+ super(rstc, "Const", ctx);
+ mRes = res;
+ }
+
+ private void Assert(boolean b) {
+ if (!b) {
+ failTest();
+ }
+ }
+
+ public void run() {
+ Assert(ScriptC_constant.const_floatTest == 1.99f);
+ Assert(ScriptC_constant.const_doubleTest == 2.05);
+ Assert(ScriptC_constant.const_charTest == -8);
+ Assert(ScriptC_constant.const_shortTest == -16);
+ Assert(ScriptC_constant.const_intTest == -32);
+ Assert(ScriptC_constant.const_longTest == 17179869184l);
+ Assert(ScriptC_constant.const_longlongTest == 68719476736l);
+
+ Assert(ScriptC_constant.const_ucharTest == 8);
+ Assert(ScriptC_constant.const_ushortTest == 16);
+ Assert(ScriptC_constant.const_uintTest == 32);
+ Assert(ScriptC_constant.const_ulongTest == 4611686018427387904L);
+ Assert(ScriptC_constant.const_int64_tTest == -17179869184l);
+ Assert(ScriptC_constant.const_uint64_tTest == 117179869184l);
+
+ Assert(ScriptC_constant.const_boolTest == true);
+
+ passTest();
+ }
+}
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_primitives.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_primitives.java
index b7a65a5..18829c2 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_primitives.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_primitives.java
@@ -92,8 +92,7 @@ public class UT_primitives extends UnitTest {
ScriptC_primitives s = new ScriptC_primitives(pRS, mRes, R.raw.primitives);
pRS.setMessageHandler(mRsMessage);
if (!initializeGlobals(s)) {
- // initializeGlobals failed
- result = -1;
+ failTest();
} else {
s.invoke_primitives_test(0, 0);
pRS.finish();
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_rstime.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_rstime.java
index f302e1a..21e657c 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_rstime.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_rstime.java
@@ -32,6 +32,7 @@ public class UT_rstime extends UnitTest {
RenderScript pRS = RenderScript.create(mCtx);
ScriptC_rstime s = new ScriptC_rstime(pRS, mRes, R.raw.rstime);
pRS.setMessageHandler(mRsMessage);
+ s.setTimeZone("America/Los_Angeles");
s.invoke_test_rstime(0, 0);
pRS.finish();
waitForMessage();
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_struct.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_struct.java
new file mode 100644
index 0000000..2a55686
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_struct.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_struct extends UnitTest {
+ private Resources mRes;
+
+ protected UT_struct(RSTestCore rstc, Resources res, Context ctx) {
+ super(rstc, "Struct", ctx);
+ mRes = res;
+ }
+
+ public void run() {
+ RenderScript pRS = RenderScript.create(mCtx);
+ ScriptC_struct s = new ScriptC_struct(pRS, mRes, R.raw.struct);
+ pRS.setMessageHandler(mRsMessage);
+
+ ScriptField_Point2 p = new ScriptField_Point2(pRS, 1);
+ ScriptField_Point2.Item i = new ScriptField_Point2.Item();
+ int val = 100;
+ i.x = val;
+ i.y = val;
+ p.set(i, 0, true);
+ s.bind_point2(p);
+ s.invoke_struct_test(val);
+ pRS.finish();
+ waitForMessage();
+
+ val = 200;
+ p.set_x(0, val, true);
+ p.set_y(0, val, true);
+ s.invoke_struct_test(val);
+ pRS.finish();
+ waitForMessage();
+ pRS.destroy();
+ }
+}
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_vector.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_vector.java
index 748701d..0ac09ca 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_vector.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_vector.java
@@ -307,7 +307,7 @@ public class UT_vector extends UnitTest {
ScriptC_vector s = new ScriptC_vector(pRS, mRes, R.raw.vector);
pRS.setMessageHandler(mRsMessage);
if (!initializeGlobals(s)) {
- result = -1;
+ failTest();
} else {
s.invoke_vector_test();
pRS.finish();
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UnitTest.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UnitTest.java
index a97ffa7..edff83f 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UnitTest.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UnitTest.java
@@ -21,7 +21,7 @@ import android.renderscript.RenderScript.RSMessageHandler;
public class UnitTest extends Thread {
public String name;
- public int result;
+ private int result;
private ScriptField_ListAllocs_s.Item mItem;
private RSTestCore mRSTC;
private boolean msgHandled;
@@ -63,7 +63,7 @@ public class UnitTest extends Thread {
}
}
- protected void updateUI() {
+ private void updateUI() {
if (mItem != null) {
mItem.result = result;
msgHandled = true;
@@ -104,6 +104,22 @@ public class UnitTest extends Thread {
}
}
+ public int getResult() {
+ return result;
+ }
+
+ public void failTest() {
+ result = -1;
+ updateUI();
+ }
+
+ public void passTest() {
+ if (result != -1) {
+ result = 1;
+ }
+ updateUI();
+ }
+
public void setItem(ScriptField_ListAllocs_s.Item item) {
mItem = item;
}
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/atomic.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/atomic.rs
new file mode 100644
index 0000000..f0a5041
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/atomic.rs
@@ -0,0 +1,77 @@
+#include "shared.rsh"
+
+// Testing atomic operations
+static bool testUMax(uint32_t dst, uint32_t src) {
+ bool failed = false;
+ uint32_t old = dst;
+ uint32_t expect = (dst > src ? dst : src);
+ uint32_t ret = rsAtomicMax(&dst, src);
+ _RS_ASSERT(old == ret);
+ _RS_ASSERT(dst == expect);
+ return failed;
+}
+
+static bool testUMin(uint32_t dst, uint32_t src) {
+ bool failed = false;
+ uint32_t old = dst;
+ uint32_t expect = (dst < src ? dst : src);
+ uint32_t ret = rsAtomicMin(&dst, src);
+ _RS_ASSERT(old == ret);
+ _RS_ASSERT(dst == expect);
+ return failed;
+}
+
+static bool testUCas(uint32_t dst, uint32_t cmp, uint32_t swp) {
+ bool failed = false;
+ uint32_t old = dst;
+ uint32_t expect = (dst == cmp ? swp : dst);
+ uint32_t ret = rsAtomicCas(&dst, cmp, swp);
+ _RS_ASSERT(old == ret);
+ _RS_ASSERT(dst == expect);
+ return failed;
+}
+
+static bool test_atomics() {
+ bool failed = false;
+
+ failed |= testUMax(5, 6);
+ failed |= testUMax(6, 5);
+ failed |= testUMax(5, 0xf0000006);
+ failed |= testUMax(0xf0000006, 5);
+
+ failed |= testUMin(5, 6);
+ failed |= testUMin(6, 5);
+ failed |= testUMin(5, 0xf0000006);
+ failed |= testUMin(0xf0000006, 5);
+
+ failed |= testUCas(4, 4, 5);
+ failed |= testUCas(4, 5, 5);
+ failed |= testUCas(5, 5, 4);
+ failed |= testUCas(5, 4, 4);
+ failed |= testUCas(0xf0000004, 0xf0000004, 0xf0000005);
+ failed |= testUCas(0xf0000004, 0xf0000005, 0xf0000005);
+ failed |= testUCas(0xf0000005, 0xf0000005, 0xf0000004);
+ failed |= testUCas(0xf0000005, 0xf0000004, 0xf0000004);
+
+ if (failed) {
+ rsDebug("test_atomics FAILED", 0);
+ }
+ else {
+ rsDebug("test_atomics PASSED", 0);
+ }
+
+ return failed;
+}
+
+void atomic_test() {
+ bool failed = false;
+ failed |= test_atomics();
+
+ if (failed) {
+ rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+ }
+ else {
+ rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+ }
+}
+
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/constant.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/constant.rs
new file mode 100644
index 0000000..732eaef
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/constant.rs
@@ -0,0 +1,19 @@
+#include "shared.rsh"
+
+const float floatTest = 1.99f;
+const double doubleTest = 2.05;
+const char charTest = -8;
+const short shortTest = -16;
+const int intTest = -32;
+const long longTest = 17179869184l; // 1 << 34
+const long long longlongTest = 68719476736l; // 1 << 36
+
+const uchar ucharTest = 8;
+const ushort ushortTest = 16;
+const uint uintTest = 32;
+const ulong ulongTest = 4611686018427387904L;
+const int64_t int64_tTest = -17179869184l; // - 1 << 34
+const uint64_t uint64_tTest = 117179869184l;
+
+const bool boolTest = true;
+
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/rstime.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/rstime.rs
index 5e3e078..7be955d 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/rstime.rs
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/rstime.rs
@@ -19,7 +19,7 @@ static bool basic_test(uint32_t index) {
rsDebug("tm.tm_yday", tm.tm_yday);
rsDebug("tm.tm_isdst", tm.tm_isdst);
- // Test a specific time (only valid for PST localtime)
+ // Test a specific time (since we set America/Los_Angeles localtime)
curTime = 1294438893;
rsLocaltime(&tm, &curTime);
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/struct.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/struct.rs
new file mode 100644
index 0000000..1cd728e
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/struct.rs
@@ -0,0 +1,37 @@
+#include "shared.rsh"
+
+typedef struct Point2 {
+ int x;
+ int y;
+} Point_2;
+Point_2 *point2;
+
+static bool test_Point_2(int expected) {
+ bool failed = false;
+
+ rsDebug("Point: ", point2[0].x, point2[0].y);
+ _RS_ASSERT(point2[0].x == expected);
+ _RS_ASSERT(point2[0].y == expected);
+
+ if (failed) {
+ rsDebug("test_Point_2 FAILED", 0);
+ }
+ else {
+ rsDebug("test_Point_2 PASSED", 0);
+ }
+
+ return failed;
+}
+
+void struct_test(int expected) {
+ bool failed = false;
+ failed |= test_Point_2(expected);
+
+ if (failed) {
+ rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+ }
+ else {
+ rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+ }
+}
+
diff --git a/tests/TileBenchmark/Android.mk b/tests/TileBenchmark/Android.mk
index 430f0f1..5851113 100644
--- a/tests/TileBenchmark/Android.mk
+++ b/tests/TileBenchmark/Android.mk
@@ -21,12 +21,8 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := TileBenchmark
-include $(BUILD_PACKAGE)
+LOCAL_MODULE_TAGS := tests
-##################################################
-include $(CLEAR_VARS)
-
-include $(BUILD_MULTI_PREBUILT)
+LOCAL_JAVA_LIBRARIES := android.test.runner
-# Use the folloing include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH))
+include $(BUILD_PACKAGE) \ No newline at end of file
diff --git a/tests/TileBenchmark/AndroidManifest.xml b/tests/TileBenchmark/AndroidManifest.xml
index ab61a9e..f125c70 100644
--- a/tests/TileBenchmark/AndroidManifest.xml
+++ b/tests/TileBenchmark/AndroidManifest.xml
@@ -18,5 +18,9 @@
android:label="@string/playback_activity"
android:theme="@android:style/Theme.Holo.NoActionBar">
</activity>
+ <uses-library android:name="android.test.runner" />
</application>
+ <instrumentation android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.test.tilebenchmark"
+ android:label="Tests for WebView Tiles."/>
</manifest>
diff --git a/tests/TileBenchmark/res/layout/main.xml b/tests/TileBenchmark/res/layout/main.xml
index 577c466..1b39d5d 100644
--- a/tests/TileBenchmark/res/layout/main.xml
+++ b/tests/TileBenchmark/res/layout/main.xml
@@ -18,46 +18,52 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
>
- <LinearLayout
- android:id="@+id/top"
- android:layout_width="match_parent"
+ <HorizontalScrollView
+ android:id="@+id/horizontalScrollView"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
- <Spinner
- android:id="@+id/movement"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:prompt="@string/movement_method"
- />
- <Spinner
- android:id="@+id/velocity"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="center_horizontal"
- android:prompt="@string/desired_scroll_velocity"
- />
- <ToggleButton
- android:id="@+id/capture"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textOn="@string/capture_stop"
- android:textOff="@string/capture_start"
- />
- <EditText
- android:id="@+id/url"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:inputType="textUri"
- android:imeOptions="actionGo"
- android:layout_weight="1"
- />
- <Button
- android:id="@+id/inspect"
- android:layout_width="wrap_content"
+ <LinearLayout
+ android:id="@+id/top"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/inspect_log"
- />
- </LinearLayout>
+ >
+ <Spinner
+ android:id="@+id/movement"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:prompt="@string/movement_method"
+ />
+ <Spinner
+ android:id="@+id/velocity"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:prompt="@string/desired_scroll_velocity"
+ />
+ <ToggleButton
+ android:id="@+id/capture"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textOn="@string/capture_stop"
+ android:textOff="@string/capture_start"
+ />
+ <EditText
+ android:id="@+id/url"
+ android:layout_width="400dp"
+ android:layout_height="wrap_content"
+ android:inputType="textUri"
+ android:imeOptions="actionGo|flagNoExtractUi"
+ android:layout_weight="1"
+ />
+ <Button
+ android:id="@+id/inspect"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/inspect_log"
+ />
+ </LinearLayout>
+ </HorizontalScrollView>
<com.test.tilebenchmark.ProfiledWebView
android:id="@+id/web"
android:layout_width="match_parent"
diff --git a/tests/TileBenchmark/res/values/strings.xml b/tests/TileBenchmark/res/values/strings.xml
index 5af52dc..6c7055b 100644
--- a/tests/TileBenchmark/res/values/strings.xml
+++ b/tests/TileBenchmark/res/values/strings.xml
@@ -49,8 +49,9 @@
<!-- Drop down menu entry - automatically scroll to the end of the page
with scrollBy() [CHAR LIMIT=15] -->
<string name="movement_auto_scroll">Auto-scroll</string>
- <!-- Drop down menu entry - [CHAR LIMIT=15] -->
- <string name="movement_auto_fling">Auto-fling</string>
+ <!-- Drop down menu entry - automatically record for a set time before
+ stopping [CHAR LIMIT=15] -->
+ <string name="movement_timed">Timed</string>
<!-- Drop down menu entry - manually navigate the page(s), hit 'capture'
button [CHAR LIMIT=15] -->
<string name="movement_manual">Manual</string>
@@ -67,14 +68,21 @@
<!-- 75th percentile - 75% of frames fall below this value [CHAR LIMIT=12]
-->
<string name="percentile_75">75%ile</string>
+ <!-- standard deviation [CHAR LIMIT=12] -->
+ <string name="std_dev">StdDev</string>
+ <!-- mean [CHAR LIMIT=12] -->
+ <string name="mean">mean</string>
+
+
+
<!-- Frame rate [CHAR LIMIT=15] -->
<string name="frames_per_second">Frames/sec</string>
<!-- Portion of viewport covered by good tiles [CHAR LIMIT=15] -->
<string name="viewport_coverage">Coverage</string>
<!-- Milliseconds taken to inval, and re-render the page [CHAR LIMIT=15] -->
<string name="render_millis">RenderMillis</string>
- <!-- Number of rendering stalls while running the test [CHAR LIMIT=15] -->
- <string name="render_stalls">Stalls</string>
+ <!-- Animation Framerate [CHAR LIMIT=15] -->
+ <string name="animation_framerate">AnimFramerate</string>
<!-- Format string for stat value overlay [CHAR LIMIT=15] -->
<string name="format_stat">%4.4f</string>
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/PerformanceTest.java b/tests/TileBenchmark/src/com/test/tilebenchmark/PerformanceTest.java
new file mode 100644
index 0000000..6356cc1
--- /dev/null
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/PerformanceTest.java
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.test.tilebenchmark;
+
+import com.test.tilebenchmark.ProfileActivity.ProfileCallback;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.os.Environment;
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
+import android.webkit.WebSettings;
+import android.widget.Spinner;
+
+public class PerformanceTest extends
+ ActivityInstrumentationTestCase2<ProfileActivity> {
+
+ public static class AnimStat {
+ double aggVal = 0;
+ double aggSqrVal = 0;
+ double count = 0;
+ }
+
+ private class StatAggregator extends PlaybackGraphs {
+ private HashMap<String, Double> mDataMap = new HashMap<String, Double>();
+ private HashMap<String, AnimStat> mAnimDataMap = new HashMap<String, AnimStat>();
+ private int mCount = 0;
+
+
+ public void aggregate() {
+ boolean inAnimTests = mAnimTests != null;
+ Resources resources = mWeb.getResources();
+ String animFramerateString = resources.getString(R.string.animation_framerate);
+ for (Map.Entry<String, Double> e : mSingleStats.entrySet()) {
+ String name = e.getKey();
+ if (inAnimTests) {
+ if (name.equals(animFramerateString)) {
+ // in animation testing phase, record animation framerate and aggregate
+ // stats, differentiating on values of mAnimTestNr and mDoubleBuffering
+ String fullName = ANIM_TEST_NAMES[mAnimTestNr] + " " + name;
+ fullName += mDoubleBuffering ? " tiled" : " webkit";
+
+ if (!mAnimDataMap.containsKey(fullName)) {
+ mAnimDataMap.put(fullName, new AnimStat());
+ }
+ AnimStat statVals = mAnimDataMap.get(fullName);
+ statVals.aggVal += e.getValue();
+ statVals.aggSqrVal += e.getValue() * e.getValue();
+ statVals.count += 1;
+ }
+ } else {
+ double aggVal = mDataMap.containsKey(name)
+ ? mDataMap.get(name) : 0;
+ mDataMap.put(name, aggVal + e.getValue());
+ }
+ }
+
+ if (inAnimTests) {
+ return;
+ }
+
+ mCount++;
+ for (int metricIndex = 0; metricIndex < Metrics.length; metricIndex++) {
+ for (int statIndex = 0; statIndex < Stats.length; statIndex++) {
+ String metricLabel = resources.getString(
+ Metrics[metricIndex].getLabelId());
+ String statLabel = resources.getString(
+ Stats[statIndex].getLabelId());
+
+ String label = metricLabel + " " + statLabel;
+ double aggVal = mDataMap.containsKey(label) ? mDataMap
+ .get(label) : 0;
+
+ aggVal += mStats[metricIndex][statIndex];
+ mDataMap.put(label, aggVal);
+ }
+ }
+
+ }
+
+ // build the final bundle of results
+ public Bundle getBundle() {
+ Bundle b = new Bundle();
+ int count = (0 == mCount) ? Integer.MAX_VALUE : mCount;
+ for (Map.Entry<String, Double> e : mDataMap.entrySet()) {
+ b.putDouble(e.getKey(), e.getValue() / count);
+ }
+
+ for (Map.Entry<String, AnimStat> e : mAnimDataMap.entrySet()) {
+ String statName = e.getKey();
+ AnimStat statVals = e.getValue();
+
+ double avg = statVals.aggVal/statVals.count;
+ double stdDev = Math.sqrt((statVals.aggSqrVal / statVals.count) - avg * avg);
+
+ b.putDouble(statName, avg);
+ b.putDouble(statName + " STD DEV", stdDev);
+ }
+
+ return b;
+ }
+ }
+
+ ProfileActivity mActivity;
+ ProfiledWebView mWeb;
+ Spinner mMovementSpinner;
+ StatAggregator mStats;
+
+ private static final String LOGTAG = "PerformanceTest";
+ private static final String TEST_LOCATION = "webkit/page_cycler";
+ private static final String URL_PREFIX = "file://";
+ private static final String URL_POSTFIX = "/index.html?skip=true";
+ private static final int MAX_ITERATIONS = 4;
+ private static final String SCROLL_TEST_DIRS[] = {
+ "alexa25_2011"
+ };
+ private static final String ANIM_TEST_DIRS[] = {
+ "dhtml"
+ };
+
+ public PerformanceTest() {
+ super(ProfileActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mActivity = getActivity();
+ mWeb = (ProfiledWebView) mActivity.findViewById(R.id.web);
+ mMovementSpinner = (Spinner) mActivity.findViewById(R.id.movement);
+ mStats = new StatAggregator();
+
+ // use mStats as a condition variable between the UI thread and
+ // this(the testing) thread
+ mActivity.setCallback(new ProfileCallback() {
+ @Override
+ public void profileCallback(RunData data) {
+ mStats.setData(data);
+ synchronized (mStats) {
+ mStats.notify();
+ }
+ }
+ });
+
+ }
+
+ private boolean loadUrl(final String url) {
+ try {
+ Log.d(LOGTAG, "test starting for url " + url);
+ mActivity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mWeb.loadUrl(url);
+ }
+ });
+ synchronized (mStats) {
+ mStats.wait();
+ }
+
+ mStats.aggregate();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ return false;
+ }
+ return true;
+ }
+
+ private boolean validTest(String nextTest) {
+ // if testing animations, test must be in mAnimTests
+ if (mAnimTests == null)
+ return true;
+
+ for (String test : mAnimTests) {
+ if (test.equals(nextTest)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean runIteration(String[] testDirs) {
+ File sdFile = Environment.getExternalStorageDirectory();
+ for (String testDirName : testDirs) {
+ File testDir = new File(sdFile, TEST_LOCATION + "/" + testDirName);
+ Log.d(LOGTAG, "Testing dir: '" + testDir.getAbsolutePath()
+ + "', exists=" + testDir.exists());
+
+ for (File siteDir : testDir.listFiles()) {
+ if (!siteDir.isDirectory() || !validTest(siteDir.getName())) {
+ continue;
+ }
+
+ if (!loadUrl(URL_PREFIX + siteDir.getAbsolutePath()
+ + URL_POSTFIX)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private boolean runTestDirs(String[] testDirs) {
+ for (int i = 0; i < MAX_ITERATIONS; i++)
+ if (!runIteration(testDirs)) {
+ return false;
+ }
+ return true;
+ }
+
+ private void pushDoubleBuffering() {
+ getInstrumentation().runOnMainSync(new Runnable() {
+ public void run() {
+ mWeb.setDoubleBuffering(mDoubleBuffering);
+ }
+ });
+ }
+
+ private void setScrollingTestingMode(final boolean scrolled) {
+ getInstrumentation().runOnMainSync(new Runnable() {
+ public void run() {
+ mMovementSpinner.setSelection(scrolled ? 0 : 2);
+ }
+ });
+ }
+
+
+ private String[] mAnimTests = null;
+ private int mAnimTestNr = -1;
+ private boolean mDoubleBuffering = true;
+ private static final String[] ANIM_TEST_NAMES = {
+ "slow", "fast"
+ };
+ private static final String[][] ANIM_TESTS = {
+ {"scrolling", "replaceimages", "layers5", "layers1"},
+ {"slidingballs", "meter", "slidein", "fadespacing", "colorfade",
+ "mozilla", "movingtext", "diagball", "zoom", "imageslide"},
+ };
+
+ private boolean checkMedia() {
+ String state = Environment.getExternalStorageState();
+
+ if (!Environment.MEDIA_MOUNTED.equals(state)
+ && !Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
+ Log.d(LOGTAG, "ARG Can't access sd card!");
+ // Can't read the SD card, fail and die!
+ getInstrumentation().sendStatus(1, null);
+ return false;
+ }
+ return true;
+ }
+
+ public void testMetrics() {
+ setScrollingTestingMode(true);
+ if (checkMedia() && runTestDirs(SCROLL_TEST_DIRS)) {
+ getInstrumentation().sendStatus(0, mStats.getBundle());
+ } else {
+ getInstrumentation().sendStatus(1, null);
+ }
+ }
+
+ private boolean runAnimationTests() {
+ for (int doubleBuffer = 0; doubleBuffer <= 1; doubleBuffer++) {
+ mDoubleBuffering = doubleBuffer == 1;
+ pushDoubleBuffering();
+ for (mAnimTestNr = 0; mAnimTestNr < ANIM_TESTS.length; mAnimTestNr++) {
+ mAnimTests = ANIM_TESTS[mAnimTestNr];
+ if (!runTestDirs(ANIM_TEST_DIRS)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ public void testAnimations() {
+ // instead of autoscrolling, load each page until either an timer fires,
+ // or the animation signals complete via javascript
+ setScrollingTestingMode(false);
+
+ if (checkMedia() && runAnimationTests()) {
+ getInstrumentation().sendStatus(0, mStats.getBundle());
+ } else {
+ getInstrumentation().sendStatus(1, null);
+ }
+ }
+}
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackGraphs.java b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackGraphs.java
index 9ea90f8..a3ae9be 100644
--- a/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackGraphs.java
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackGraphs.java
@@ -80,7 +80,7 @@ public class PlaybackGraphs {
for (int tileID = 1; tileID < frame.length; tileID++) {
TileData data = frame[tileID];
double coverage = viewportCoverage(frame[0], data);
- total += coverage * (data.isReady ? 1 : 0);
+ total += coverage * (data.isReady ? 100 : 0);
totalCount += coverage;
}
if (totalCount == 0) {
@@ -91,7 +91,7 @@ public class PlaybackGraphs {
@Override
public double getMax() {
- return 1;
+ return 100;
}
@Override
@@ -108,6 +108,9 @@ public class PlaybackGraphs {
}
public static double getPercentile(double sortedValues[], double ratioAbove) {
+ if (sortedValues.length == 0)
+ return -1;
+
double index = ratioAbove * (sortedValues.length - 1);
int intIndex = (int) Math.floor(index);
if (index == intIndex) {
@@ -118,6 +121,31 @@ public class PlaybackGraphs {
+ sortedValues[intIndex + 1] * (alpha);
}
+ public static double getMean(double sortedValues[]) {
+ if (sortedValues.length == 0)
+ return -1;
+
+ double agg = 0;
+ for (double val : sortedValues) {
+ agg += val;
+ }
+ return agg / sortedValues.length;
+ }
+
+ public static double getStdDev(double sortedValues[]) {
+ if (sortedValues.length == 0)
+ return -1;
+
+ double agg = 0;
+ double sqrAgg = 0;
+ for (double val : sortedValues) {
+ agg += val;
+ sqrAgg += val*val;
+ }
+ double mean = agg / sortedValues.length;
+ return Math.sqrt((sqrAgg / sortedValues.length) - (mean * mean));
+ }
+
protected static StatGen[] Stats = new StatGen[] {
new StatGen() {
@Override
@@ -149,6 +177,26 @@ public class PlaybackGraphs {
public int getLabelId() {
return R.string.percentile_75;
}
+ }, new StatGen() {
+ @Override
+ public double getValue(double[] sortedValues) {
+ return getStdDev(sortedValues);
+ }
+
+ @Override
+ public int getLabelId() {
+ return R.string.std_dev;
+ }
+ }, new StatGen() {
+ @Override
+ public double getValue(double[] sortedValues) {
+ return getMean(sortedValues);
+ }
+
+ @Override
+ public int getLabelId() {
+ return R.string.mean;
+ }
},
};
@@ -159,40 +207,47 @@ public class PlaybackGraphs {
}
private ArrayList<ShapeDrawable> mShapes = new ArrayList<ShapeDrawable>();
- protected double[][] mStats = new double[Metrics.length][Stats.length];
+ protected final double[][] mStats = new double[Metrics.length][Stats.length];
protected HashMap<String, Double> mSingleStats;
+ private void gatherFrameMetric(int metricIndex, double metricValues[], RunData data) {
+ // create graph out of rectangles, one per frame
+ int lastBar = 0;
+ for (int frameIndex = 0; frameIndex < data.frames.length; frameIndex++) {
+ TileData frame[] = data.frames[frameIndex];
+ int newBar = (frame[0].top + frame[0].bottom) / 2;
+
+ MetricGen s = Metrics[metricIndex];
+ double absoluteValue = s.getValue(frame);
+ double relativeValue = absoluteValue / s.getMax();
+ relativeValue = Math.min(1,relativeValue);
+ relativeValue = Math.max(0,relativeValue);
+ int rightPos = (int) (-BAR_WIDTH * metricIndex);
+ int leftPos = (int) (-BAR_WIDTH * (metricIndex + relativeValue));
+
+ ShapeDrawable graphBar = new ShapeDrawable();
+ graphBar.getPaint().setColor(Color.BLUE);
+ graphBar.setBounds(leftPos, lastBar, rightPos, newBar);
+
+ mShapes.add(graphBar);
+ metricValues[frameIndex] = absoluteValue;
+ lastBar = newBar;
+ }
+ }
+
public void setData(RunData data) {
mShapes.clear();
double metricValues[] = new double[data.frames.length];
+ mSingleStats = data.singleStats;
+
if (data.frames.length == 0) {
return;
}
for (int metricIndex = 0; metricIndex < Metrics.length; metricIndex++) {
- // create graph out of rectangles, one per frame
- int lastBar = 0;
- for (int frameIndex = 0; frameIndex < data.frames.length; frameIndex++) {
- TileData frame[] = data.frames[frameIndex];
- int newBar = (frame[0].top + frame[0].bottom) / 2;
-
- MetricGen s = Metrics[metricIndex];
- double absoluteValue = s.getValue(frame);
- double relativeValue = absoluteValue / s.getMax();
- relativeValue = Math.min(1,relativeValue);
- relativeValue = Math.max(0,relativeValue);
- int rightPos = (int) (-BAR_WIDTH * metricIndex);
- int leftPos = (int) (-BAR_WIDTH * (metricIndex + relativeValue));
-
- ShapeDrawable graphBar = new ShapeDrawable();
- graphBar.getPaint().setColor(Color.BLUE);
- graphBar.setBounds(leftPos, lastBar, rightPos, newBar);
-
- mShapes.add(graphBar);
- metricValues[frameIndex] = absoluteValue;
- lastBar = newBar;
- }
+ // calculate metric based on list of frames
+ gatherFrameMetric(metricIndex, metricValues, data);
// store aggregate statistics per metric (median, and similar)
Arrays.sort(metricValues);
@@ -200,8 +255,6 @@ public class PlaybackGraphs {
mStats[metricIndex][statIndex] =
Stats[statIndex].getValue(metricValues);
}
-
- mSingleStats = data.singleStats;
}
}
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfileActivity.java b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfileActivity.java
index e7a21ad..2e77157 100644
--- a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfileActivity.java
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfileActivity.java
@@ -22,11 +22,12 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.CountDownTimer;
+import android.util.Log;
import android.util.Pair;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
-import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.AdapterView;
@@ -49,6 +50,8 @@ import java.io.ObjectOutputStream;
*/
public class ProfileActivity extends Activity {
+ private static final int TIMED_RECORD_MILLIS = 2000;
+
public interface ProfileCallback {
public void profileCallback(RunData data);
}
@@ -65,6 +68,7 @@ public class ProfileActivity extends Activity {
LoggingWebViewClient mLoggingWebViewClient = new LoggingWebViewClient();
AutoLoggingWebViewClient mAutoLoggingWebViewClient = new AutoLoggingWebViewClient();
+ TimedLoggingWebViewClient mTimedLoggingWebViewClient = new TimedLoggingWebViewClient();
private enum TestingState {
NOT_TESTING,
@@ -93,18 +97,18 @@ public class ProfileActivity extends Activity {
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
String movementStr = parent.getItemAtPosition(position).toString();
- if (movementStr == getResources().getString(
- R.string.movement_auto_scroll)
- || movementStr == getResources().getString(
- R.string.movement_auto_fling)) {
+ if (movementStr == getResources().getString(R.string.movement_auto_scroll)) {
mWeb.setWebViewClient(mAutoLoggingWebViewClient);
mCaptureButton.setEnabled(false);
mVelocitySpinner.setEnabled(true);
- } else if (movementStr == getResources().getString(
- R.string.movement_manual)) {
+ } else if (movementStr == getResources().getString(R.string.movement_manual)) {
mWeb.setWebViewClient(mLoggingWebViewClient);
mCaptureButton.setEnabled(true);
mVelocitySpinner.setEnabled(false);
+ } else if (movementStr == getResources().getString(R.string.movement_timed)) {
+ mWeb.setWebViewClient(mTimedLoggingWebViewClient);
+ mCaptureButton.setEnabled(false);
+ mVelocitySpinner.setEnabled(false);
}
}
@@ -124,16 +128,46 @@ public class ProfileActivity extends Activity {
super.onPageStarted(view, url, favicon);
mUrl.setText(url);
}
+
+ @Override
+ public void onPageFinished(WebView view, String url) {
+ super.onPageFinished(view, url);
+ view.requestFocus();
+ ((ProfiledWebView)view).onPageFinished();
+ }
}
private class AutoLoggingWebViewClient extends LoggingWebViewClient {
+ @Override
+ public void onPageFinished(WebView view, String url) {
+ super.onPageFinished(view, url);
+ startViewProfiling(true);
+ }
@Override
+ public void onPageStarted(WebView view, String url, Bitmap favicon) {
+ super.onPageStarted(view, url, favicon);
+ setTestingState(TestingState.PRE_TESTING);
+ }
+ }
+
+ private class TimedLoggingWebViewClient extends LoggingWebViewClient {
+ @Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
- view.requestFocus();
+ startViewProfiling(false);
- startViewProfiling(true);
+ // after a fixed time after page finished, stop testing
+ new CountDownTimer(TIMED_RECORD_MILLIS, TIMED_RECORD_MILLIS) {
+ @Override
+ public void onTick(long millisUntilFinished) {
+ }
+
+ @Override
+ public void onFinish() {
+ mWeb.stopScrollTest();
+ }
+ }.start();
}
@Override
@@ -178,11 +212,13 @@ public class ProfileActivity extends Activity {
mMovementSpinner.setEnabled(false);
break;
case START_TESTING:
+ mCaptureButton.setChecked(true);
mUrl.setBackgroundResource(R.color.background_start_testing);
mInspectButton.setEnabled(false);
mMovementSpinner.setEnabled(false);
break;
case STOP_TESTING:
+ mCaptureButton.setChecked(false);
mUrl.setBackgroundResource(R.color.background_stop_testing);
break;
case SAVED_TESTING:
@@ -195,7 +231,6 @@ public class ProfileActivity extends Activity {
/** auto - automatically scroll. */
private void startViewProfiling(boolean auto) {
// toggle capture button to indicate capture state to user
- mCaptureButton.setChecked(true);
mWeb.startScrollTest(mCallback, auto);
setTestingState(TestingState.START_TESTING);
}
@@ -217,7 +252,7 @@ public class ProfileActivity extends Activity {
public void profileCallback(RunData data) {
new StoreFileTask().execute(new Pair<String, RunData>(
TEMP_FILENAME, data));
- mCaptureButton.setChecked(false);
+ Log.d("ProfileActivity", "stored " + data.frames.length + " frames in file");
setTestingState(TestingState.STOP_TESTING);
}
});
@@ -245,8 +280,8 @@ public class ProfileActivity extends Activity {
// Movement spinner
String content[] = {
getResources().getString(R.string.movement_auto_scroll),
- getResources().getString(R.string.movement_auto_fling),
- getResources().getString(R.string.movement_manual)
+ getResources().getString(R.string.movement_manual),
+ getResources().getString(R.string.movement_timed)
};
adapter = new ArrayAdapter<CharSequence>(this,
android.R.layout.simple_spinner_item, content);
@@ -270,12 +305,7 @@ public class ProfileActivity extends Activity {
});
// Custom profiling WebView
- WebSettings settings = mWeb.getSettings();
- settings.setJavaScriptEnabled(true);
- settings.setSupportZoom(true);
- settings.setEnableSmoothTransition(true);
- settings.setBuiltInZoomControls(true);
- settings.setLoadWithOverviewMode(true);
+ mWeb.init(this);
mWeb.setWebViewClient(new LoggingWebViewClient());
// URL text entry
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java
index 10802b4..a38ac25 100644
--- a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java
@@ -20,23 +20,32 @@ import android.content.Context;
import android.os.CountDownTimer;
import android.util.AttributeSet;
import android.util.Log;
+import android.webkit.WebSettings;
import android.webkit.WebView;
+import android.widget.Toast;
+
+import java.util.ArrayList;
import com.test.tilebenchmark.ProfileActivity.ProfileCallback;
import com.test.tilebenchmark.RunData.TileData;
public class ProfiledWebView extends WebView {
+ private static final String LOGTAG = "ProfiledWebView";
+
private int mSpeed;
private boolean mIsTesting = false;
private boolean mIsScrolling = false;
private ProfileCallback mCallback;
private long mContentInvalMillis;
- private boolean mHadToBeForced = false;
- private int mTestCount = 0;
- private static final int LOAD_STALL_MILLIS = 5000; // nr of millis after load,
+ private static final int LOAD_STALL_MILLIS = 2000; // nr of millis after load,
// before test is forced
+ // ignore anim end events until this many millis after load
+ private static final long ANIM_SAFETY_THRESHOLD = 200;
+ private long mLoadTime;
+ private long mAnimationTime;
+
public ProfiledWebView(Context context) {
super(context);
}
@@ -54,6 +63,39 @@ public class ProfiledWebView extends WebView {
super(context, attrs, defStyle, privateBrowsing);
}
+ private class JavaScriptInterface {
+ Context mContext;
+
+ /** Instantiate the interface and set the context */
+ JavaScriptInterface(Context c) {
+ mContext = c;
+ }
+
+ /** Show a toast from the web page */
+ public void animationComplete() {
+ Toast.makeText(mContext, "Animation complete!", Toast.LENGTH_SHORT).show();
+ //Log.d(LOGTAG, "anim complete");
+ mAnimationTime = System.currentTimeMillis();
+ }
+ }
+
+ public void init(Context c) {
+ WebSettings settings = getSettings();
+ settings.setJavaScriptEnabled(true);
+ settings.setSupportZoom(true);
+ settings.setEnableSmoothTransition(true);
+ settings.setBuiltInZoomControls(true);
+ settings.setLoadWithOverviewMode(true);
+ settings.setProperty("use_minimal_memory", "false"); // prefetch tiles, as browser does
+ addJavascriptInterface(new JavaScriptInterface(c), "Android");
+ mAnimationTime = 0;
+ mLoadTime = 0;
+ }
+
+ public void onPageFinished() {
+ mLoadTime = System.currentTimeMillis();
+ }
+
@Override
protected void onDraw(android.graphics.Canvas canvas) {
if (mIsTesting && mIsScrolling) {
@@ -73,16 +115,12 @@ public class ProfiledWebView extends WebView {
* scrolling, invalidate all content and redraw it, measuring time taken.
*/
public void startScrollTest(ProfileCallback callback, boolean autoScrolling) {
- mIsScrolling = autoScrolling;
mCallback = callback;
mIsTesting = false;
- mContentInvalMillis = System.currentTimeMillis();
- registerPageSwapCallback();
- contentInvalidateAll();
- invalidate();
+ mIsScrolling = false;
+ WebSettings settings = getSettings();
+ settings.setProperty("tree_updates", "0");
- mTestCount++;
- final int testCount = mTestCount;
if (autoScrolling) {
// after a while, force it to start even if the pages haven't swapped
@@ -93,15 +131,18 @@ public class ProfiledWebView extends WebView {
@Override
public void onFinish() {
- if (testCount == mTestCount && !mIsTesting) {
- mHadToBeForced = true;
- Log.d("ProfiledWebView", "num " + testCount
- + " forcing a page swap with a scroll...");
- scrollBy(0, 1);
- invalidate(); // ensure a redraw so that auto-scrolling can occur
- }
+ // invalidate all content, and kick off redraw
+ Log.d("ProfiledWebView",
+ "kicking off test with callback registration, and tile discard...");
+ discardAllTextures();
+ invalidate();
+ mIsScrolling = true;
+ mContentInvalMillis = System.currentTimeMillis();
}
}.start();
+ } else {
+ mIsTesting = true;
+ tileProfilingStart();
}
}
@@ -111,13 +152,36 @@ public class ProfiledWebView extends WebView {
*/
@Override
protected void pageSwapCallback(boolean startAnim) {
- mContentInvalMillis = System.currentTimeMillis() - mContentInvalMillis;
super.pageSwapCallback(startAnim);
- Log.d("ProfiledWebView", "REDRAW TOOK " + mContentInvalMillis
- + "millis");
- mIsTesting = true;
- invalidate(); // ensure a redraw so that auto-scrolling can occur
- tileProfilingStart();
+
+ if (!mIsTesting && mIsScrolling) {
+ // kick off testing
+ mContentInvalMillis = System.currentTimeMillis() - mContentInvalMillis;
+ Log.d("ProfiledWebView", "REDRAW TOOK " + mContentInvalMillis + "millis");
+ mIsTesting = true;
+ invalidate(); // ensure a redraw so that auto-scrolling can occur
+ tileProfilingStart();
+ }
+ }
+
+ private double animFramerate() {
+ WebSettings settings = getSettings();
+ String updatesString = settings.getProperty("tree_updates");
+ int updates = (updatesString == null) ? -1 : Integer.parseInt(updatesString);
+
+ long animationTime;
+ if (mAnimationTime == 0 || mAnimationTime - mLoadTime < ANIM_SAFETY_THRESHOLD) {
+ animationTime = System.currentTimeMillis() - mLoadTime;
+ } else {
+ animationTime = mAnimationTime - mLoadTime;
+ }
+
+ return updates * 1000.0 / animationTime;
+ }
+
+ public void setDoubleBuffering(boolean useDoubleBuffering) {
+ WebSettings settings = getSettings();
+ settings.setProperty("use_double_buffering", useDoubleBuffering ? "true" : "false");
}
/*
@@ -136,11 +200,12 @@ public class ProfiledWebView extends WebView {
// record the time spent (before scrolling) rendering the page
data.singleStats.put(getResources().getString(R.string.render_millis),
(double)mContentInvalMillis);
- // record if the page render timed out
- Log.d("ProfiledWebView", "hadtobeforced = " + mHadToBeForced);
- data.singleStats.put(getResources().getString(R.string.render_stalls),
- mHadToBeForced ? 1.0 : 0.0);
- mHadToBeForced = false;
+
+ // record framerate
+ double framerate = animFramerate();
+ Log.d(LOGTAG, "anim framerate was "+framerate);
+ data.singleStats.put(getResources().getString(R.string.animation_framerate),
+ framerate);
for (int frame = 0; frame < data.frames.length; frame++) {
data.frames[frame] = new TileData[
@@ -168,6 +233,8 @@ public class ProfiledWebView extends WebView {
@Override
public void loadUrl(String url) {
+ mAnimationTime = 0;
+ mLoadTime = 0;
if (!url.startsWith("http://") && !url.startsWith("file://")) {
url = "http://" + url;
}
diff --git a/tests/TileBenchmark/tests/Android.mk b/tests/TileBenchmark/tests/Android.mk
deleted file mode 100644
index 8b235ec..0000000
--- a/tests/TileBenchmark/tests/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_JAVA_LIBRARIES := android.test.runner
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := TileBenchmarkTests
-
-LOCAL_INSTRUMENTATION_FOR := TileBenchmark
-
-include $(BUILD_PACKAGE)
diff --git a/tests/TileBenchmark/tests/src/com/test/tilebenchmark/PerformanceTest.java b/tests/TileBenchmark/tests/src/com/test/tilebenchmark/PerformanceTest.java
deleted file mode 100644
index 6bf6f6b..0000000
--- a/tests/TileBenchmark/tests/src/com/test/tilebenchmark/PerformanceTest.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.test.tilebenchmark;
-
-import com.test.tilebenchmark.ProfileActivity.ProfileCallback;
-
-import java.io.File;
-import java.util.HashMap;
-import java.util.Map;
-
-import android.content.res.Resources;
-import android.os.Bundle;
-import android.os.Environment;
-import android.test.ActivityInstrumentationTestCase2;
-import android.util.Log;
-
-public class PerformanceTest extends
- ActivityInstrumentationTestCase2<ProfileActivity> {
-
- private class StatAggregator extends PlaybackGraphs {
- private HashMap<String, Double> mDataMap = new HashMap<String, Double>();
- private int mCount = 0;
-
- public void aggregate() {
- mCount++;
- Resources resources = mView.getResources();
- for (int metricIndex = 0; metricIndex < Metrics.length; metricIndex++) {
- for (int statIndex = 0; statIndex < Stats.length; statIndex++) {
- String metricLabel = resources.getString(
- Metrics[metricIndex].getLabelId());
- String statLabel = resources.getString(
- Stats[statIndex].getLabelId());
-
- String label = metricLabel + " " + statLabel;
- double aggVal = mDataMap.containsKey(label) ? mDataMap
- .get(label) : 0;
-
- aggVal += mStats[metricIndex][statIndex];
- mDataMap.put(label, aggVal);
- }
- }
- for (Map.Entry<String, Double> e : mSingleStats.entrySet()) {
- double aggVal = mDataMap.containsKey(e.getKey())
- ? mDataMap.get(e.getKey()) : 0;
- mDataMap.put(e.getKey(), aggVal + e.getValue());
- }
- }
-
- public Bundle getBundle() {
- Bundle b = new Bundle();
- int count = 0 == mCount ? Integer.MAX_VALUE : mCount;
- for (Map.Entry<String, Double> e : mDataMap.entrySet()) {
- b.putDouble(e.getKey(), e.getValue() / count);
- }
- return b;
- }
- }
-
- ProfileActivity mActivity;
- ProfiledWebView mView;
- StatAggregator mStats = new StatAggregator();
-
- private static final String LOGTAG = "PerformanceTest";
- private static final String TEST_LOCATION = "webkit/page_cycler";
- private static final String URL_PREFIX = "file://";
- private static final String URL_POSTFIX = "/index.html?skip=true";
- private static final int MAX_ITERATIONS = 4;
- private static final String TEST_DIRS[] = {
- "intl1"//, "alexa_us", "android", "dom", "intl2", "moz", "moz2"
- };
-
- public PerformanceTest() {
- super(ProfileActivity.class);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mActivity = getActivity();
- mView = (ProfiledWebView) mActivity.findViewById(R.id.web);
- }
-
- private boolean loadUrl(final String url) {
- try {
- Log.d(LOGTAG, "test starting for url " + url);
- mActivity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- mView.loadUrl(url);
- }
- });
- synchronized (mStats) {
- mStats.wait();
- }
- mStats.aggregate();
- } catch (InterruptedException e) {
- e.printStackTrace();
- return false;
- }
- return true;
- }
-
- private boolean runIteration() {
- File sdFile = Environment.getExternalStorageDirectory();
- for (String testDirName : TEST_DIRS) {
- File testDir = new File(sdFile, TEST_LOCATION + "/" + testDirName);
- Log.d(LOGTAG, "Testing dir: '" + testDir.getAbsolutePath()
- + "', exists=" + testDir.exists());
- for (File siteDir : testDir.listFiles()) {
- if (!siteDir.isDirectory())
- continue;
-
- if (!loadUrl(URL_PREFIX + siteDir.getAbsolutePath()
- + URL_POSTFIX)) {
- return false;
- }
- }
- }
- return true;
- }
-
- public void testMetrics() {
- String state = Environment.getExternalStorageState();
-
- if (!Environment.MEDIA_MOUNTED.equals(state)
- && !Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
- Log.d(LOGTAG, "ARG Can't access sd card!");
- // Can't read the SD card, fail and die!
- getInstrumentation().sendStatus(1, null);
- return;
- }
-
- // use mGraphs as a condition variable between the UI thread and
- // this(the testing) thread
- mActivity.setCallback(new ProfileCallback() {
- @Override
- public void profileCallback(RunData data) {
- Log.d(LOGTAG, "test completion callback");
- mStats.setData(data);
- synchronized (mStats) {
- mStats.notify();
- }
- }
- });
-
- for (int i = 0; i < MAX_ITERATIONS; i++)
- if (!runIteration()) {
- getInstrumentation().sendStatus(1, null);
- return;
- }
- getInstrumentation().sendStatus(0, mStats.getBundle());
- }
-}
diff --git a/tests/TtsTests/Android.mk b/tests/TtsTests/Android.mk
new file mode 100644
index 0000000..e049c90
--- /dev/null
+++ b/tests/TtsTests/Android.mk
@@ -0,0 +1,28 @@
+#
+# Copyright (C) 2011 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_STATIC_JAVA_LIBRARIES := littlemock
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_PACKAGE_NAME := TtsTests
+
+include $(BUILD_PACKAGE)
diff --git a/tests/TtsTests/AndroidManifest.xml b/tests/TtsTests/AndroidManifest.xml
new file mode 100644
index 0000000..b6d5111
--- /dev/null
+++ b/tests/TtsTests/AndroidManifest.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2011 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.speech.tts">
+ <application>
+ <uses-library android:name="android.test.runner" />
+
+
+ <service android:name=".MockableTextToSpeechService"
+ android:label="Mockable Text-to-speech Service">
+ <intent-filter>
+ <action android:name="android.intent.action.TTS_SERVICE" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </service>
+
+ <activity android:name=".MockableCheckVoiceData"
+ android:theme="@android:style/Theme.NoDisplay">
+ <intent-filter>
+ <action android:name="android.speech.tts.engine.CHECK_TTS_DATA" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+ </application>
+
+ <instrumentation android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.android.speech.tts"
+ android:label="Tests for android.speech.tts" />
+</manifest>
diff --git a/tests/TtsTests/src/com/android/speech/tts/MockableCheckVoiceData.java b/tests/TtsTests/src/com/android/speech/tts/MockableCheckVoiceData.java
new file mode 100644
index 0000000..0ab8ed6
--- /dev/null
+++ b/tests/TtsTests/src/com/android/speech/tts/MockableCheckVoiceData.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.speech.tts;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.speech.tts.TextToSpeech;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class MockableCheckVoiceData extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ MockableTextToSpeechService.IDelegate delegate =
+ MockableTextToSpeechService.getMocker();
+
+ ArrayList<String> availableLangs = delegate.getAvailableVoices();
+ ArrayList<String> unavailableLangs = delegate.getUnavailableVoices();
+
+ final Intent returnVal = new Intent();
+
+ // Returns early.
+ if (availableLangs == null) {
+ setResult(TextToSpeech.Engine.CHECK_VOICE_DATA_FAIL, returnVal);
+ finish();
+ return;
+ }
+
+ returnVal.putStringArrayListExtra(TextToSpeech.Engine.EXTRA_AVAILABLE_VOICES,
+ availableLangs);
+
+ if (unavailableLangs != null && unavailableLangs.size() > 0) {
+ returnVal.putStringArrayListExtra(TextToSpeech.Engine.EXTRA_UNAVAILABLE_VOICES,
+ unavailableLangs);
+ }
+
+ setResult(TextToSpeech.Engine.CHECK_VOICE_DATA_PASS, returnVal);
+ finish();
+ }
+
+}
diff --git a/tests/TtsTests/src/com/android/speech/tts/MockableTextToSpeechService.java b/tests/TtsTests/src/com/android/speech/tts/MockableTextToSpeechService.java
new file mode 100644
index 0000000..20648a4
--- /dev/null
+++ b/tests/TtsTests/src/com/android/speech/tts/MockableTextToSpeechService.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.speech.tts;
+
+import android.speech.tts.SynthesisCallback;
+import android.speech.tts.SynthesisRequest;
+import android.speech.tts.TextToSpeechService;
+
+import java.util.ArrayList;
+
+public class MockableTextToSpeechService extends TextToSpeechService {
+
+ private static IDelegate sDelegate;
+
+ public static void setMocker(IDelegate delegate) {
+ sDelegate = delegate;
+ }
+
+ static IDelegate getMocker() {
+ return sDelegate;
+ }
+
+ @Override
+ protected int onIsLanguageAvailable(String lang, String country, String variant) {
+ return sDelegate.onIsLanguageAvailable(lang, country, variant);
+ }
+
+ @Override
+ protected String[] onGetLanguage() {
+ return sDelegate.onGetLanguage();
+ }
+
+ @Override
+ protected int onLoadLanguage(String lang, String country, String variant) {
+ return sDelegate.onLoadLanguage(lang, country, variant);
+ }
+
+ @Override
+ protected void onStop() {
+ sDelegate.onStop();
+ }
+
+ @Override
+ protected void onSynthesizeText(SynthesisRequest request, SynthesisCallback callback) {
+ sDelegate.onSynthesizeText(request, callback);
+ }
+
+ public static interface IDelegate {
+ int onIsLanguageAvailable(String lang, String country, String variant);
+
+ String[] onGetLanguage();
+
+ int onLoadLanguage(String lang, String country, String variant);
+
+ void onStop();
+
+ void onSynthesizeText(SynthesisRequest request, SynthesisCallback callback);
+
+ ArrayList<String> getAvailableVoices();
+
+ ArrayList<String> getUnavailableVoices();
+ }
+
+}
diff --git a/tests/TtsTests/src/com/android/speech/tts/TextToSpeechTests.java b/tests/TtsTests/src/com/android/speech/tts/TextToSpeechTests.java
new file mode 100644
index 0000000..b736e9f
--- /dev/null
+++ b/tests/TtsTests/src/com/android/speech/tts/TextToSpeechTests.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.speech.tts;
+
+import android.speech.tts.SynthesisCallback;
+import android.speech.tts.SynthesisRequest;
+import android.speech.tts.TextToSpeech;
+import android.test.InstrumentationTestCase;
+
+import com.android.speech.tts.MockableTextToSpeechService.IDelegate;
+import com.google.testing.littlemock.ArgumentCaptor;
+import com.google.testing.littlemock.Behaviour;
+import com.google.testing.littlemock.LittleMock;
+import junit.framework.Assert;
+
+import java.util.Locale;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class TextToSpeechTests extends InstrumentationTestCase {
+ private static final String MOCK_ENGINE = "com.android.speech.tts";
+ private static final String MOCK_PACKAGE = "com.android.speech.tts.__testpackage__";
+
+ private TextToSpeech mTts;
+
+ @Override
+ public void setUp() throws Exception {
+ IDelegate passThrough = LittleMock.mock(IDelegate.class);
+ MockableTextToSpeechService.setMocker(passThrough);
+
+ blockingInitAndVerify(MOCK_ENGINE, TextToSpeech.SUCCESS);
+ assertEquals(MOCK_ENGINE, mTts.getCurrentEngine());
+ }
+
+
+ @Override
+ public void tearDown() {
+ if (mTts != null) {
+ mTts.shutdown();
+ }
+ }
+
+ public void testEngineInitialized() throws Exception {
+ // Fail on an engine that doesn't exist.
+ blockingInitAndVerify("__DOES_NOT_EXIST__", TextToSpeech.ERROR);
+
+ // Also, the "current engine" must be null
+ assertNull(mTts.getCurrentEngine());
+ }
+
+ public void testSetLanguage_delegation() {
+ IDelegate delegate = LittleMock.mock(IDelegate.class);
+ MockableTextToSpeechService.setMocker(delegate);
+
+ // Test 1 :Tests that calls to onLoadLanguage( ) are delegated through to the
+ // service without any caching or intermediate steps.
+ mTts.setLanguage(new Locale("eng", "USA", "variant"));
+ LittleMock.verify(delegate, LittleMock.times(1)).onLoadLanguage(
+ "eng", "USA", "variant");
+ }
+
+ public void testSetLanguage_availableLanguage() throws Exception {
+ IDelegate delegate = LittleMock.mock(IDelegate.class);
+ MockableTextToSpeechService.setMocker(delegate);
+
+ // ---------------------------------------------------------
+ // Test 2 : Tests that when the language is successfully set
+ // like above (returns LANG_COUNTRY_AVAILABLE). That the
+ // request language changes from that point on.
+ LittleMock.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).when(delegate).onLoadLanguage(
+ "eng", "USA", "variant");
+ mTts.setLanguage(new Locale("eng", "USA", "variant"));
+ blockingCallSpeak("foo bar", delegate);
+ ArgumentCaptor<SynthesisRequest> req = LittleMock.createCaptor();
+ LittleMock.verify(delegate, LittleMock.times(1)).onSynthesizeText(req.capture(),
+ LittleMock.<SynthesisCallback>anyObject());
+
+ assertEquals("eng", req.getValue().getLanguage());
+ assertEquals("USA", req.getValue().getCountry());
+ assertEquals("", req.getValue().getVariant());
+ }
+
+ public void testSetLanguage_unavailableLanguage() throws Exception {
+ IDelegate delegate = LittleMock.mock(IDelegate.class);
+ MockableTextToSpeechService.setMocker(delegate);
+
+ // ---------------------------------------------------------
+ // TEST 3 : Tests that the language that is set does not change when the
+ // engine reports it could not load the specified language.
+ LittleMock.doReturn(TextToSpeech.LANG_NOT_SUPPORTED).when(
+ delegate).onLoadLanguage("fra", "FRA", "");
+ mTts.setLanguage(Locale.FRANCE);
+ blockingCallSpeak("le fou barre", delegate);
+ ArgumentCaptor<SynthesisRequest> req2 = LittleMock.createCaptor();
+ LittleMock.verify(delegate, LittleMock.times(1)).onSynthesizeText(req2.capture(),
+ LittleMock.<SynthesisCallback>anyObject());
+
+ // The params are basically unchanged.
+ assertEquals("eng", req2.getValue().getLanguage());
+ assertEquals("USA", req2.getValue().getCountry());
+ assertEquals("", req2.getValue().getVariant());
+ }
+
+
+ public void testGetLanguage_invalidReturnValues() {
+ IDelegate delegate = LittleMock.mock(IDelegate.class);
+ MockableTextToSpeechService.setMocker(delegate);
+
+ // Test1: Simple end to end test. Ensure that bad return values
+ // are dealt with appropriately.
+ LittleMock.doReturn(null).when(delegate).onGetLanguage();
+ Locale returnVal = mTts.getLanguage();
+ assertNull(returnVal);
+
+
+ // Bad value 2. An array of length < 3.
+ LittleMock.doReturn(new String[] {"eng", "usa"}).when(delegate).onGetLanguage();
+ returnVal = mTts.getLanguage();
+ assertNull(returnVal);
+ }
+
+ public void testGetLanguage_validReturnValues() {
+ IDelegate delegate = LittleMock.mock(IDelegate.class);
+ MockableTextToSpeechService.setMocker(delegate);
+
+ // A correct value.
+ LittleMock.doReturn(new String[] {"eng", "usa", ""}).when(delegate).onGetLanguage();
+ Locale returnVal = mTts.getLanguage();
+
+ // Note: This is not the same as Locale.US . Well tough luck for
+ // being the only component of the entire framework that standardized
+ // three letter country and language codes.
+ assertEquals(new Locale("eng", "USA", ""), returnVal);
+ }
+
+ public void testIsLanguageAvailable() {
+ IDelegate delegate = LittleMock.mock(IDelegate.class);
+ MockableTextToSpeechService.setMocker(delegate);
+
+ // Test1: Simple end to end test.
+ LittleMock.doReturn(TextToSpeech.LANG_COUNTRY_AVAILABLE).when(
+ delegate).onIsLanguageAvailable("eng", "USA", "");
+
+ assertEquals(TextToSpeech.LANG_COUNTRY_AVAILABLE, mTts.isLanguageAvailable(Locale.US));
+ LittleMock.verify(delegate, LittleMock.times(1)).onIsLanguageAvailable(
+ "eng", "USA", "");
+ }
+
+
+ private void blockingCallSpeak(String speech, IDelegate mock) throws
+ InterruptedException {
+ final CountDownLatch latch = new CountDownLatch(1);
+ doCountDown(latch).when(mock).onSynthesizeText(LittleMock.<SynthesisRequest>anyObject(),
+ LittleMock.<SynthesisCallback>anyObject());
+ mTts.speak(speech, TextToSpeech.QUEUE_ADD, null);
+
+ awaitCountDown(latch, 5, TimeUnit.SECONDS);
+ }
+
+ private void blockingInitAndVerify(final String engine, int errorCode) throws
+ InterruptedException {
+ TextToSpeech.OnInitListener listener = LittleMock.mock(
+ TextToSpeech.OnInitListener.class);
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ doCountDown(latch).when(listener).onInit(errorCode);
+
+ mTts = new TextToSpeech(getInstrumentation().getTargetContext(),
+ listener, engine, MOCK_PACKAGE, false /* use fallback package */);
+
+ awaitCountDown(latch, 5, TimeUnit.SECONDS);
+ }
+
+ public interface CountDownBehaviour extends Behaviour {
+ /** Used to mock methods that return a result. */
+ Behaviour andReturn(Object result);
+ }
+
+ public static CountDownBehaviour doCountDown(final CountDownLatch latch) {
+ return new CountDownBehaviour() {
+ @Override
+ public <T> T when(T mock) {
+ return LittleMock.doAnswer(new Callable<Void>() {
+ @Override
+ public Void call() throws Exception {
+ latch.countDown();
+ return null;
+ }
+ }).when(mock);
+ }
+
+ @Override
+ public Behaviour andReturn(final Object result) {
+ return new Behaviour() {
+ @Override
+ public <T> T when(T mock) {
+ return LittleMock.doAnswer(new Callable<Object>() {
+ @Override
+ public Object call() throws Exception {
+ latch.countDown();
+ return result;
+ }
+ }).when(mock);
+ }
+ };
+ }
+ };
+ }
+
+ public static void awaitCountDown(CountDownLatch latch, long timeout, TimeUnit unit)
+ throws InterruptedException {
+ Assert.assertTrue("Waited too long for method call", latch.await(timeout, unit));
+ }
+}
diff --git a/tests/WebViewTests/Android.mk b/tests/WebViewTests/Android.mk
new file mode 100644
index 0000000..b118845
--- /dev/null
+++ b/tests/WebViewTests/Android.mk
@@ -0,0 +1,27 @@
+#
+# Copyright (C) 2011 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_PACKAGE_NAME := WebViewTests
+
+include $(BUILD_PACKAGE)
diff --git a/tests/WebViewTests/AndroidManifest.xml b/tests/WebViewTests/AndroidManifest.xml
new file mode 100644
index 0000000..8b080c1
--- /dev/null
+++ b/tests/WebViewTests/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2011 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.webviewtests">
+ <application>
+ <uses-library android:name="android.test.runner" />
+ <activity android:name="WebViewStubActivity" android:label="WebViewStubActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.TEST" />
+ </intent-filter>
+ </activity>
+ </application>
+
+ <instrumentation android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.android.webviewtests"
+ android:label="Tests for android.webkit.WebView" />
+</manifest>
diff --git a/tests/WebViewTests/res/layout/webview_layout.xml b/tests/WebViewTests/res/layout/webview_layout.xml
new file mode 100644
index 0000000..d266d21
--- /dev/null
+++ b/tests/WebViewTests/res/layout/webview_layout.xml
@@ -0,0 +1,25 @@
+<?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:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <WebView android:id="@+id/web_page"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+</LinearLayout>
diff --git a/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeArrayCoercionTest.java b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeArrayCoercionTest.java
new file mode 100644
index 0000000..c2bbdf5
--- /dev/null
+++ b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeArrayCoercionTest.java
@@ -0,0 +1,625 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Part of the test suite for the WebView's Java Bridge. This class tests that
+ * we correctly convert JavaScript arrays to Java arrays when passing them to
+ * the methods of injected Java objects.
+ *
+ * The conversions should follow
+ * http://jdk6.java.net/plugin2/liveconnect/#JS_JAVA_CONVERSIONS. Places in
+ * which the implementation differs from the spec are marked with
+ * LIVECONNECT_COMPLIANCE.
+ * FIXME: Consider making our implementation more compliant, if it will not
+ * break backwards-compatibility. See b/4408210.
+ *
+ * To run this test ...
+ * adb shell am instrument -w -e class com.android.webviewtests.JavaBridgeArrayCoercionTest \
+ * com.android.webviewtests/android.test.InstrumentationTestRunner
+ */
+
+package com.android.webviewtests;
+
+public class JavaBridgeArrayCoercionTest extends JavaBridgeTestBase {
+ private class TestObject extends Controller {
+ private Object mObjectInstance;
+ private CustomType mCustomTypeInstance;
+
+ private boolean[] mBooleanArray;
+ private byte[] mByteArray;
+ private char[] mCharArray;
+ private short[] mShortArray;
+ private int[] mIntArray;
+ private long[] mLongArray;
+ private float[] mFloatArray;
+ private double[] mDoubleArray;
+ private String[] mStringArray;
+ private Object[] mObjectArray;
+ private CustomType[] mCustomTypeArray;
+
+ public TestObject() {
+ mObjectInstance = new Object();
+ mCustomTypeInstance = new CustomType();
+ }
+
+ public Object getObjectInstance() {
+ return mObjectInstance;
+ }
+ public CustomType getCustomTypeInstance() {
+ return mCustomTypeInstance;
+ }
+
+ public synchronized void setBooleanArray(boolean[] x) {
+ mBooleanArray = x;
+ notifyResultIsReady();
+ }
+ public synchronized void setByteArray(byte[] x) {
+ mByteArray = x;
+ notifyResultIsReady();
+ }
+ public synchronized void setCharArray(char[] x) {
+ mCharArray = x;
+ notifyResultIsReady();
+ }
+ public synchronized void setShortArray(short[] x) {
+ mShortArray = x;
+ notifyResultIsReady();
+ }
+ public synchronized void setIntArray(int[] x) {
+ mIntArray = x;
+ notifyResultIsReady();
+ }
+ public synchronized void setLongArray(long[] x) {
+ mLongArray = x;
+ notifyResultIsReady();
+ }
+ public synchronized void setFloatArray(float[] x) {
+ mFloatArray = x;
+ notifyResultIsReady();
+ }
+ public synchronized void setDoubleArray(double[] x) {
+ mDoubleArray = x;
+ notifyResultIsReady();
+ }
+ public synchronized void setStringArray(String[] x) {
+ mStringArray = x;
+ notifyResultIsReady();
+ }
+ public synchronized void setObjectArray(Object[] x) {
+ mObjectArray = x;
+ notifyResultIsReady();
+ }
+ public synchronized void setCustomTypeArray(CustomType[] x) {
+ mCustomTypeArray = x;
+ notifyResultIsReady();
+ }
+
+ public synchronized boolean[] waitForBooleanArray() {
+ waitForResult();
+ return mBooleanArray;
+ }
+ public synchronized byte[] waitForByteArray() {
+ waitForResult();
+ return mByteArray;
+ }
+ public synchronized char[] waitForCharArray() {
+ waitForResult();
+ return mCharArray;
+ }
+ public synchronized short[] waitForShortArray() {
+ waitForResult();
+ return mShortArray;
+ }
+ public synchronized int[] waitForIntArray() {
+ waitForResult();
+ return mIntArray;
+ }
+ public synchronized long[] waitForLongArray() {
+ waitForResult();
+ return mLongArray;
+ }
+ public synchronized float[] waitForFloatArray() {
+ waitForResult();
+ return mFloatArray;
+ }
+ public synchronized double[] waitForDoubleArray() {
+ waitForResult();
+ return mDoubleArray;
+ }
+ public synchronized String[] waitForStringArray() {
+ waitForResult();
+ return mStringArray;
+ }
+ public synchronized Object[] waitForObjectArray() {
+ waitForResult();
+ return mObjectArray;
+ }
+ public synchronized CustomType[] waitForCustomTypeArray() {
+ waitForResult();
+ return mCustomTypeArray;
+ }
+ }
+
+ // Two custom types used when testing passing objects.
+ private class CustomType {
+ }
+
+ private TestObject mTestObject;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mTestObject = new TestObject();
+ setUpWebView(mTestObject, "testObject");
+ }
+
+ // Note that all tests use a single element array for simplicity. We test
+ // multiple elements elsewhere.
+
+ // Test passing an array of JavaScript numbers in the int32 range to a
+ // method which takes a Java array.
+ public void testPassNumberInt32() throws Throwable {
+ executeJavaScript("testObject.setBooleanArray([0]);");
+ assertFalse(mTestObject.waitForBooleanArray()[0]);
+ // LIVECONNECT_COMPLIANCE: Should convert to boolean.
+ executeJavaScript("testObject.setBooleanArray([42]);");
+ assertFalse(mTestObject.waitForBooleanArray()[0]);
+
+ executeJavaScript("testObject.setByteArray([42]);");
+ assertEquals(42, mTestObject.waitForByteArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should convert to numeric char value.
+ executeJavaScript("testObject.setCharArray([42]);");
+ assertEquals('\u0000', mTestObject.waitForCharArray()[0]);
+
+ executeJavaScript("testObject.setShortArray([42]);");
+ assertEquals(42, mTestObject.waitForShortArray()[0]);
+
+ executeJavaScript("testObject.setIntArray([42]);");
+ assertEquals(42, mTestObject.waitForIntArray()[0]);
+
+ executeJavaScript("testObject.setLongArray([42]);");
+ assertEquals(42L, mTestObject.waitForLongArray()[0]);
+
+ executeJavaScript("testObject.setFloatArray([42]);");
+ assertEquals(42.0f, mTestObject.waitForFloatArray()[0]);
+
+ executeJavaScript("testObject.setDoubleArray([42]);");
+ assertEquals(42.0, mTestObject.waitForDoubleArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should create array and create instances of java.lang.Number.
+ executeJavaScript("testObject.setObjectArray([42]);");
+ assertNull(mTestObject.waitForObjectArray());
+
+ // LIVECONNECT_COMPLIANCE: Should create instances of java.lang.String.
+ executeJavaScript("testObject.setStringArray([42]);");
+ assertNull(mTestObject.waitForStringArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setCustomTypeArray([42]);");
+ assertNull(mTestObject.waitForCustomTypeArray());
+ }
+
+ // Test passing an array of JavaScript numbers in the double range to a
+ // method which takes a Java array.
+ public void testPassNumberDouble() throws Throwable {
+ // LIVECONNECT_COMPLIANCE: Should convert to boolean.
+ executeJavaScript("testObject.setBooleanArray([42.1]);");
+ assertFalse(mTestObject.waitForBooleanArray()[0]);
+
+ executeJavaScript("testObject.setByteArray([42.1]);");
+ assertEquals(42, mTestObject.waitForByteArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should convert to numeric char value.
+ executeJavaScript("testObject.setCharArray([42.1]);");
+ assertEquals('\u0000', mTestObject.waitForCharArray()[0]);
+
+ executeJavaScript("testObject.setShortArray([42.1]);");
+ assertEquals(42, mTestObject.waitForShortArray()[0]);
+
+ executeJavaScript("testObject.setIntArray([42.1]);");
+ assertEquals(42, mTestObject.waitForIntArray()[0]);
+
+ executeJavaScript("testObject.setLongArray([42.1]);");
+ assertEquals(42L, mTestObject.waitForLongArray()[0]);
+
+ executeJavaScript("testObject.setFloatArray([42.1]);");
+ assertEquals(42.1f, mTestObject.waitForFloatArray()[0]);
+
+ executeJavaScript("testObject.setDoubleArray([42.1]);");
+ assertEquals(42.1, mTestObject.waitForDoubleArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should create array and create instances of java.lang.Number.
+ executeJavaScript("testObject.setObjectArray([42.1]);");
+ assertNull(mTestObject.waitForObjectArray());
+
+ // LIVECONNECT_COMPLIANCE: Should create instances of java.lang.String.
+ executeJavaScript("testObject.setStringArray([42.1]);");
+ assertNull(mTestObject.waitForStringArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setCustomTypeArray([42.1]);");
+ assertNull(mTestObject.waitForCustomTypeArray());
+ }
+
+ // Test passing an array of JavaScript NaN values to a method which takes a
+ // Java array.
+ public void testPassNumberNaN() throws Throwable {
+ executeJavaScript("testObject.setBooleanArray([Number.NaN]);");
+ assertFalse(mTestObject.waitForBooleanArray()[0]);
+
+ executeJavaScript("testObject.setByteArray([Number.NaN]);");
+ assertEquals(0, mTestObject.waitForByteArray()[0]);
+
+ executeJavaScript("testObject.setCharArray([Number.NaN]);");
+ assertEquals('\u0000', mTestObject.waitForCharArray()[0]);
+
+ executeJavaScript("testObject.setShortArray([Number.NaN]);");
+ assertEquals(0, mTestObject.waitForShortArray()[0]);
+
+ executeJavaScript("testObject.setIntArray([Number.NaN]);");
+ assertEquals(0, mTestObject.waitForIntArray()[0]);
+
+ executeJavaScript("testObject.setLongArray([Number.NaN]);");
+ assertEquals(0L, mTestObject.waitForLongArray()[0]);
+
+ executeJavaScript("testObject.setFloatArray([Number.NaN]);");
+ assertEquals(Float.NaN, mTestObject.waitForFloatArray()[0]);
+
+ executeJavaScript("testObject.setDoubleArray([Number.NaN]);");
+ assertEquals(Double.NaN, mTestObject.waitForDoubleArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should create array and create instances of java.lang.Number.
+ executeJavaScript("testObject.setObjectArray([Number.NaN]);");
+ assertNull(mTestObject.waitForObjectArray());
+
+ // LIVECONNECT_COMPLIANCE: Should create instances of java.lang.String.
+ executeJavaScript("testObject.setStringArray([Number.NaN]);");
+ assertNull(mTestObject.waitForStringArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setCustomTypeArray([Number.NaN]);");
+ assertNull(mTestObject.waitForCustomTypeArray());
+ }
+
+ // Test passing an array of JavaScript infinity values to a method which
+ // takes a Java array.
+ public void testPassNumberInfinity() throws Throwable {
+ executeJavaScript("testObject.setBooleanArray([Infinity]);");
+ assertFalse(mTestObject.waitForBooleanArray()[0]);
+
+ executeJavaScript("testObject.setByteArray([Infinity]);");
+ assertEquals(-1, mTestObject.waitForByteArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should convert to maximum numeric char value.
+ executeJavaScript("testObject.setCharArray([Infinity]);");
+ assertEquals('\u0000', mTestObject.waitForCharArray()[0]);
+
+ executeJavaScript("testObject.setShortArray([Infinity]);");
+ assertEquals(-1, mTestObject.waitForShortArray()[0]);
+
+ executeJavaScript("testObject.setIntArray([Infinity]);");
+ assertEquals(Integer.MAX_VALUE, mTestObject.waitForIntArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should be Long.MAX_VALUE.
+ executeJavaScript("testObject.setLongArray([Infinity]);");
+ assertEquals(-1L, mTestObject.waitForLongArray()[0]);
+
+ executeJavaScript("testObject.setFloatArray([Infinity]);");
+ assertEquals(Float.POSITIVE_INFINITY, mTestObject.waitForFloatArray()[0]);
+
+ executeJavaScript("testObject.setDoubleArray([Infinity]);");
+ assertEquals(Double.POSITIVE_INFINITY, mTestObject.waitForDoubleArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should create array and create instances of java.lang.Number.
+ executeJavaScript("testObject.setObjectArray([Infinity]);");
+ assertNull(mTestObject.waitForObjectArray());
+
+ // LIVECONNECT_COMPLIANCE: Should create instances of java.lang.String.
+ executeJavaScript("testObject.setStringArray([Infinity]);");
+ assertNull(mTestObject.waitForStringArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setCustomTypeArray([Infinity]);");
+ assertNull(mTestObject.waitForCustomTypeArray());
+ }
+
+ // Test passing an array of JavaScript boolean values to a method which
+ // takes a Java array.
+ public void testPassBoolean() throws Throwable {
+ executeJavaScript("testObject.setBooleanArray([true]);");
+ assertTrue(mTestObject.waitForBooleanArray()[0]);
+ executeJavaScript("testObject.setBooleanArray([false]);");
+ assertFalse(mTestObject.waitForBooleanArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should be 1.
+ executeJavaScript("testObject.setByteArray([true]);");
+ assertEquals(0, mTestObject.waitForByteArray()[0]);
+ executeJavaScript("testObject.setByteArray([false]);");
+ assertEquals(0, mTestObject.waitForByteArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should convert to numeric char value 1.
+ executeJavaScript("testObject.setCharArray([true]);");
+ assertEquals('\u0000', mTestObject.waitForCharArray()[0]);
+ executeJavaScript("testObject.setCharArray([false]);");
+ assertEquals('\u0000', mTestObject.waitForCharArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should be 1.
+ executeJavaScript("testObject.setShortArray([true]);");
+ assertEquals(0, mTestObject.waitForShortArray()[0]);
+ executeJavaScript("testObject.setShortArray([false]);");
+ assertEquals(0, mTestObject.waitForShortArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should be 1.
+ executeJavaScript("testObject.setIntArray([true]);");
+ assertEquals(0, mTestObject.waitForIntArray()[0]);
+ executeJavaScript("testObject.setIntArray([false]);");
+ assertEquals(0, mTestObject.waitForIntArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should be 1.
+ executeJavaScript("testObject.setLongArray([true]);");
+ assertEquals(0L, mTestObject.waitForLongArray()[0]);
+ executeJavaScript("testObject.setLongArray([false]);");
+ assertEquals(0L, mTestObject.waitForLongArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should be 1.0.
+ executeJavaScript("testObject.setFloatArray([true]);");
+ assertEquals(0.0f, mTestObject.waitForFloatArray()[0]);
+ executeJavaScript("testObject.setFloatArray([false]);");
+ assertEquals(0.0f, mTestObject.waitForFloatArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should be 1.0.
+ executeJavaScript("testObject.setDoubleArray([true]);");
+ assertEquals(0.0, mTestObject.waitForDoubleArray()[0]);
+ executeJavaScript("testObject.setDoubleArray([false]);");
+ assertEquals(0.0, mTestObject.waitForDoubleArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should create array and create instances of java.lang.Number.
+ executeJavaScript("testObject.setObjectArray([true]);");
+ assertNull(mTestObject.waitForObjectArray());
+
+ // LIVECONNECT_COMPLIANCE: Should create instances of java.lang.String.
+ executeJavaScript("testObject.setStringArray([true]);");
+ assertNull(mTestObject.waitForStringArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setCustomTypeArray([true]);");
+ assertNull(mTestObject.waitForCustomTypeArray());
+ }
+
+ // Test passing an array of JavaScript strings to a method which takes a
+ // Java array.
+ public void testPassString() throws Throwable {
+ // LIVECONNECT_COMPLIANCE: Non-empty string should convert to true.
+ executeJavaScript("testObject.setBooleanArray([\"+042.10\"]);");
+ assertFalse(mTestObject.waitForBooleanArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should use valueOf() of appropriate type.
+ executeJavaScript("testObject.setByteArray([\"+042.10\"]);");
+ assertEquals(0, mTestObject.waitForByteArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should decode and convert to numeric char value.
+ executeJavaScript("testObject.setCharArray([\"+042.10\"]);");
+ assertEquals(0, mTestObject.waitForCharArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should use valueOf() of appropriate type.
+ executeJavaScript("testObject.setShortArray([\"+042.10\"]);");
+ assertEquals(0, mTestObject.waitForShortArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should use valueOf() of appropriate type.
+ executeJavaScript("testObject.setIntArray([\"+042.10\"]);");
+ assertEquals(0, mTestObject.waitForIntArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should use valueOf() of appropriate type.
+ executeJavaScript("testObject.setLongArray([\"+042.10\"]);");
+ assertEquals(0L, mTestObject.waitForLongArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should use valueOf() of appropriate type.
+ executeJavaScript("testObject.setFloatArray([\"+042.10\"]);");
+ assertEquals(0.0f, mTestObject.waitForFloatArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should use valueOf() of appropriate type.
+ executeJavaScript("testObject.setDoubleArray([\"+042.10\"]);");
+ assertEquals(0.0, mTestObject.waitForDoubleArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should create array and create instances of java.lang.Number.
+ executeJavaScript("testObject.setObjectArray([\"+042.10\"]);");
+ assertNull(mTestObject.waitForObjectArray());
+
+ executeJavaScript("testObject.setStringArray([\"+042.10\"]);");
+ assertEquals("+042.10", mTestObject.waitForStringArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setCustomTypeArray([\"+042.10\"]);");
+ assertNull(mTestObject.waitForCustomTypeArray());
+ }
+
+ // Test passing an array of JavaScript objects to a method which takes a
+ // Java array.
+ public void testPassJavaScriptObject() throws Throwable {
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setBooleanArray([{foo: 42}]);");
+ assertFalse(mTestObject.waitForBooleanArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setByteArray([{foo: 42}]);");
+ assertEquals(0, mTestObject.waitForByteArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setCharArray([{foo: 42}]);");
+ assertEquals('\u0000', mTestObject.waitForCharArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setShortArray([{foo: 42}]);");
+ assertEquals(0, mTestObject.waitForShortArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setIntArray([{foo: 42}]);");
+ assertEquals(0, mTestObject.waitForIntArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setLongArray([{foo: 42}]);");
+ assertEquals(0L, mTestObject.waitForLongArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setFloatArray([{foo: 42}]);");
+ assertEquals(0.0f, mTestObject.waitForFloatArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setDoubleArray([{foo: 42}]);");
+ assertEquals(0.0, mTestObject.waitForDoubleArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setObjectArray([{foo: 42}]);");
+ assertNull(mTestObject.waitForObjectArray());
+
+ // LIVECONNECT_COMPLIANCE: Should call toString() on object.
+ executeJavaScript("testObject.setStringArray([{foo: 42}]);");
+ assertNull(mTestObject.waitForStringArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setCustomTypeArray([{foo: 42}]);");
+ assertNull(mTestObject.waitForCustomTypeArray());
+ }
+
+ // Test passing an array of Java objects to a method which takes a Java
+ // array.
+ public void testPassJavaObject() throws Throwable {
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setBooleanArray([testObject.getObjectInstance()]);");
+ assertFalse(mTestObject.waitForBooleanArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setByteArray([testObject.getObjectInstance()]);");
+ assertEquals(0, mTestObject.waitForByteArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setCharArray([testObject.getObjectInstance()]);");
+ assertEquals('\u0000', mTestObject.waitForCharArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setShortArray([testObject.getObjectInstance()]);");
+ assertEquals(0, mTestObject.waitForShortArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setIntArray([testObject.getObjectInstance()]);");
+ assertEquals(0, mTestObject.waitForIntArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setLongArray([testObject.getObjectInstance()]);");
+ assertEquals(0L, mTestObject.waitForLongArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setFloatArray([testObject.getObjectInstance()]);");
+ assertEquals(0.0f, mTestObject.waitForFloatArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setDoubleArray([testObject.getObjectInstance()]);");
+ assertEquals(0.0, mTestObject.waitForDoubleArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should create an array and pass Java object.
+ executeJavaScript("testObject.setObjectArray([testObject.getObjectInstance()]);");
+ assertNull(mTestObject.waitForObjectArray());
+
+ // LIVECONNECT_COMPLIANCE: Should call toString() on object.
+ executeJavaScript("testObject.setStringArray([testObject.getObjectInstance()]);");
+ assertNull(mTestObject.waitForStringArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should create array and pass Java object.
+ executeJavaScript("testObject.setCustomTypeArray([testObject.getObjectInstance()]);");
+ assertNull(mTestObject.waitForCustomTypeArray());
+ executeJavaScript("testObject.setCustomTypeArray([testObject.getCustomTypeInstance()]);");
+ assertNull(mTestObject.waitForCustomTypeArray());
+ }
+
+ // Test passing an array of JavaScript null values to a method which takes
+ // a Java array.
+ public void testPassNull() throws Throwable {
+ executeJavaScript("testObject.setByteArray([null]);");
+ assertEquals(0, mTestObject.waitForByteArray()[0]);
+
+ executeJavaScript("testObject.setCharArray([null]);");
+ assertEquals('\u0000', mTestObject.waitForCharArray()[0]);
+
+ executeJavaScript("testObject.setShortArray([null]);");
+ assertEquals(0, mTestObject.waitForShortArray()[0]);
+
+ executeJavaScript("testObject.setIntArray([null]);");
+ assertEquals(0, mTestObject.waitForIntArray()[0]);
+
+ executeJavaScript("testObject.setLongArray([null]);");
+ assertEquals(0L, mTestObject.waitForLongArray()[0]);
+
+ executeJavaScript("testObject.setFloatArray([null]);");
+ assertEquals(0.0f, mTestObject.waitForFloatArray()[0]);
+
+ executeJavaScript("testObject.setDoubleArray([null]);");
+ assertEquals(0.0, mTestObject.waitForDoubleArray()[0]);
+
+ executeJavaScript("testObject.setBooleanArray([null]);");
+ assertFalse(mTestObject.waitForBooleanArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should create array and pass null.
+ executeJavaScript("testObject.setObjectArray([null]);");
+ assertNull(mTestObject.waitForObjectArray());
+
+ executeJavaScript("testObject.setStringArray([null]);");
+ assertNull(mTestObject.waitForStringArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should create array and pass null.
+ executeJavaScript("testObject.setCustomTypeArray([null]);");
+ assertNull(mTestObject.waitForCustomTypeArray());
+ }
+
+ // Test passing an array of JavaScript undefined values to a method which
+ // takes a Java array.
+ public void testPassUndefined() throws Throwable {
+ executeJavaScript("testObject.setByteArray([undefined]);");
+ assertEquals(0, mTestObject.waitForByteArray()[0]);
+
+ executeJavaScript("testObject.setCharArray([undefined]);");
+ assertEquals(0, mTestObject.waitForCharArray()[0]);
+
+ executeJavaScript("testObject.setShortArray([undefined]);");
+ assertEquals(0, mTestObject.waitForShortArray()[0]);
+
+ executeJavaScript("testObject.setIntArray([undefined]);");
+ assertEquals(0, mTestObject.waitForIntArray()[0]);
+
+ executeJavaScript("testObject.setLongArray([undefined]);");
+ assertEquals(0L, mTestObject.waitForLongArray()[0]);
+
+ executeJavaScript("testObject.setFloatArray([undefined]);");
+ assertEquals(0.0f, mTestObject.waitForFloatArray()[0]);
+
+ executeJavaScript("testObject.setDoubleArray([undefined]);");
+ assertEquals(0.0, mTestObject.waitForDoubleArray()[0]);
+
+ executeJavaScript("testObject.setBooleanArray([undefined]);");
+ assertEquals(false, mTestObject.waitForBooleanArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should create array and pass null.
+ executeJavaScript("testObject.setObjectArray([undefined]);");
+ assertNull(mTestObject.waitForObjectArray());
+
+ executeJavaScript("testObject.setStringArray([undefined]);");
+ assertNull(mTestObject.waitForStringArray()[0]);
+
+ // LIVECONNECT_COMPLIANCE: Should create array and pass null.
+ executeJavaScript("testObject.setCustomTypeArray([undefined]);");
+ assertNull(mTestObject.waitForCustomTypeArray());
+ }
+}
diff --git a/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeArrayTest.java b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeArrayTest.java
new file mode 100644
index 0000000..2fd42a7
--- /dev/null
+++ b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeArrayTest.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Part of the test suite for the WebView's Java Bridge. This class tests the
+ * general use of arrays.
+ *
+ * The conversions should follow
+ * http://jdk6.java.net/plugin2/liveconnect/#JS_JAVA_CONVERSIONS. Places in
+ * which the implementation differs from the spec are marked with
+ * LIVECONNECT_COMPLIANCE.
+ * FIXME: Consider making our implementation more compliant, if it will not
+ * break backwards-compatibility. See b/4408210.
+ *
+ * To run this test ...
+ * adb shell am instrument -w -e class com.android.webviewtests.JavaBridgeArrayTest \
+ * com.android.webviewtests/android.test.InstrumentationTestRunner
+ */
+
+package com.android.webviewtests;
+
+public class JavaBridgeArrayTest extends JavaBridgeTestBase {
+ private class TestObject extends Controller {
+ private boolean mBooleanValue;
+ private int mIntValue;
+ private String mStringValue;
+
+ private int[] mIntArray;
+ private int[][] mIntIntArray;
+
+ private boolean mWasArrayMethodCalled;
+
+ public synchronized void setBooleanValue(boolean x) {
+ mBooleanValue = x;
+ notifyResultIsReady();
+ }
+ public synchronized void setIntValue(int x) {
+ mIntValue = x;
+ notifyResultIsReady();
+ }
+ public synchronized void setStringValue(String x) {
+ mStringValue = x;
+ notifyResultIsReady();
+ }
+
+ public synchronized boolean waitForBooleanValue() {
+ waitForResult();
+ return mBooleanValue;
+ }
+ public synchronized int waitForIntValue() {
+ waitForResult();
+ return mIntValue;
+ }
+ public synchronized String waitForStringValue() {
+ waitForResult();
+ return mStringValue;
+ }
+
+ public synchronized void setIntArray(int[] x) {
+ mIntArray = x;
+ notifyResultIsReady();
+ }
+ public synchronized void setIntIntArray(int[][] x) {
+ mIntIntArray = x;
+ notifyResultIsReady();
+ }
+
+ public synchronized int[] waitForIntArray() {
+ waitForResult();
+ return mIntArray;
+ }
+ public synchronized int[][] waitForIntIntArray() {
+ waitForResult();
+ return mIntIntArray;
+ }
+
+ public synchronized int[] arrayMethod() {
+ mWasArrayMethodCalled = true;
+ return new int[] {42, 43, 44};
+ }
+
+ public synchronized boolean wasArrayMethodCalled() {
+ return mWasArrayMethodCalled;
+ }
+ }
+
+ private TestObject mTestObject;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mTestObject = new TestObject();
+ setUpWebView(mTestObject, "testObject");
+ }
+
+ public void testArrayLength() throws Throwable {
+ executeJavaScript("testObject.setIntArray([42, 43, 44]);");
+ int[] result = mTestObject.waitForIntArray();
+ assertEquals(3, result.length);
+ assertEquals(42, result[0]);
+ assertEquals(43, result[1]);
+ assertEquals(44, result[2]);
+ }
+
+ public void testPassNull() throws Throwable {
+ executeJavaScript("testObject.setIntArray(null);");
+ assertNull(mTestObject.waitForIntArray());
+ }
+
+ public void testPassUndefined() throws Throwable {
+ executeJavaScript("testObject.setIntArray(undefined);");
+ assertNull(mTestObject.waitForIntArray());
+ }
+
+ public void testPassEmptyArray() throws Throwable {
+ executeJavaScript("testObject.setIntArray([]);");
+ assertEquals(0, mTestObject.waitForIntArray().length);
+ }
+
+ // Note that this requires being able to pass a string from JavaScript to
+ // Java.
+ public void testPassArrayToStringMethod() throws Throwable {
+ // LIVECONNECT_COMPLIANCE: Should call toString() on array.
+ executeJavaScript("testObject.setStringValue([42, 42, 42]);");
+ assertEquals("undefined", mTestObject.waitForStringValue());
+ }
+
+ // Note that this requires being able to pass an integer from JavaScript to
+ // Java.
+ public void testPassArrayToNonStringNonArrayMethod() throws Throwable {
+ // LIVECONNECT_COMPLIANCE: Should raise JavaScript exception.
+ executeJavaScript("testObject.setIntValue([42, 42, 42]);");
+ assertEquals(0, mTestObject.waitForIntValue());
+ }
+
+ public void testPassNonArrayToArrayMethod() throws Throwable {
+ // LIVECONNECT_COMPLIANCE: Should raise JavaScript exception.
+ executeJavaScript("testObject.setIntArray(42);");
+ assertNull(mTestObject.waitForIntArray());
+ }
+
+ public void testObjectWithLengthProperty() throws Throwable {
+ executeJavaScript("testObject.setIntArray({length: 3, 1: 42});");
+ int[] result = mTestObject.waitForIntArray();
+ assertEquals(3, result.length);
+ assertEquals(0, result[0]);
+ assertEquals(42, result[1]);
+ assertEquals(0, result[2]);
+ }
+
+ public void testNonNumericLengthProperty() throws Throwable {
+ // LIVECONNECT_COMPLIANCE: This should not count as an array, so we
+ // should raise a JavaScript exception.
+ executeJavaScript("testObject.setIntArray({length: \"foo\"});");
+ assertNull(mTestObject.waitForIntArray());
+ }
+
+ public void testLengthOutOfBounds() throws Throwable {
+ // LIVECONNECT_COMPLIANCE: This should not count as an array, so we
+ // should raise a JavaScript exception.
+ executeJavaScript("testObject.setIntArray({length: -1});");
+ assertNull(mTestObject.waitForIntArray());
+
+ // LIVECONNECT_COMPLIANCE: This should not count as an array, so we
+ // should raise a JavaScript exception.
+ long length = (long)Integer.MAX_VALUE + 1L;
+ executeJavaScript("testObject.setIntArray({length: " + length + "});");
+ assertNull(mTestObject.waitForIntArray());
+
+ // LIVECONNECT_COMPLIANCE: This should not count as an array, so we
+ // should raise a JavaScript exception.
+ length = (long)Integer.MAX_VALUE + 1L - (long)Integer.MIN_VALUE + 1L;
+ executeJavaScript("testObject.setIntArray({length: " + length + "});");
+ assertNull(mTestObject.waitForIntArray());
+ }
+
+ public void testSparseArray() throws Throwable {
+ executeJavaScript("var x = [42, 43]; x[3] = 45; testObject.setIntArray(x);");
+ int[] result = mTestObject.waitForIntArray();
+ assertEquals(4, result.length);
+ assertEquals(42, result[0]);
+ assertEquals(43, result[1]);
+ assertEquals(0, result[2]);
+ assertEquals(45, result[3]);
+ }
+
+ // Note that this requires being able to pass a boolean from JavaScript to
+ // Java.
+ public void testMethodReturningArrayNotCalled() throws Throwable {
+ // We don't invoke methods which return arrays, but note that no
+ // exception is raised.
+ // LIVECONNECT_COMPLIANCE: Should call method and convert result to
+ // JavaScript array.
+ executeJavaScript("testObject.setBooleanValue(undefined === testObject.arrayMethod())");
+ assertTrue(mTestObject.waitForBooleanValue());
+ assertFalse(mTestObject.wasArrayMethodCalled());
+ }
+
+ public void testMultiDimensionalArrayMethod() throws Throwable {
+ // LIVECONNECT_COMPLIANCE: Should handle multi-dimensional arrays.
+ executeJavaScript("testObject.setIntIntArray([ [42, 43], [44, 45] ]);");
+ assertNull(mTestObject.waitForIntIntArray());
+ }
+
+ public void testPassMultiDimensionalArray() throws Throwable {
+ // LIVECONNECT_COMPLIANCE: Should handle multi-dimensional arrays.
+ executeJavaScript("testObject.setIntArray([ [42, 43], [44, 45] ]);");
+ int[] result = mTestObject.waitForIntArray();
+ assertEquals(2, result.length);
+ assertEquals(0, result[0]);
+ assertEquals(0, result[1]);
+ }
+}
diff --git a/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeBasicsTest.java b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeBasicsTest.java
new file mode 100644
index 0000000..c9bbb77
--- /dev/null
+++ b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeBasicsTest.java
@@ -0,0 +1,396 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Part of the test suite for the WebView's Java Bridge. Tests a number of features including ...
+ * - The type of injected objects
+ * - The type of their methods
+ * - Replacing objects
+ * - Removing objects
+ * - Access control
+ * - Calling methods on returned objects
+ * - Multiply injected objects
+ * - Threading
+ * - Inheritance
+ *
+ * To run this test ...
+ * adb shell am instrument -w -e class com.android.webviewtests.JavaBridgeBasicsTest \
+ * com.android.webviewtests/android.test.InstrumentationTestRunner
+ */
+
+package com.android.webviewtests;
+
+public class JavaBridgeBasicsTest extends JavaBridgeTestBase {
+ private class TestController extends Controller {
+ private int mIntValue;
+ private long mLongValue;
+ private String mStringValue;
+ private boolean mBooleanValue;
+
+ public synchronized void setIntValue(int x) {
+ mIntValue = x;
+ notifyResultIsReady();
+ }
+ public synchronized void setLongValue(long x) {
+ mLongValue = x;
+ notifyResultIsReady();
+ }
+ public synchronized void setStringValue(String x) {
+ mStringValue = x;
+ notifyResultIsReady();
+ }
+ public synchronized void setBooleanValue(boolean x) {
+ mBooleanValue = x;
+ notifyResultIsReady();
+ }
+
+ public synchronized int waitForIntValue() {
+ waitForResult();
+ return mIntValue;
+ }
+ public synchronized long waitForLongValue() {
+ waitForResult();
+ return mLongValue;
+ }
+ public synchronized String waitForStringValue() {
+ waitForResult();
+ return mStringValue;
+ }
+ public synchronized boolean waitForBooleanValue() {
+ waitForResult();
+ return mBooleanValue;
+ }
+ }
+
+ private static class ObjectWithStaticMethod {
+ public static String staticMethod() {
+ return "foo";
+ }
+ }
+
+ TestController mTestController;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mTestController = new TestController();
+ setUpWebView(mTestController, "testController");
+ }
+
+ // Note that this requires that we can pass a JavaScript string to Java.
+ protected String executeJavaScriptAndGetStringResult(String script) throws Throwable {
+ executeJavaScript("testController.setStringValue(" + script + ");");
+ return mTestController.waitForStringValue();
+ }
+
+ protected void injectObjectAndReload(final Object object, final String name) throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ getWebView().addJavascriptInterface(object, name);
+ getWebView().reload();
+ }
+ });
+ mWebViewClient.waitForOnPageFinished();
+ }
+
+ // Note that this requires that we can pass a JavaScript boolean to Java.
+ private void assertRaisesException(String script) throws Throwable {
+ executeJavaScript("try {" +
+ script + ";" +
+ " testController.setBooleanValue(false);" +
+ "} catch (exception) {" +
+ " testController.setBooleanValue(true);" +
+ "}");
+ assertTrue(mTestController.waitForBooleanValue());
+ }
+
+ public void testTypeOfInjectedObject() throws Throwable {
+ assertEquals("object", executeJavaScriptAndGetStringResult("typeof testController"));
+ }
+
+ public void testAdditionNotReflectedUntilReload() throws Throwable {
+ assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof testObject"));
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ getWebView().addJavascriptInterface(new Object(), "testObject");
+ }
+ });
+ assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof testObject"));
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ getWebView().reload();
+ }
+ });
+ mWebViewClient.waitForOnPageFinished();
+ assertEquals("object", executeJavaScriptAndGetStringResult("typeof testObject"));
+ }
+
+ public void testRemovalNotReflectedUntilReload() throws Throwable {
+ injectObjectAndReload(new Object(), "testObject");
+ assertEquals("object", executeJavaScriptAndGetStringResult("typeof testObject"));
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ getWebView().removeJavascriptInterface("testObject");
+ }
+ });
+ assertEquals("object", executeJavaScriptAndGetStringResult("typeof testObject"));
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ getWebView().reload();
+ }
+ });
+ mWebViewClient.waitForOnPageFinished();
+ assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof testObject"));
+ }
+
+ public void testRemoveObjectNotAdded() throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ getWebView().removeJavascriptInterface("foo");
+ getWebView().reload();
+ }
+ });
+ mWebViewClient.waitForOnPageFinished();
+ assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof foo"));
+ }
+
+ public void testTypeOfMethod() throws Throwable {
+ assertEquals("function",
+ executeJavaScriptAndGetStringResult("typeof testController.setStringValue"));
+ }
+
+ public void testTypeOfInvalidMethod() throws Throwable {
+ assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof testController.foo"));
+ }
+
+ public void testCallingInvalidMethodRaisesException() throws Throwable {
+ assertRaisesException("testController.foo()");
+ }
+
+ // Note that this requires that we can pass a JavaScript string to Java.
+ public void testTypeOfStaticMethod() throws Throwable {
+ injectObjectAndReload(new ObjectWithStaticMethod(), "testObject");
+ executeJavaScript("testController.setStringValue(typeof testObject.staticMethod)");
+ assertEquals("function", mTestController.waitForStringValue());
+ }
+
+ // Note that this requires that we can pass a JavaScript string to Java.
+ public void testCallStaticMethod() throws Throwable {
+ injectObjectAndReload(new ObjectWithStaticMethod(), "testObject");
+ executeJavaScript("testController.setStringValue(testObject.staticMethod())");
+ assertEquals("foo", mTestController.waitForStringValue());
+ }
+
+ public void testPrivateMethodNotExposed() throws Throwable {
+ injectObjectAndReload(new Object() {
+ private void method() {}
+ }, "testObject");
+ assertEquals("undefined",
+ executeJavaScriptAndGetStringResult("typeof testObject.method"));
+ }
+
+ public void testReplaceInjectedObject() throws Throwable {
+ injectObjectAndReload(new Object() {
+ public void method() { mTestController.setStringValue("object 1"); }
+ }, "testObject");
+ executeJavaScript("testObject.method()");
+ assertEquals("object 1", mTestController.waitForStringValue());
+
+ injectObjectAndReload(new Object() {
+ public void method() { mTestController.setStringValue("object 2"); }
+ }, "testObject");
+ executeJavaScript("testObject.method()");
+ assertEquals("object 2", mTestController.waitForStringValue());
+ }
+
+ public void testInjectNullObjectIsIgnored() throws Throwable {
+ injectObjectAndReload(null, "testObject");
+ assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof testObject"));
+ }
+
+ public void testReplaceInjectedObjectWithNullObjectIsIgnored() throws Throwable {
+ injectObjectAndReload(new Object(), "testObject");
+ assertEquals("object", executeJavaScriptAndGetStringResult("typeof testObject"));
+ injectObjectAndReload(null, "testObject");
+ assertEquals("object", executeJavaScriptAndGetStringResult("typeof testObject"));
+ }
+
+ public void testCallOverloadedMethodWithDifferentNumberOfArguments() throws Throwable {
+ injectObjectAndReload(new Object() {
+ public void method() { mTestController.setStringValue("0 args"); }
+ public void method(int x) { mTestController.setStringValue("1 arg"); }
+ public void method(int x, int y) { mTestController.setStringValue("2 args"); }
+ }, "testObject");
+ executeJavaScript("testObject.method()");
+ assertEquals("0 args", mTestController.waitForStringValue());
+ executeJavaScript("testObject.method(42)");
+ assertEquals("1 arg", mTestController.waitForStringValue());
+ executeJavaScript("testObject.method(null)");
+ assertEquals("1 arg", mTestController.waitForStringValue());
+ executeJavaScript("testObject.method(undefined)");
+ assertEquals("1 arg", mTestController.waitForStringValue());
+ executeJavaScript("testObject.method(42, 42)");
+ assertEquals("2 args", mTestController.waitForStringValue());
+ }
+
+ public void testCallMethodWithWrongNumberOfArgumentsRaisesException() throws Throwable {
+ assertRaisesException("testController.setIntValue()");
+ assertRaisesException("testController.setIntValue(42, 42)");
+ }
+
+ public void testObjectPersistsAcrossPageLoads() throws Throwable {
+ assertEquals("object", executeJavaScriptAndGetStringResult("typeof testController"));
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ getWebView().reload();
+ }
+ });
+ mWebViewClient.waitForOnPageFinished();
+ assertEquals("object", executeJavaScriptAndGetStringResult("typeof testController"));
+ }
+
+ public void testSameObjectInjectedMultipleTimes() throws Throwable {
+ class TestObject {
+ private int mNumMethodInvocations;
+ public void method() { mTestController.setIntValue(++mNumMethodInvocations); }
+ }
+ final TestObject testObject = new TestObject();
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ getWebView().addJavascriptInterface(testObject, "testObject1");
+ getWebView().addJavascriptInterface(testObject, "testObject2");
+ getWebView().reload();
+ }
+ });
+ mWebViewClient.waitForOnPageFinished();
+ executeJavaScript("testObject1.method()");
+ assertEquals(1, mTestController.waitForIntValue());
+ executeJavaScript("testObject2.method()");
+ assertEquals(2, mTestController.waitForIntValue());
+ }
+
+ public void testCallMethodOnReturnedObject() throws Throwable {
+ injectObjectAndReload(new Object() {
+ public Object getInnerObject() {
+ return new Object() {
+ public void method(int x) { mTestController.setIntValue(x); }
+ };
+ }
+ }, "testObject");
+ executeJavaScript("testObject.getInnerObject().method(42)");
+ assertEquals(42, mTestController.waitForIntValue());
+ }
+
+ public void testReturnedObjectInjectedElsewhere() throws Throwable {
+ class InnerObject {
+ private int mNumMethodInvocations;
+ public void method() { mTestController.setIntValue(++mNumMethodInvocations); }
+ }
+ final InnerObject innerObject = new InnerObject();
+ final Object object = new Object() {
+ public InnerObject getInnerObject() {
+ return innerObject;
+ }
+ };
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ getWebView().addJavascriptInterface(object, "testObject");
+ getWebView().addJavascriptInterface(innerObject, "innerObject");
+ getWebView().reload();
+ }
+ });
+ mWebViewClient.waitForOnPageFinished();
+ executeJavaScript("testObject.getInnerObject().method()");
+ assertEquals(1, mTestController.waitForIntValue());
+ executeJavaScript("innerObject.method()");
+ assertEquals(2, mTestController.waitForIntValue());
+ }
+
+ public void testMethodInvokedOnBackgroundThread() throws Throwable {
+ injectObjectAndReload(new Object() {
+ public void captureThreadId() {
+ mTestController.setLongValue(Thread.currentThread().getId());
+ }
+ }, "testObject");
+ executeJavaScript("testObject.captureThreadId()");
+ final long threadId = mTestController.waitForLongValue();
+ assertFalse(threadId == Thread.currentThread().getId());
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ assertFalse(threadId == Thread.currentThread().getId());
+ }
+ });
+ }
+
+ public void testPublicInheritedMethod() throws Throwable {
+ class Base {
+ public void method(int x) { mTestController.setIntValue(x); }
+ }
+ class Derived extends Base {
+ }
+ injectObjectAndReload(new Derived(), "testObject");
+ assertEquals("function", executeJavaScriptAndGetStringResult("typeof testObject.method"));
+ executeJavaScript("testObject.method(42)");
+ assertEquals(42, mTestController.waitForIntValue());
+ }
+
+ public void testPrivateInheritedMethod() throws Throwable {
+ class Base {
+ private void method() {}
+ }
+ class Derived extends Base {
+ }
+ injectObjectAndReload(new Derived(), "testObject");
+ assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof testObject.method"));
+ }
+
+ public void testOverriddenMethod() throws Throwable {
+ class Base {
+ public void method() { mTestController.setStringValue("base"); }
+ }
+ class Derived extends Base {
+ public void method() { mTestController.setStringValue("derived"); }
+ }
+ injectObjectAndReload(new Derived(), "testObject");
+ executeJavaScript("testObject.method()");
+ assertEquals("derived", mTestController.waitForStringValue());
+ }
+
+ public void testEnumerateMembers() throws Throwable {
+ injectObjectAndReload(new Object() {
+ public void method() {}
+ private void privateMethod() {}
+ public int field;
+ private int privateField;
+ }, "testObject");
+ executeJavaScript(
+ "var result = \"\"; " +
+ "for (x in testObject) { result += \" \" + x } " +
+ "testController.setStringValue(result);");
+ // LIVECONNECT_COMPLIANCE: Should be able to enumerate members.
+ assertEquals("", mTestController.waitForStringValue());
+ }
+}
diff --git a/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeCoercionTest.java b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeCoercionTest.java
new file mode 100644
index 0000000..a0f78a4
--- /dev/null
+++ b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeCoercionTest.java
@@ -0,0 +1,646 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Part of the test suite for the WebView's Java Bridge. This class tests that
+ * we correctly convert JavaScript values to Java values when passing them to
+ * the methods of injected Java objects.
+ *
+ * The conversions should follow
+ * http://jdk6.java.net/plugin2/liveconnect/#JS_JAVA_CONVERSIONS. Places in
+ * which the implementation differs from the spec are marked with
+ * LIVECONNECT_COMPLIANCE.
+ * FIXME: Consider making our implementation more compliant, if it will not
+ * break backwards-compatibility. See b/4408210.
+ *
+ * To run this test ...
+ * adb shell am instrument -w -e class com.android.webviewtests.JavaBridgeCoercionTest \
+ * com.android.webviewtests/android.test.InstrumentationTestRunner
+ */
+
+package com.android.webviewtests;
+
+public class JavaBridgeCoercionTest extends JavaBridgeTestBase {
+ private class TestObject extends Controller {
+ private Object objectInstance;
+ private CustomType customTypeInstance;
+ private CustomType2 customType2Instance;
+
+ private boolean mBooleanValue;
+ private byte mByteValue;
+ private char mCharValue;
+ private short mShortValue;
+ private int mIntValue;
+ private long mLongValue;
+ private float mFloatValue;
+ private double mDoubleValue;
+ private String mStringValue;
+ private Object mObjectValue;
+ private CustomType mCustomTypeValue;
+
+ public TestObject() {
+ objectInstance = new Object();
+ customTypeInstance = new CustomType();
+ customType2Instance = new CustomType2();
+ }
+
+ public Object getObjectInstance() {
+ return objectInstance;
+ }
+ public CustomType getCustomTypeInstance() {
+ return customTypeInstance;
+ }
+ public CustomType2 getCustomType2Instance() {
+ return customType2Instance;
+ }
+
+ public synchronized void setBooleanValue(boolean x) {
+ mBooleanValue = x;
+ notifyResultIsReady();
+ }
+ public synchronized void setByteValue(byte x) {
+ mByteValue = x;
+ notifyResultIsReady();
+ }
+ public synchronized void setCharValue(char x) {
+ mCharValue = x;
+ notifyResultIsReady();
+ }
+ public synchronized void setShortValue(short x) {
+ mShortValue = x;
+ notifyResultIsReady();
+ }
+ public synchronized void setIntValue(int x) {
+ mIntValue = x;
+ notifyResultIsReady();
+ }
+ public synchronized void setLongValue(long x) {
+ mLongValue = x;
+ notifyResultIsReady();
+ }
+ public synchronized void setFloatValue(float x) {
+ mFloatValue = x;
+ notifyResultIsReady();
+ }
+ public synchronized void setDoubleValue(double x) {
+ mDoubleValue = x;
+ notifyResultIsReady();
+ }
+ public synchronized void setStringValue(String x) {
+ mStringValue = x;
+ notifyResultIsReady();
+ }
+ public synchronized void setObjectValue(Object x) {
+ mObjectValue = x;
+ notifyResultIsReady();
+ }
+ public synchronized void setCustomTypeValue(CustomType x) {
+ mCustomTypeValue = x;
+ notifyResultIsReady();
+ }
+
+ public synchronized boolean waitForBooleanValue() {
+ waitForResult();
+ return mBooleanValue;
+ }
+ public synchronized byte waitForByteValue() {
+ waitForResult();
+ return mByteValue;
+ }
+ public synchronized char waitForCharValue() {
+ waitForResult();
+ return mCharValue;
+ }
+ public synchronized short waitForShortValue() {
+ waitForResult();
+ return mShortValue;
+ }
+ public synchronized int waitForIntValue() {
+ waitForResult();
+ return mIntValue;
+ }
+ public synchronized long waitForLongValue() {
+ waitForResult();
+ return mLongValue;
+ }
+ public synchronized float waitForFloatValue() {
+ waitForResult();
+ return mFloatValue;
+ }
+ public synchronized double waitForDoubleValue() {
+ waitForResult();
+ return mDoubleValue;
+ }
+ public synchronized String waitForStringValue() {
+ waitForResult();
+ return mStringValue;
+ }
+ public synchronized Object waitForObjectValue() {
+ waitForResult();
+ return mObjectValue;
+ }
+ public synchronized CustomType waitForCustomTypeValue() {
+ waitForResult();
+ return mCustomTypeValue;
+ }
+ }
+
+ // Two custom types used when testing passing objects.
+ private static class CustomType {
+ }
+ private static class CustomType2 {
+ }
+
+ private TestObject mTestObject;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mTestObject = new TestObject();
+ setUpWebView(mTestObject, "testObject");
+ }
+
+ // Test passing a JavaScript number in the int32 range to a method of an
+ // injected object.
+ public void testPassNumberInt32() throws Throwable {
+ executeJavaScript("testObject.setByteValue(42);");
+ assertEquals(42, mTestObject.waitForByteValue());
+ executeJavaScript("testObject.setByteValue(" + Byte.MAX_VALUE + " + 42);");
+ assertEquals(Byte.MIN_VALUE + 42 - 1, mTestObject.waitForByteValue());
+
+ // LIVECONNECT_COMPLIANCE: Should convert to numeric char value.
+ executeJavaScript("testObject.setCharValue(42);");
+ assertEquals('\u0000', mTestObject.waitForCharValue());
+
+ executeJavaScript("testObject.setShortValue(42);");
+ assertEquals(42, mTestObject.waitForShortValue());
+ executeJavaScript("testObject.setShortValue(" + Short.MAX_VALUE + " + 42);");
+ assertEquals(Short.MIN_VALUE + 42 - 1, mTestObject.waitForShortValue());
+
+ executeJavaScript("testObject.setIntValue(42);");
+ assertEquals(42, mTestObject.waitForIntValue());
+
+ executeJavaScript("testObject.setLongValue(42);");
+ assertEquals(42L, mTestObject.waitForLongValue());
+
+ executeJavaScript("testObject.setFloatValue(42);");
+ assertEquals(42.0f, mTestObject.waitForFloatValue());
+
+ executeJavaScript("testObject.setDoubleValue(42);");
+ assertEquals(42.0, mTestObject.waitForDoubleValue());
+
+ // LIVECONNECT_COMPLIANCE: Should create an instance of java.lang.Number.
+ executeJavaScript("testObject.setObjectValue(42);");
+ assertNull(mTestObject.waitForObjectValue());
+
+ // The spec allows the JS engine flexibility in how to format the number.
+ executeJavaScript("testObject.setStringValue(42);");
+ String str = mTestObject.waitForStringValue();
+ assertTrue("42".equals(str) || "42.0".equals(str));
+
+ executeJavaScript("testObject.setBooleanValue(0);");
+ assertFalse(mTestObject.waitForBooleanValue());
+ // LIVECONNECT_COMPLIANCE: Should be true;
+ executeJavaScript("testObject.setBooleanValue(42);");
+ assertFalse(mTestObject.waitForBooleanValue());
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setCustomTypeValue(42);");
+ assertNull(mTestObject.waitForCustomTypeValue());
+ }
+
+ // Test passing a JavaScript number in the double range to a method of an
+ // injected object.
+ public void testPassNumberDouble() throws Throwable {
+ executeJavaScript("testObject.setByteValue(42.1);");
+ assertEquals(42, mTestObject.waitForByteValue());
+ executeJavaScript("testObject.setByteValue(" + Byte.MAX_VALUE + " + 42.1);");
+ assertEquals(Byte.MIN_VALUE + 42 - 1, mTestObject.waitForByteValue());
+ executeJavaScript("testObject.setByteValue(" + Integer.MAX_VALUE + " + 42.1);");
+ assertEquals(-1, mTestObject.waitForByteValue());
+
+ // LIVECONNECT_COMPLIANCE: Should convert to numeric char value.
+ executeJavaScript("testObject.setCharValue(42.1);");
+ assertEquals('\u0000', mTestObject.waitForCharValue());
+
+ executeJavaScript("testObject.setShortValue(42.1);");
+ assertEquals(42, mTestObject.waitForShortValue());
+ executeJavaScript("testObject.setShortValue(" + Short.MAX_VALUE + " + 42.1);");
+ assertEquals(Short.MIN_VALUE + 42 - 1, mTestObject.waitForShortValue());
+ executeJavaScript("testObject.setShortValue(" + Integer.MAX_VALUE + " + 42.1);");
+ assertEquals(-1, mTestObject.waitForShortValue());
+
+ executeJavaScript("testObject.setIntValue(42.1);");
+ assertEquals(42, mTestObject.waitForIntValue());
+ executeJavaScript("testObject.setIntValue(" + Integer.MAX_VALUE + " + 42.1);");
+ assertEquals(Integer.MAX_VALUE, mTestObject.waitForIntValue());
+
+ executeJavaScript("testObject.setLongValue(42.1);");
+ assertEquals(42L, mTestObject.waitForLongValue());
+ // LIVECONNECT_COMPLIANCE: Should be Long.MAX_VALUE.
+ executeJavaScript("testObject.setLongValue(" + Long.MAX_VALUE + " + 42.1);");
+ assertEquals(Long.MIN_VALUE, mTestObject.waitForLongValue());
+
+ executeJavaScript("testObject.setFloatValue(42.1);");
+ assertEquals(42.1f, mTestObject.waitForFloatValue());
+
+ executeJavaScript("testObject.setDoubleValue(42.1);");
+ assertEquals(42.1, mTestObject.waitForDoubleValue());
+
+ // LIVECONNECT_COMPLIANCE: Should create an instance of java.lang.Number.
+ executeJavaScript("testObject.setObjectValue(42.1);");
+ assertNull(mTestObject.waitForObjectValue());
+
+ executeJavaScript("testObject.setStringValue(42.1);");
+ assertEquals("42.1", mTestObject.waitForStringValue());
+
+ executeJavaScript("testObject.setBooleanValue(0.0);");
+ assertFalse(mTestObject.waitForBooleanValue());
+ // LIVECONNECT_COMPLIANCE: Should be true.
+ executeJavaScript("testObject.setBooleanValue(42.1);");
+ assertFalse(mTestObject.waitForBooleanValue());
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setCustomTypeValue(42.1);");
+ assertNull(mTestObject.waitForCustomTypeValue());
+ }
+
+ // Test passing JavaScript NaN to a method of an injected object.
+ public void testPassNumberNaN() throws Throwable {
+ executeJavaScript("testObject.setByteValue(Number.NaN);");
+ assertEquals(0, mTestObject.waitForByteValue());
+
+ executeJavaScript("testObject.setCharValue(Number.NaN);");
+ assertEquals('\u0000', mTestObject.waitForCharValue());
+
+ executeJavaScript("testObject.setShortValue(Number.NaN);");
+ assertEquals(0, mTestObject.waitForShortValue());
+
+ executeJavaScript("testObject.setIntValue(Number.NaN);");
+ assertEquals(0, mTestObject.waitForIntValue());
+
+ executeJavaScript("testObject.setLongValue(Number.NaN);");
+ assertEquals(0L, mTestObject.waitForLongValue());
+
+ executeJavaScript("testObject.setFloatValue(Number.NaN);");
+ assertEquals(Float.NaN, mTestObject.waitForFloatValue());
+
+ executeJavaScript("testObject.setDoubleValue(Number.NaN);");
+ assertEquals(Double.NaN, mTestObject.waitForDoubleValue());
+
+ // LIVECONNECT_COMPLIANCE: Should create an instance of java.lang.Number.
+ executeJavaScript("testObject.setObjectValue(Number.NaN);");
+ assertNull(mTestObject.waitForObjectValue());
+
+ executeJavaScript("testObject.setStringValue(Number.NaN);");
+ assertEquals("NaN", mTestObject.waitForStringValue());
+
+ executeJavaScript("testObject.setBooleanValue(Number.NaN);");
+ assertFalse(mTestObject.waitForBooleanValue());
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setCustomTypeValue(Number.NaN);");
+ assertNull(mTestObject.waitForCustomTypeValue());
+ }
+
+ // Test passing JavaScript infinity to a method of an injected object.
+ public void testPassNumberInfinity() throws Throwable {
+ executeJavaScript("testObject.setByteValue(Infinity);");
+ assertEquals(-1, mTestObject.waitForByteValue());
+
+ // LIVECONNECT_COMPLIANCE: Should convert to maximum numeric char value.
+ executeJavaScript("testObject.setCharValue(Infinity);");
+ assertEquals('\u0000', mTestObject.waitForCharValue());
+
+ executeJavaScript("testObject.setShortValue(Infinity);");
+ assertEquals(-1, mTestObject.waitForShortValue());
+
+ executeJavaScript("testObject.setIntValue(Infinity);");
+ assertEquals(Integer.MAX_VALUE, mTestObject.waitForIntValue());
+
+ // LIVECONNECT_COMPLIANCE: Should be Long.MAX_VALUE.
+ executeJavaScript("testObject.setLongValue(Infinity);");
+ assertEquals(-1L, mTestObject.waitForLongValue());
+
+ executeJavaScript("testObject.setFloatValue(Infinity);");
+ assertEquals(Float.POSITIVE_INFINITY, mTestObject.waitForFloatValue());
+
+ executeJavaScript("testObject.setDoubleValue(Infinity);");
+ assertEquals(Double.POSITIVE_INFINITY, mTestObject.waitForDoubleValue());
+
+ // LIVECONNECT_COMPLIANCE: Should create an instance of java.lang.Number.
+ executeJavaScript("testObject.setObjectValue(Infinity);");
+ assertNull(mTestObject.waitForObjectValue());
+
+ executeJavaScript("testObject.setStringValue(Infinity);");
+ assertEquals("Inf", mTestObject.waitForStringValue());
+
+ executeJavaScript("testObject.setBooleanValue(Infinity);");
+ assertFalse(mTestObject.waitForBooleanValue());
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setCustomTypeValue(Infinity);");
+ assertNull(mTestObject.waitForCustomTypeValue());
+ }
+
+ // Test passing a JavaScript boolean to a method of an injected object.
+ public void testPassBoolean() throws Throwable {
+ executeJavaScript("testObject.setBooleanValue(true);");
+ assertTrue(mTestObject.waitForBooleanValue());
+ executeJavaScript("testObject.setBooleanValue(false);");
+ assertFalse(mTestObject.waitForBooleanValue());
+
+ // LIVECONNECT_COMPLIANCE: Should create an instance of java.lang.Boolean.
+ executeJavaScript("testObject.setObjectValue(true);");
+ assertNull(mTestObject.waitForObjectValue());
+
+ executeJavaScript("testObject.setStringValue(false);");
+ assertEquals("false", mTestObject.waitForStringValue());
+ executeJavaScript("testObject.setStringValue(true);");
+ assertEquals("true", mTestObject.waitForStringValue());
+
+ // LIVECONNECT_COMPLIANCE: Should be 1.
+ executeJavaScript("testObject.setByteValue(true);");
+ assertEquals(0, mTestObject.waitForByteValue());
+ executeJavaScript("testObject.setByteValue(false);");
+ assertEquals(0, mTestObject.waitForByteValue());
+
+ // LIVECONNECT_COMPLIANCE: Should convert to numeric char value 1.
+ executeJavaScript("testObject.setCharValue(true);");
+ assertEquals('\u0000', mTestObject.waitForCharValue());
+ executeJavaScript("testObject.setCharValue(false);");
+ assertEquals('\u0000', mTestObject.waitForCharValue());
+
+ // LIVECONNECT_COMPLIANCE: Should be 1.
+ executeJavaScript("testObject.setShortValue(true);");
+ assertEquals(0, mTestObject.waitForShortValue());
+ executeJavaScript("testObject.setShortValue(false);");
+ assertEquals(0, mTestObject.waitForShortValue());
+
+ // LIVECONNECT_COMPLIANCE: Should be 1.
+ executeJavaScript("testObject.setIntValue(true);");
+ assertEquals(0, mTestObject.waitForIntValue());
+ executeJavaScript("testObject.setIntValue(false);");
+ assertEquals(0, mTestObject.waitForIntValue());
+
+ // LIVECONNECT_COMPLIANCE: Should be 1.
+ executeJavaScript("testObject.setLongValue(true);");
+ assertEquals(0L, mTestObject.waitForLongValue());
+ executeJavaScript("testObject.setLongValue(false);");
+ assertEquals(0L, mTestObject.waitForLongValue());
+
+ // LIVECONNECT_COMPLIANCE: Should be 1.0.
+ executeJavaScript("testObject.setFloatValue(true);");
+ assertEquals(0.0f, mTestObject.waitForFloatValue());
+ executeJavaScript("testObject.setFloatValue(false);");
+ assertEquals(0.0f, mTestObject.waitForFloatValue());
+
+ // LIVECONNECT_COMPLIANCE: Should be 1.0.
+ executeJavaScript("testObject.setDoubleValue(true);");
+ assertEquals(0.0, mTestObject.waitForDoubleValue());
+ executeJavaScript("testObject.setDoubleValue(false);");
+ assertEquals(0.0, mTestObject.waitForDoubleValue());
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setCustomTypeValue(true);");
+ assertNull(mTestObject.waitForCustomTypeValue());
+ }
+
+ // Test passing a JavaScript string to a method of an injected object.
+ public void testPassString() throws Throwable {
+ executeJavaScript("testObject.setStringValue(\"+042.10\");");
+ assertEquals("+042.10", mTestObject.waitForStringValue());
+
+ // Make sure that we distinguish between the empty string and NULL.
+ executeJavaScript("testObject.setStringValue(\"\");");
+ assertEquals("", mTestObject.waitForStringValue());
+
+ // LIVECONNECT_COMPLIANCE: Should create an instance of java.lang.String.
+ executeJavaScript("testObject.setObjectValue(\"+042.10\");");
+ assertNull(mTestObject.waitForObjectValue());
+
+ // LIVECONNECT_COMPLIANCE: Should use valueOf() of appropriate type.
+ executeJavaScript("testObject.setByteValue(\"+042.10\");");
+ assertEquals(0, mTestObject.waitForByteValue());
+
+ // LIVECONNECT_COMPLIANCE: Should use valueOf() of appropriate type.
+ executeJavaScript("testObject.setShortValue(\"+042.10\");");
+ assertEquals(0, mTestObject.waitForShortValue());
+
+ // LIVECONNECT_COMPLIANCE: Should use valueOf() of appropriate type.
+ executeJavaScript("testObject.setIntValue(\"+042.10\");");
+ assertEquals(0, mTestObject.waitForIntValue());
+
+ // LIVECONNECT_COMPLIANCE: Should use valueOf() of appropriate type.
+ executeJavaScript("testObject.setLongValue(\"+042.10\");");
+ assertEquals(0L, mTestObject.waitForLongValue());
+
+ // LIVECONNECT_COMPLIANCE: Should use valueOf() of appropriate type.
+ executeJavaScript("testObject.setFloatValue(\"+042.10\");");
+ assertEquals(0.0f, mTestObject.waitForFloatValue());
+
+ // LIVECONNECT_COMPLIANCE: Should use valueOf() of appropriate type.
+ executeJavaScript("testObject.setDoubleValue(\"+042.10\");");
+ assertEquals(0.0, mTestObject.waitForDoubleValue());
+
+ // LIVECONNECT_COMPLIANCE: Should decode and convert to numeric char value.
+ executeJavaScript("testObject.setCharValue(\"+042.10\");");
+ assertEquals('\u0000', mTestObject.waitForCharValue());
+
+ // LIVECONNECT_COMPLIANCE: Non-empty string should convert to true.
+ executeJavaScript("testObject.setBooleanValue(\"+042.10\");");
+ assertFalse(mTestObject.waitForBooleanValue());
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setCustomTypeValue(\"+042.10\");");
+ assertNull(mTestObject.waitForCustomTypeValue());
+ }
+
+ // Test passing a JavaScript object to a method of an injected object.
+ public void testPassJavaScriptObject() throws Throwable {
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setObjectValue({foo: 42});");
+ assertNull(mTestObject.waitForObjectValue());
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setCustomTypeValue({foo: 42});");
+ assertNull(mTestObject.waitForCustomTypeValue());
+
+ // LIVECONNECT_COMPLIANCE: Should call toString() on object.
+ executeJavaScript("testObject.setStringValue({foo: 42});");
+ assertEquals("undefined", mTestObject.waitForStringValue());
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setByteValue({foo: 42});");
+ assertEquals(0, mTestObject.waitForByteValue());
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setCharValue({foo: 42});");
+ assertEquals('\u0000', mTestObject.waitForCharValue());
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setShortValue({foo: 42});");
+ assertEquals(0, mTestObject.waitForShortValue());
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setIntValue({foo: 42});");
+ assertEquals(0, mTestObject.waitForIntValue());
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setLongValue({foo: 42});");
+ assertEquals(0L, mTestObject.waitForLongValue());
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setFloatValue({foo: 42});");
+ assertEquals(0.0f, mTestObject.waitForFloatValue());
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setDoubleValue({foo: 42});");
+ assertEquals(0.0, mTestObject.waitForDoubleValue());
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setBooleanValue({foo: 42});");
+ assertFalse(mTestObject.waitForBooleanValue());
+ }
+
+ // Test passing a Java object to a method of an injected object. Note that
+ // this test requires being able to return objects from the methods of
+ // injected objects. This is tested elsewhere.
+ public void testPassJavaObject() throws Throwable {
+ executeJavaScript("testObject.setObjectValue(testObject.getObjectInstance());");
+ assertTrue(mTestObject.getObjectInstance() == mTestObject.waitForObjectValue());
+ executeJavaScript("testObject.setObjectValue(testObject.getCustomTypeInstance());");
+ assertTrue(mTestObject.getCustomTypeInstance() == mTestObject.waitForObjectValue());
+
+ executeJavaScript("testObject.setCustomTypeValue(testObject.getObjectInstance());");
+ assertTrue(mTestObject.getObjectInstance() == mTestObject.waitForCustomTypeValue());
+ executeJavaScript("testObject.setCustomTypeValue(testObject.getCustomTypeInstance());");
+ assertTrue(mTestObject.getCustomTypeInstance() == mTestObject.waitForCustomTypeValue());
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception, as the types are unrelated.
+ executeJavaScript("testObject.setCustomTypeValue(testObject.getCustomType2Instance());");
+ assertTrue(mTestObject.getCustomType2Instance() ==
+ (Object)mTestObject.waitForCustomTypeValue());
+
+ // LIVECONNECT_COMPLIANCE: Should call toString() on object.
+ executeJavaScript("testObject.setStringValue(testObject.getObjectInstance());");
+ assertEquals("undefined", mTestObject.waitForStringValue());
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setByteValue(testObject.getObjectInstance());");
+ assertEquals(0, mTestObject.waitForByteValue());
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setCharValue(testObject.getObjectInstance());");
+ assertEquals('\u0000', mTestObject.waitForCharValue());
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setShortValue(testObject.getObjectInstance());");
+ assertEquals(0, mTestObject.waitForShortValue());
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setIntValue(testObject.getObjectInstance());");
+ assertEquals(0, mTestObject.waitForIntValue());
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setLongValue(testObject.getObjectInstance());");
+ assertEquals(0L, mTestObject.waitForLongValue());
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setFloatValue(testObject.getObjectInstance());");
+ assertEquals(0.0f, mTestObject.waitForFloatValue());
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setDoubleValue(testObject.getObjectInstance());");
+ assertEquals(0.0, mTestObject.waitForDoubleValue());
+
+ // LIVECONNECT_COMPLIANCE: Should raise a JavaScript exception.
+ executeJavaScript("testObject.setBooleanValue(testObject.getObjectInstance());");
+ assertFalse(mTestObject.waitForBooleanValue());
+ }
+
+ // Test passing JavaScript null to a method of an injected object.
+ public void testPassNull() throws Throwable {
+ executeJavaScript("testObject.setObjectValue(null);");
+ assertNull(mTestObject.waitForObjectValue());
+
+ executeJavaScript("testObject.setCustomTypeValue(null);");
+ assertNull(mTestObject.waitForCustomTypeValue());
+
+ executeJavaScript("testObject.setStringValue(null);");
+ assertNull(mTestObject.waitForStringValue());
+
+ executeJavaScript("testObject.setByteValue(null);");
+ assertEquals(0, mTestObject.waitForByteValue());
+
+ executeJavaScript("testObject.setCharValue(null);");
+ assertEquals('\u0000', mTestObject.waitForCharValue());
+
+ executeJavaScript("testObject.setShortValue(null);");
+ assertEquals(0, mTestObject.waitForShortValue());
+
+ executeJavaScript("testObject.setIntValue(null);");
+ assertEquals(0, mTestObject.waitForIntValue());
+
+ executeJavaScript("testObject.setLongValue(null);");
+ assertEquals(0L, mTestObject.waitForLongValue());
+
+ executeJavaScript("testObject.setFloatValue(null);");
+ assertEquals(0.0f, mTestObject.waitForFloatValue());
+
+ executeJavaScript("testObject.setDoubleValue(null);");
+ assertEquals(0.0, mTestObject.waitForDoubleValue());
+
+ executeJavaScript("testObject.setBooleanValue(null);");
+ assertFalse(mTestObject.waitForBooleanValue());
+ }
+
+ // Test passing JavaScript undefined to a method of an injected object.
+ public void testPassUndefined() throws Throwable {
+ executeJavaScript("testObject.setObjectValue(undefined);");
+ assertNull(mTestObject.waitForObjectValue());
+
+ executeJavaScript("testObject.setCustomTypeValue(undefined);");
+ assertNull(mTestObject.waitForCustomTypeValue());
+
+ // LIVECONNECT_COMPLIANCE: Should be NULL.
+ executeJavaScript("testObject.setStringValue(undefined);");
+ assertEquals("undefined", mTestObject.waitForStringValue());
+
+ executeJavaScript("testObject.setByteValue(undefined);");
+ assertEquals(0, mTestObject.waitForByteValue());
+
+ executeJavaScript("testObject.setCharValue(undefined);");
+ assertEquals('\u0000', mTestObject.waitForCharValue());
+
+ executeJavaScript("testObject.setShortValue(undefined);");
+ assertEquals(0, mTestObject.waitForShortValue());
+
+ executeJavaScript("testObject.setIntValue(undefined);");
+ assertEquals(0, mTestObject.waitForIntValue());
+
+ executeJavaScript("testObject.setLongValue(undefined);");
+ assertEquals(0L, mTestObject.waitForLongValue());
+
+ executeJavaScript("testObject.setFloatValue(undefined);");
+ assertEquals(0.0f, mTestObject.waitForFloatValue());
+
+ executeJavaScript("testObject.setDoubleValue(undefined);");
+ assertEquals(0.0, mTestObject.waitForDoubleValue());
+
+ executeJavaScript("testObject.setBooleanValue(undefined);");
+ assertFalse(mTestObject.waitForBooleanValue());
+ }
+}
diff --git a/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeFieldsTest.java b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeFieldsTest.java
new file mode 100644
index 0000000..0ccd175
--- /dev/null
+++ b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeFieldsTest.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Part of the test suite for the WebView's Java Bridge. This test tests the
+ * use of fields.
+ *
+ * To run this test ...
+ * adb shell am instrument -w -e class com.android.webviewtests.JavaBridgeFieldsTest \
+ * com.android.webviewtests/android.test.InstrumentationTestRunner
+ */
+
+package com.android.webviewtests;
+
+public class JavaBridgeFieldsTest extends JavaBridgeTestBase {
+ private class TestObject extends Controller {
+ private String mStringValue;
+
+ // These methods are used to control the test.
+ public synchronized void setStringValue(String x) {
+ mStringValue = x;
+ notifyResultIsReady();
+ }
+ public synchronized String waitForStringValue() {
+ waitForResult();
+ return mStringValue;
+ }
+
+ public boolean booleanField = true;
+ public byte byteField = 42;
+ public char charField = '\u002A';
+ public short shortField = 42;
+ public int intField = 42;
+ public long longField = 42L;
+ public float floatField = 42.0f;
+ public double doubleField = 42.0;
+ public String stringField = "foo";
+ public Object objectField = new Object();
+ public CustomType customTypeField = new CustomType();
+ }
+
+ // A custom type used when testing passing objects.
+ private class CustomType {
+ }
+
+ TestObject mTestObject;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mTestObject = new TestObject();
+ setUpWebView(mTestObject, "testObject");
+ }
+
+ // Note that this requires that we can pass a JavaScript string to Java.
+ protected String executeJavaScriptAndGetStringResult(String script) throws Throwable {
+ executeJavaScript("testObject.setStringValue(" + script + ");");
+ return mTestObject.waitForStringValue();
+ }
+
+ // The Java bridge does not provide access to fields.
+ // FIXME: Consider providing support for this. See See b/4408210.
+ public void testFieldTypes() throws Throwable {
+ assertEquals("undefined",
+ executeJavaScriptAndGetStringResult("typeof testObject.booleanField"));
+ assertEquals("undefined",
+ executeJavaScriptAndGetStringResult("typeof testObject.byteField"));
+ assertEquals("undefined",
+ executeJavaScriptAndGetStringResult("typeof testObject.charField"));
+ assertEquals("undefined",
+ executeJavaScriptAndGetStringResult("typeof testObject.shortField"));
+ assertEquals("undefined",
+ executeJavaScriptAndGetStringResult("typeof testObject.intField"));
+ assertEquals("undefined",
+ executeJavaScriptAndGetStringResult("typeof testObject.longField"));
+ assertEquals("undefined",
+ executeJavaScriptAndGetStringResult("typeof testObject.floatField"));
+ assertEquals("undefined",
+ executeJavaScriptAndGetStringResult("typeof testObject.doubleField"));
+ assertEquals("undefined",
+ executeJavaScriptAndGetStringResult("typeof testObject.objectField"));
+ assertEquals("undefined",
+ executeJavaScriptAndGetStringResult("typeof testObject.stringField"));
+ assertEquals("undefined",
+ executeJavaScriptAndGetStringResult("typeof testObject.customTypeField"));
+ }
+}
diff --git a/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeReturnValuesTest.java b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeReturnValuesTest.java
new file mode 100644
index 0000000..44d5cc6
--- /dev/null
+++ b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeReturnValuesTest.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Part of the test suite for the WebView's Java Bridge. This test checks that
+ * we correctly convert Java values to JavaScript values when returning them
+ * from the methods of injected Java objects.
+ *
+ * The conversions should follow
+ * http://jdk6.java.net/plugin2/liveconnect/#JS_JAVA_CONVERSIONS. Places in
+ * which the implementation differs from the spec are marked with
+ * LIVECONNECT_COMPLIANCE.
+ * FIXME: Consider making our implementation more compliant, if it will not
+ * break backwards-compatibility. See b/4408210.
+ *
+ * To run this test ...
+ * adb shell am instrument -w -e class com.android.webviewtests.JavaBridgeReturnValuesTest \
+ * com.android.webviewtests/android.test.InstrumentationTestRunner
+ */
+
+package com.android.webviewtests;
+
+public class JavaBridgeReturnValuesTest extends JavaBridgeTestBase {
+ // An instance of this class is injected into the page to test returning
+ // Java values to JavaScript.
+ private class TestObject extends Controller {
+ private String mStringValue;
+ private boolean mBooleanValue;
+
+ // These four methods are used to control the test.
+ public synchronized void setStringValue(String x) {
+ mStringValue = x;
+ notifyResultIsReady();
+ }
+ public synchronized String waitForStringValue() {
+ waitForResult();
+ return mStringValue;
+ }
+ public synchronized void setBooleanValue(boolean x) {
+ mBooleanValue = x;
+ notifyResultIsReady();
+ }
+ public synchronized boolean waitForBooleanValue() {
+ waitForResult();
+ return mBooleanValue;
+ }
+
+ public boolean getBooleanValue() {
+ return true;
+ }
+ public byte getByteValue() {
+ return 42;
+ }
+ public char getCharValue() {
+ return '\u002A';
+ }
+ public short getShortValue() {
+ return 42;
+ }
+ public int getIntValue() {
+ return 42;
+ }
+ public long getLongValue() {
+ return 42L;
+ }
+ public float getFloatValue() {
+ return 42.1f;
+ }
+ public float getFloatValueNoDecimal() {
+ return 42.0f;
+ }
+ public double getDoubleValue() {
+ return 42.1;
+ }
+ public double getDoubleValueNoDecimal() {
+ return 42.0;
+ }
+ public String getStringValue() {
+ return "foo";
+ }
+ public String getEmptyStringValue() {
+ return "";
+ }
+ public String getNullStringValue() {
+ return null;
+ }
+ public Object getObjectValue() {
+ return new Object();
+ }
+ public Object getNullObjectValue() {
+ return null;
+ }
+ public CustomType getCustomTypeValue() {
+ return new CustomType();
+ }
+ public void getVoidValue() {
+ }
+ }
+
+ // A custom type used when testing passing objects.
+ private class CustomType {
+ }
+
+ TestObject mTestObject;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mTestObject = new TestObject();
+ setUpWebView(mTestObject, "testObject");
+ }
+
+ // Note that this requires that we can pass a JavaScript string to Java.
+ protected String executeJavaScriptAndGetStringResult(String script) throws Throwable {
+ executeJavaScript("testObject.setStringValue(" + script + ");");
+ return mTestObject.waitForStringValue();
+ }
+
+ // Note that this requires that we can pass a JavaScript boolean to Java.
+ private boolean executeJavaScriptAndGetBooleanResult(String script) throws Throwable {
+ executeJavaScript("testObject.setBooleanValue(" + script + ");");
+ return mTestObject.waitForBooleanValue();
+ }
+
+ public void testMethodReturnTypes() throws Throwable {
+ assertEquals("boolean",
+ executeJavaScriptAndGetStringResult("typeof testObject.getBooleanValue()"));
+ assertEquals("number",
+ executeJavaScriptAndGetStringResult("typeof testObject.getByteValue()"));
+ // char values are returned to JavaScript as numbers.
+ assertEquals("number",
+ executeJavaScriptAndGetStringResult("typeof testObject.getCharValue()"));
+ assertEquals("number",
+ executeJavaScriptAndGetStringResult("typeof testObject.getShortValue()"));
+ assertEquals("number",
+ executeJavaScriptAndGetStringResult("typeof testObject.getIntValue()"));
+ assertEquals("number",
+ executeJavaScriptAndGetStringResult("typeof testObject.getLongValue()"));
+ assertEquals("number",
+ executeJavaScriptAndGetStringResult("typeof testObject.getFloatValue()"));
+ assertEquals("number",
+ executeJavaScriptAndGetStringResult("typeof testObject.getFloatValueNoDecimal()"));
+ assertEquals("number",
+ executeJavaScriptAndGetStringResult("typeof testObject.getDoubleValue()"));
+ assertEquals("number",
+ executeJavaScriptAndGetStringResult("typeof testObject.getDoubleValueNoDecimal()"));
+ assertEquals("string",
+ executeJavaScriptAndGetStringResult("typeof testObject.getStringValue()"));
+ assertEquals("string",
+ executeJavaScriptAndGetStringResult("typeof testObject.getEmptyStringValue()"));
+ // LIVECONNECT_COMPLIANCE: This should have type object.
+ assertEquals("undefined",
+ executeJavaScriptAndGetStringResult("typeof testObject.getNullStringValue()"));
+ assertEquals("object",
+ executeJavaScriptAndGetStringResult("typeof testObject.getObjectValue()"));
+ assertEquals("object",
+ executeJavaScriptAndGetStringResult("typeof testObject.getNullObjectValue()"));
+ assertEquals("object",
+ executeJavaScriptAndGetStringResult("typeof testObject.getCustomTypeValue()"));
+ assertEquals("undefined",
+ executeJavaScriptAndGetStringResult("typeof testObject.getVoidValue()"));
+ }
+
+ public void testMethodReturnValues() throws Throwable {
+ // We do the string comparison in JavaScript, to avoid relying on the
+ // coercion algorithm from JavaScript to Java.
+ assertTrue(executeJavaScriptAndGetBooleanResult("testObject.getBooleanValue()"));
+ assertTrue(executeJavaScriptAndGetBooleanResult("42 === testObject.getByteValue()"));
+ // char values are returned to JavaScript as numbers.
+ assertTrue(executeJavaScriptAndGetBooleanResult("42 === testObject.getCharValue()"));
+ assertTrue(executeJavaScriptAndGetBooleanResult("42 === testObject.getShortValue()"));
+ assertTrue(executeJavaScriptAndGetBooleanResult("42 === testObject.getIntValue()"));
+ assertTrue(executeJavaScriptAndGetBooleanResult("42 === testObject.getLongValue()"));
+ assertTrue(executeJavaScriptAndGetBooleanResult(
+ "Math.abs(42.1 - testObject.getFloatValue()) < 0.001"));
+ assertTrue(executeJavaScriptAndGetBooleanResult(
+ "42.0 === testObject.getFloatValueNoDecimal()"));
+ assertTrue(executeJavaScriptAndGetBooleanResult(
+ "Math.abs(42.1 - testObject.getDoubleValue()) < 0.001"));
+ assertTrue(executeJavaScriptAndGetBooleanResult(
+ "42.0 === testObject.getDoubleValueNoDecimal()"));
+ assertEquals("foo", executeJavaScriptAndGetStringResult("testObject.getStringValue()"));
+ assertEquals("", executeJavaScriptAndGetStringResult("testObject.getEmptyStringValue()"));
+ assertTrue(executeJavaScriptAndGetBooleanResult("undefined === testObject.getVoidValue()"));
+ }
+}
diff --git a/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeTestBase.java b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeTestBase.java
new file mode 100644
index 0000000..1af3f63
--- /dev/null
+++ b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeTestBase.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Common functionality for testing the WebView's Java Bridge.
+ */
+
+package com.android.webviewtests;
+
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+
+import junit.framework.Assert;
+
+public class JavaBridgeTestBase extends ActivityInstrumentationTestCase2<WebViewStubActivity> {
+ protected class TestWebViewClient extends WebViewClient {
+ private boolean mIsPageFinished;
+ @Override
+ public synchronized void onPageFinished(WebView webView, String url) {
+ mIsPageFinished = true;
+ notify();
+ }
+ public synchronized void waitForOnPageFinished() throws RuntimeException {
+ while (!mIsPageFinished) {
+ try {
+ wait(5000);
+ } catch (Exception e) {
+ continue;
+ }
+ if (!mIsPageFinished) {
+ throw new RuntimeException("Timed out waiting for onPageFinished()");
+ }
+ }
+ mIsPageFinished = false;
+ }
+ }
+
+ protected class Controller {
+ private boolean mIsResultReady;
+
+ protected synchronized void notifyResultIsReady() {
+ mIsResultReady = true;
+ notify();
+ }
+ protected synchronized void waitForResult() {
+ while (!mIsResultReady) {
+ try {
+ wait(5000);
+ } catch (Exception e) {
+ continue;
+ }
+ if (!mIsResultReady) {
+ Assert.fail("Wait timed out");
+ }
+ }
+ mIsResultReady = false;
+ }
+ }
+
+ protected TestWebViewClient mWebViewClient;
+
+ public JavaBridgeTestBase() {
+ super(WebViewStubActivity.class);
+ }
+
+ // Sets up the WebView and injects the supplied object. Intended to be called from setUp().
+ protected void setUpWebView(final Object object, final String name) throws Exception {
+ mWebViewClient = new TestWebViewClient();
+ // This starts the activity, so must be called on the test thread.
+ final WebViewStubActivity activity = getActivity();
+ // On the UI thread, load an empty page and wait for it to finish
+ // loading so that the Java object is injected.
+ try {
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ WebView webView = activity.getWebView();
+ webView.addJavascriptInterface(object, name);
+ webView.getSettings().setJavaScriptEnabled(true);
+ webView.setWebViewClient(mWebViewClient);
+ webView.loadData("<!DOCTYPE html><title></title>", "text/html", null);
+ }
+ });
+ mWebViewClient.waitForOnPageFinished();
+ } catch (Throwable e) {
+ throw new RuntimeException("Failed to set up WebView: " + Log.getStackTraceString(e));
+ }
+ }
+
+ protected void executeJavaScript(final String script) throws Throwable {
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ getWebView().loadUrl("javascript:" + script);
+ }
+ });
+ }
+
+ protected WebView getWebView() {
+ return getActivity().getWebView();
+ }
+}
diff --git a/tests/WebViewTests/src/com/android/webviewtests/WebViewStubActivity.java b/tests/WebViewTests/src/com/android/webviewtests/WebViewStubActivity.java
new file mode 100644
index 0000000..ccfd3d5
--- /dev/null
+++ b/tests/WebViewTests/src/com/android/webviewtests/WebViewStubActivity.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.webviewtests;
+
+import com.android.webviewtests.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.webkit.WebView;
+
+public class WebViewStubActivity extends Activity {
+ private WebView mWebView;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.webview_layout);
+ mWebView = (WebView) findViewById(R.id.web_page);
+ }
+
+ public WebView getWebView() {
+ return mWebView;
+ }
+}
diff --git a/tests/touchlag/Android.mk b/tests/touchlag/Android.mk
new file mode 100644
index 0000000..4f8aa1e
--- /dev/null
+++ b/tests/touchlag/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ touchlag.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils libutils \
+
+LOCAL_MODULE:= test-touchlag
+
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_EXECUTABLE)
diff --git a/tests/touchlag/touchlag.cpp b/tests/touchlag/touchlag.cpp
new file mode 100644
index 0000000..df4befb
--- /dev/null
+++ b/tests/touchlag/touchlag.cpp
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/fb.h>
+#include <linux/input.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <cutils/memory.h>
+#include <asm-generic/mman.h>
+#include <sys/mman.h>
+#include <utils/threads.h>
+#include <unistd.h>
+#include <math.h>
+
+using namespace android;
+
+#ifndef FBIO_WAITFORVSYNC
+#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
+#endif
+
+struct Buffer {
+ size_t w;
+ size_t h;
+ size_t s;
+ union {
+ void* addr;
+ uint32_t* pixels;
+ };
+};
+
+void clearBuffer(Buffer* buf, uint32_t pixel) {
+ android_memset32(buf->pixels, pixel, buf->s * buf->h * 4);
+}
+
+void drawTwoPixels(Buffer* buf, uint32_t pixel, ssize_t x, ssize_t y, size_t w) {
+ if (y>0 && y<ssize_t(buf->h)) {
+ uint32_t* bits = buf->pixels + y * buf->s;
+ if (x>=0 && x<buf->w) {
+ bits[x] = pixel;
+ }
+ ssize_t W(w);
+ if ((x+W)>=0 && (x+W)<buf->w) {
+ bits[x+W] = pixel;
+ }
+ }
+}
+
+void drawHLine(Buffer* buf, uint32_t pixel, ssize_t x, ssize_t y, size_t w) {
+ if (y>0 && y<ssize_t(buf->h)) {
+ ssize_t W(w);
+ if (x<0) {
+ W += x;
+ x = 0;
+ }
+ if (x+w > buf->w) {
+ W = buf->w - x;
+ }
+ if (W>0) {
+ uint32_t* bits = buf->pixels + y * buf->s + x;
+ android_memset32(bits, pixel, W*4);
+ }
+ }
+}
+
+void drawRect(Buffer* buf, uint32_t pixel, ssize_t x, ssize_t y, size_t w, size_t h) {
+ ssize_t W(w), H(h);
+ if (x<0) {
+ w += x;
+ x = 0;
+ }
+ if (y<0) {
+ h += y;
+ y = 0;
+ }
+ if (x+w > buf->w) W = buf->w - x;
+ if (y+h > buf->h) H = buf->h - y;
+ if (W>0 && H>0) {
+ uint32_t* bits = buf->pixels + y * buf->s + x;
+ for (ssize_t i=0 ; i<H ; i++) {
+ android_memset32(bits, pixel, W*4);
+ bits += buf->s;
+ }
+ }
+}
+
+void drawCircle(Buffer* buf, uint32_t pixel,
+ size_t x0, size_t y0, size_t radius, bool filled = false) {
+ ssize_t f = 1 - radius;
+ ssize_t ddF_x = 1;
+ ssize_t ddF_y = -2 * radius;
+ ssize_t x = 0;
+ ssize_t y = radius;
+ if (filled) {
+ drawHLine(buf, pixel, x0-radius, y0, 2*radius);
+ } else {
+ drawTwoPixels(buf, pixel, x0-radius, y0, 2*radius);
+ }
+ while (x < y) {
+ if (f >= 0) {
+ y--;
+ ddF_y += 2;
+ f += ddF_y;
+ }
+ x++;
+ ddF_x += 2;
+ f += ddF_x;
+ if (filled) {
+ drawHLine(buf, pixel, x0-x, y0+y, 2*x);
+ drawHLine(buf, pixel, x0-x, y0-y, 2*x);
+ drawHLine(buf, pixel, x0-y, y0+x, 2*y);
+ drawHLine(buf, pixel, x0-y, y0-x, 2*y);
+ } else {
+ drawTwoPixels(buf, pixel, x0-x, y0+y, 2*x);
+ drawTwoPixels(buf, pixel, x0-x, y0-y, 2*x);
+ drawTwoPixels(buf, pixel, x0-y, y0+x, 2*y);
+ drawTwoPixels(buf, pixel, x0-y, y0-x, 2*y);
+ }
+ }
+}
+
+class TouchEvents {
+ class EventThread : public Thread {
+ int fd;
+
+ virtual bool threadLoop() {
+ input_event event;
+ int first_down = 0;
+ do {
+ read(fd, &event, sizeof(event));
+ if (event.type == EV_ABS) {
+ if (event.code == ABS_MT_TRACKING_ID) {
+ down = event.value == -1 ? 0 : 1;
+ first_down = down;
+ }
+ if (event.code == ABS_MT_POSITION_X) {
+ x = event.value;
+ }
+ if (event.code == ABS_MT_POSITION_Y) {
+ y = event.value;
+ }
+ }
+ } while (event.type == EV_SYN);
+ return true;
+ }
+
+ public:
+ int x, y, down;
+ EventThread() : Thread(false),
+ x(0), y(0), down(0)
+ {
+ fd = open("/dev/input/event1", O_RDONLY);
+ }
+};
+ sp<EventThread> thread;
+
+public:
+ TouchEvents() {
+ thread = new EventThread();
+ thread->run("EventThread", PRIORITY_URGENT_DISPLAY);
+ }
+
+ int getMostRecentPosition(int* x, int* y) {
+ *x = thread->x;
+ *y = thread->y;
+ return thread->down;
+ }
+};
+
+
+struct Queue {
+ struct position {
+ int x, y;
+ };
+ int index;
+ position q[16];
+ Queue() : index(0) { }
+ void push(int x, int y) {
+ index++;
+ index &= 0xF;
+ q[index].x = x;
+ q[index].y = y;
+ }
+ void get(int lag, int* x, int* y) {
+ const int i = (index - lag) & 0xF;
+ *x = q[i].x;
+ *y = q[i].y;
+ }
+};
+
+extern char *optarg;
+extern int optind;
+extern int optopt;
+extern int opterr;
+extern int optreset;
+
+void usage(const char* name) {
+ printf("\nusage: %s [-h] [-l lag]\n", name);
+}
+
+int main(int argc, char** argv) {
+ fb_var_screeninfo vi;
+ fb_fix_screeninfo fi;
+
+ int lag = 0;
+ int fd = open("/dev/graphics/fb0", O_RDWR);
+ ioctl(fd, FBIOGET_VSCREENINFO, &vi);
+ ioctl(fd, FBIOGET_FSCREENINFO, &fi);
+ void* bits = mmap(0, fi.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ Buffer framebuffer;
+ framebuffer.w = vi.xres;
+ framebuffer.h = vi.yres;
+ framebuffer.s = fi.line_length / (vi.bits_per_pixel >> 3);
+ framebuffer.addr = bits;
+
+ int ch;
+ while ((ch = getopt(argc, argv, "hl:")) != -1) {
+ switch (ch) {
+ case 'l':
+ lag = atoi(optarg);
+ break;
+ case 'h':
+ default:
+ usage(argv[0]);
+ exit(0);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+
+ TouchEvents touch;
+ Queue queue;
+
+
+ int x=0, y=0, down=0;
+ int lag_x=0, lag_y=0;
+
+ clearBuffer(&framebuffer, 0);
+ while (true) {
+ uint32_t crt = 0;
+ int err = ioctl(fd, FBIO_WAITFORVSYNC, &crt);
+
+ // draw beam marker
+ drawRect(&framebuffer, 0x400000, framebuffer.w-2, 0, 2, framebuffer.h);
+ // erase screen
+ if (lag) {
+ drawCircle(&framebuffer, 0, lag_x, lag_y, 100);
+ drawHLine(&framebuffer, 0, 0, lag_y, 32);
+ }
+ drawCircle(&framebuffer, 0, x, y, 100, true);
+ drawHLine(&framebuffer, 0, 0, y, 32);
+
+ // draw a line at y=1000
+ drawHLine(&framebuffer, 0x808080, 0, 1000, framebuffer.w);
+
+ // get touch events
+ touch.getMostRecentPosition(&x, &y);
+ queue.push(x, y);
+ queue.get(lag, &lag_x, &lag_y);
+
+ if (lag) {
+ drawCircle(&framebuffer, 0x00FF00, lag_x, lag_y, 100);
+ drawHLine(&framebuffer, 0x00FF00, 0, lag_y, 32);
+ }
+
+ drawCircle(&framebuffer, 0xFFFFFF, x, y, 100, true);
+ drawHLine(&framebuffer, 0xFFFFFF, 0, y, 32);
+
+ // draw end of frame beam marker
+ drawRect(&framebuffer, 0x004000, framebuffer.w-2, 0, 2, framebuffer.h);
+ }
+
+ close(fd);
+ return 0;
+}