Merge "CTS test for the new TelephonyManager APIs" into klp-dev
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 8695981..354775d 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -89,6 +89,9 @@
<meta-data android:name="test_category" android:value="@string/test_category_device_admin" />
</activity>
+ <!-- A generic activity for intent based tests -->
+ <activity android:name=".IntentDrivenTestActivity"/>
+
<activity android:name=".admin.ScreenLockTestActivity"
android:label="@string/da_screen_lock_test"
android:configChanges="keyboardHidden|orientation|screenSize">
@@ -472,9 +475,6 @@
<meta-data android:name="test_category" android:value="@string/test_category_deskclock" />
</activity>
- <activity android:name=".deskclock.ShowAlarmsTestActivity"
- android:label="@string/dc_show_alarms_test"/>
-
<receiver android:name=".widget.WidgetCtsProvider">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
diff --git a/apps/CtsVerifier/res/layout/dc_show_alarms.xml b/apps/CtsVerifier/res/layout/dc_show_alarms.xml
deleted file mode 100644
index 06a2bb1..0000000
--- a/apps/CtsVerifier/res/layout/dc_show_alarms.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- >
-
- <LinearLayout android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:padding="5dp"
- >
-
- <TextView android:layout_width="wrap_content"
- android:textSize="18sp"
- android:layout_height="wrap_content"
- android:text="@string/dc_show_alarms_test_info"
- />
-
- <Button android:id="@+id/dc_show_alarms"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/dc_show_alarms_button"
- />
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- >
- <include layout="@layout/pass_fail_buttons" />
- </LinearLayout>
-</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/intent_driven_test.xml b/apps/CtsVerifier/res/layout/intent_driven_test.xml
new file mode 100644
index 0000000..1b68074
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/intent_driven_test.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ >
+
+ <LinearLayout android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:padding="5dp"
+ >
+
+ <TextView android:id="@+id/info"
+ android:layout_width="wrap_content"
+ android:textSize="18sp"
+ android:layout_height="wrap_content"
+ android:text="@string/dc_show_alarms_test_info"
+ />
+
+ <LinearLayout android:id="@+id/buttons"
+ android:orientation="horizontal"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ >
+ <include layout="@layout/pass_fail_buttons"/>
+ </LinearLayout>
+</RelativeLayout>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index ef14be3..0f164ef 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -15,7 +15,7 @@
-->
<resources>
<string name="app_name">CTS Verifier</string>
-
+
<string name="title_version">CTS Verifier %1$s</string>
<string name="pass_button_text">Pass</string>
@@ -32,7 +32,7 @@
<string name="test_category_security">Security</string>
<string name="test_category_streaming">Streaming</string>
<string name="test_category_features">Features</string>
- <string name="test_category_deskclock">Desk Clock</string>
+ <string name="test_category_deskclock">Clock</string>
<string name="test_category_other">Other</string>
<string name="clear">Clear</string>
<string name="test_results_cleared">Test results cleared.</string>
@@ -617,9 +617,9 @@
<string name="widget_fail">Fail</string>
<!-- Strings for DeskClock -->
- <string name="deskclock_tests">Desk Clock Tests</string>
+ <string name="deskclock_tests">Alarms and Timers Tests</string>
<string name="deskclock_tests_info">
- The Desk Clock tests verify that the Desk Clock app implements the Clock API\'s properly.
+ The Alarms and Timers tests verify that the Clock app implements the AlarmClock API properly.
</string>
<string name="deskclock_group_alarms">Alarms</string>
<string name="deskclock_group_timers">Timers</string>
@@ -628,9 +628,69 @@
<string name="dc_show_alarms_test_info">
This test verifies that the SHOW_ALARMS API works.\n
1. Press the "Show Alarms" button.\n
- 2. Verify that the Desk Clock app is launched and displays the Alarms section\n
+ 2. Verify that a UI of the clock app is launched and displays the list of alarms\n
</string>
<string name="dc_show_alarms_button">Show Alarms</string>
+ <string name="dc_set_alarm_with_ui_test">Set Alarm Test</string>
+ <string name="dc_set_alarm_with_ui_test_info">
+ This test verifies that the ACTION_SET_ALARM with no parameters API works.\n
+ 1. Press the "Set Alarm" button.\n
+ 2. Verify that the clock app is launched and displays a UI to manage alarms.\n
+ </string>
+ <string name="dc_set_alarm_button">Set Alarm</string>
+ <string name="dc_set_alarm_verify_button">Verify</string>
+ <string name="dc_start_alarm_test">Start Alarm Test</string>
+ <string name="dc_start_alarm_test_info">
+ This test verifies that the ACTION_SET_ALARM API actually starts an alarm.\n
+ 1. Press the "Start Alarm" button.\n
+ 2. Make sure the alarms UI is NOT shown\n
+ 3. Wait for the alarm to fire (may take up to 2 minutes)\n
+ 4. Verify that the alarm title is: "Start Alarm Test",\n
+ the alarm is silent and vibrating (if the device supports vibrate).\n
+ 5. Dismiss the alarm.\n
+ 6. Verify that the alarm is not in the Clock\'s alarms list. The Verify button opens
+ the alarm view.\n
+ </string>
+ <string name="dc_start_alarm_button">Start Alarm</string>
+
+ <string name="dc_full_alarm_test">Full Alarm Test</string>
+ <string name="dc_full_alarm_test_info">
+ This test verifies that the ACTION_SET_ALARM API supports all extras.\n
+ 1. Press the "Create Alarm" button.\n
+ 2. Verify that you see one alarm with the following information:\n
+ Name of alarm: Create Alarm Test. \n
+ Vibrate: on.\n
+ Ringtone: silent.\n
+ Time: 01:23. \n
+ Repeating on: Monday and Wednesday. \n
+ </string>
+ <string name="dc_full_alarm_button">Create Alarm</string>
+
+ <string name="dc_set_timer_with_ui_test">Set Timer Test</string>
+ <string name="dc_set_timer_with_ui_test_info">
+ This test verifies that the ACTION_SET_TIMER API with no paramters open the UI\n
+ 1. Press the "Set Timer" button.\n
+ 2. Verify that the an app is launched and displays a UI to manage timers.\n
+ </string>
+ <string name="dc_set_timer_with_ui_button">Set Timer</string>
+
+ <string name="dc_start_timer_test">Start Timer Test</string>
+ <string name="dc_start_timer_test_info">
+ This test verifies that the ACTION_SET_TIMER API actually starts a timer\n
+ 1. Press the "Start Timer" button.\n
+ 2. Verify that a timer is started and NO timers UI is shown.\n
+ 3. Verify that the timer named "Start Timer Test" rings after 30 seconds. Dismiss it.\n
+ 4. Verify that the timer is deleted after the dismissal.\n
+ </string>
+ <string name="dc_start_timer_button">Start Timer</string>
+
+ <string name="dc_start_timer_with_ui_test">Start Timer With UI Test</string>
+ <string name="dc_start_timer_with_ui_test_info">
+ This test verifies that the ACTION_SET_TIMER API actually starts a timer with UI\n
+ 1. Press the "Start Timer" button.\n
+ 2. Verify that a timer is started and the timers UI is shown with a timer named "Start Timer Test".\n
+ 3. Verify that the timer rings after 30 seconds.\n
+ </string>
</resources>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/IntentDrivenTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/IntentDrivenTestActivity.java
new file mode 100644
index 0000000..9833abd
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/IntentDrivenTestActivity.java
@@ -0,0 +1,215 @@
+// Copyright 2013 Google Inc. All Rights Reserved.
+
+package com.android.cts.verifier;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+
+/**
+ * A generic activity for intent based tests.
+ *
+ * This activity can be reused for various tests that are intent based. The activity consists of a
+ * text view containing instructions and one or more buttons that trigger intents.
+ * Each button can send one or more intenrs as startActivity() calls.
+ *
+ * The intents can either be generated statically and passed as an extra to the intent that started
+ * this activity or in some cases where the intent needs to be based on dynamic data (for example
+ * time of day), an {@link IntentFactory} class name can be passed instead. This intent factory
+ * will dynamically create the intent when the button is clicked based on the test id and the
+ * button that was clicked.
+ */
+public class IntentDrivenTestActivity extends PassFailButtons.Activity implements OnClickListener {
+ public static final String EXTRA_ID = "id";
+ public static final String EXTRA_TITLE = "title";
+ public static final String EXTRA_INFO = "info";
+ public static final String EXTRA_BUTTONS = "buttons";
+
+ private String mTestId;
+ private ButtonInfo[] mButtonInfos;
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.intent_driven_test);
+ setPassFailButtonClickListeners();
+
+ final Intent intent = getIntent();
+ if (!intent.hasExtra(EXTRA_ID)
+ || !intent.hasExtra(EXTRA_TITLE)
+ || !intent.hasExtra(EXTRA_INFO)
+ || !intent.hasExtra(EXTRA_BUTTONS)) {
+ throw new IllegalArgumentException(
+ "Intent must have EXTRA_ID, EXTRA_TITLE, EXTRA_INFO & EXTRA_BUTTONS");
+ }
+
+ mTestId = intent.getStringExtra(EXTRA_ID);
+ setTitle(intent.getIntExtra(EXTRA_TITLE, -1));
+
+ final TextView info = (TextView) findViewById(R.id.info);
+ info.setText(intent.getIntExtra(EXTRA_INFO, -1));
+
+ final ViewGroup buttons = (ViewGroup) findViewById(R.id.buttons);
+ final Parcelable[] parcelables = intent.getParcelableArrayExtra(EXTRA_BUTTONS);
+ mButtonInfos = new ButtonInfo[parcelables.length];
+ for (int i = 0; i < parcelables.length; i++) {
+ final ButtonInfo buttonInfo = (ButtonInfo) parcelables[i];
+ mButtonInfos[i] = buttonInfo;
+ final Button button = new Button(this);
+ buttons.addView(button);
+ button.setText(buttonInfo.mButtonText);
+ button.setTag(i);
+ button.setOnClickListener(this);
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ setResult(RESULT_CANCELED);
+ }
+
+ @Override
+ public void onClick(View v) {
+ final ButtonInfo buttonInfo = mButtonInfos[(Integer) v.getTag()];
+ final Intent[] intents = buttonInfo.getIntents();
+ if (intents != null) {
+ for (Parcelable intent : intents) {
+ startActivity((Intent) intent);
+ }
+ } else {
+ final Class<?> factoryClass;
+ final String className = buttonInfo.getIntentFactoryClassName();
+ try {
+ factoryClass = Thread.currentThread().getContextClassLoader().loadClass(className);
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException("Factory not found: " + className, e);
+ }
+ final IntentFactory factory;
+ try {
+ factory = (IntentFactory) factoryClass.newInstance();
+ } catch (InstantiationException e) {
+ throw new IllegalArgumentException("Can't create factory: " + className, e);
+ } catch (IllegalAccessException e) {
+ throw new IllegalArgumentException("Can't create factory: " + className, e);
+ }
+
+ for (Intent intent : factory.createIntents(mTestId, buttonInfo.getButtonText())) {
+ startActivity(intent);
+ }
+ }
+ }
+
+ @Override
+ public String getTestId() {
+ return mTestId;
+ }
+
+ public static class TestInfo {
+ private final String mTestId;
+ private final int mTitle;
+ private final int mInfoText;
+ private final ButtonInfo[] mButtons;
+
+ public TestInfo(String testId, int title, int infoText, ButtonInfo... buttons) {
+ mTestId = testId;
+ mTitle = title;
+ mInfoText = infoText;
+ mButtons = buttons;
+ }
+
+ public String getTestId() {
+ return mTestId;
+ }
+
+ public int getTitle() {
+ return mTitle;
+ }
+
+ public int getInfoText() {
+ return mInfoText;
+ }
+
+ public ButtonInfo[] getButtons() {
+ return mButtons;
+ }
+ }
+
+ public static class ButtonInfo implements Parcelable {
+ private final int mButtonText;
+ private final Intent[] mIntents;
+ private final String mIntentFactoryClassName;
+
+ public ButtonInfo(int buttonText, Intent... intents) {
+ mButtonText = buttonText;
+ mIntents = intents;
+ mIntentFactoryClassName = null;
+ }
+
+ public ButtonInfo(int buttonText, String intentFactoryClassName) {
+ mButtonText = buttonText;
+ mIntents = null;
+ mIntentFactoryClassName = intentFactoryClassName;
+ }
+
+ public ButtonInfo(Parcel source) {
+ mButtonText = source.readInt();
+ final Parcelable[] parcelables = source.readParcelableArray(null);
+ if (parcelables != null) {
+ mIntents = new Intent[parcelables.length];
+ for (int i = 0, parcelablesLength = parcelables.length; i < parcelablesLength; i++) {
+ mIntents[i] = (Intent) parcelables[i];
+ }
+ } else {
+ mIntents = null;
+ }
+ mIntentFactoryClassName = source.readString();
+ }
+
+ public int getButtonText() {
+ return mButtonText;
+ }
+
+ public Intent[] getIntents() {
+ return mIntents;
+ }
+
+ public String getIntentFactoryClassName() {
+ return mIntentFactoryClassName;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mButtonText);
+ dest.writeParcelableArray(mIntents, 0);
+ dest.writeString(mIntentFactoryClassName);
+ }
+
+ public static final Creator<ButtonInfo> CREATOR = new Creator<ButtonInfo>() {
+ public ButtonInfo createFromParcel(Parcel source) {
+ return new ButtonInfo(source);
+ }
+
+ public ButtonInfo[] newArray(int size) {
+ return new ButtonInfo[size];
+ }
+ };
+
+ }
+
+ public interface IntentFactory {
+ Intent[] createIntents(String testId, int buttonText);
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/deskclock/DeskClockTestsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/deskclock/DeskClockTestsActivity.java
index 91b9b98..fcd88d1 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/deskclock/DeskClockTestsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/deskclock/DeskClockTestsActivity.java
@@ -5,17 +5,125 @@
import android.content.Intent;
import android.database.DataSetObserver;
import android.os.Bundle;
+import android.provider.AlarmClock;
import com.android.cts.verifier.ArrayTestListAdapter;
+import com.android.cts.verifier.IntentDrivenTestActivity;
import com.android.cts.verifier.PassFailButtons;
import com.android.cts.verifier.R;
import com.android.cts.verifier.TestListAdapter.TestListItem;
+import com.android.cts.verifier.IntentDrivenTestActivity.ButtonInfo;
+import com.android.cts.verifier.IntentDrivenTestActivity.IntentFactory;
+import com.android.cts.verifier.IntentDrivenTestActivity.TestInfo;
+
+import java.util.ArrayList;
+import java.util.Calendar;
/**
* Activity that lists all the DeskClock tests.
*/
public class DeskClockTestsActivity extends PassFailButtons.TestListActivity {
+ private static final String SHOW_ALARMS_TEST = "SHOW_ALARMS";
+ public static final String SET_ALARM_WITH_UI_TEST = "SET_ALARM_WITH_UI";
+ public static final String START_ALARM_TEST = "START_ALARM";
+ public static final String CREATE_ALARM_TEST = "CREATE_ALARM";
+ public static final String SET_TIMER_WITH_UI_TEST = "SET_TIMER_WITH_UI";
+ public static final String START_TIMER = "START_TIMER";
+ public static final String START_TIMER_WITH_UI = "START_TIMER_WITH_UI";
+
+ private static final ArrayList<Integer> DAYS = new ArrayList<Integer>();
+
+ private static final Intent CREATE_ALARM_INTENT = new Intent(AlarmClock.ACTION_SET_ALARM)
+ .putExtra(AlarmClock.EXTRA_MESSAGE, "Create Alarm Test")
+ .putExtra(AlarmClock.EXTRA_SKIP_UI, false)
+ .putExtra(AlarmClock.EXTRA_VIBRATE, true)
+ .putExtra(AlarmClock.EXTRA_RINGTONE, AlarmClock.VALUE_RINGTONE_SILENT)
+ .putExtra(AlarmClock.EXTRA_HOUR, 1)
+ .putExtra(AlarmClock.EXTRA_MINUTES, 23)
+ .putExtra(AlarmClock.EXTRA_DAYS, DAYS);
+
+ static {
+ DAYS.add(Calendar.MONDAY);
+ DAYS.add(Calendar.WEDNESDAY);
+ }
+
+ private static final Intent SHOW__ALARMS_INTENT = new Intent(AlarmClock.ACTION_SHOW_ALARMS);
+
+ private static final Intent SET_ALARM_WITH_UI_INTENT = new Intent(AlarmClock.ACTION_SET_ALARM)
+ .putExtra(AlarmClock.EXTRA_SKIP_UI, false);
+
+ private static final Intent SET_TIMER_WITH_UI_INTENT = new Intent(AlarmClock.ACTION_SET_TIMER)
+ .putExtra(AlarmClock.EXTRA_SKIP_UI, false);
+
+ private static final Intent START_TIMER_INTENT = new Intent(AlarmClock.ACTION_SET_TIMER)
+ .putExtra(AlarmClock.EXTRA_SKIP_UI, true)
+ .putExtra(AlarmClock.EXTRA_MESSAGE, "Start Timer Test")
+ .putExtra(AlarmClock.EXTRA_LENGTH, 30);
+
+ private static final Intent START_TIMER_WITH_UI_INTENT = new Intent(AlarmClock.ACTION_SET_TIMER)
+ .putExtra(AlarmClock.EXTRA_SKIP_UI, false)
+ .putExtra(AlarmClock.EXTRA_MESSAGE, "Start Timer Test")
+ .putExtra(AlarmClock.EXTRA_LENGTH, 30);
+
+ private static final TestInfo[] ALARM_TESTS = new TestInfo[] {
+ new TestInfo(
+ SHOW_ALARMS_TEST,
+ R.string.dc_show_alarms_test,
+ R.string.dc_show_alarms_test_info,
+ new ButtonInfo(
+ R.string.dc_show_alarms_button,
+ SHOW__ALARMS_INTENT)),
+ new TestInfo(
+ SET_ALARM_WITH_UI_TEST,
+ R.string.dc_set_alarm_with_ui_test,
+ R.string.dc_set_alarm_with_ui_test_info,
+ new ButtonInfo(
+ R.string.dc_set_alarm_button,
+ SET_ALARM_WITH_UI_INTENT)),
+ new TestInfo(
+ START_ALARM_TEST,
+ R.string.dc_start_alarm_test,
+ R.string.dc_start_alarm_test_info,
+ new ButtonInfo(
+ R.string.dc_set_alarm_button,
+ DeskClockIntentFactory.class.getName()),
+ new ButtonInfo(
+ R.string.dc_set_alarm_verify_button,
+ SHOW__ALARMS_INTENT)),
+ new TestInfo(
+ CREATE_ALARM_TEST,
+ R.string.dc_full_alarm_test,
+ R.string.dc_full_alarm_test_info,
+ new ButtonInfo(
+ R.string.dc_full_alarm_button,
+ CREATE_ALARM_INTENT)),
+ };
+
+ private static final TestInfo[] TIMER_TESTS = new TestInfo[] {
+ new TestInfo(
+ SET_TIMER_WITH_UI_TEST,
+ R.string.dc_set_timer_with_ui_test,
+ R.string.dc_set_timer_with_ui_test_info,
+ new ButtonInfo(
+ R.string.dc_set_timer_with_ui_button,
+ SET_TIMER_WITH_UI_INTENT)),
+ new TestInfo(
+ START_TIMER,
+ R.string.dc_start_timer_test,
+ R.string.dc_start_timer_test_info,
+ new ButtonInfo(
+ R.string.dc_start_timer_button,
+ START_TIMER_INTENT)),
+ new TestInfo(
+ START_TIMER_WITH_UI,
+ R.string.dc_start_timer_with_ui_test,
+ R.string.dc_start_timer_with_ui_test_info,
+ new ButtonInfo(
+ R.string.dc_start_timer_button,
+ START_TIMER_WITH_UI_INTENT)),
+ };
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -28,10 +136,10 @@
final ArrayTestListAdapter adapter = new ArrayTestListAdapter(this);
adapter.add(TestListItem.newCategory(this, R.string.deskclock_group_alarms));
- adapter.add(TestListItem.newTest(this,
- R.string.dc_show_alarms_test,
- ShowAlarmsTestActivity.class.getName(),
- new Intent(this, ShowAlarmsTestActivity.class), null));
+ addTests(adapter, ALARM_TESTS);
+
+ adapter.add(TestListItem.newCategory(this, R.string.deskclock_group_timers));
+ addTests(adapter, TIMER_TESTS);
adapter.registerDataSetObserver(new DataSetObserver() {
@Override
@@ -43,10 +151,46 @@
setTestListAdapter(adapter);
}
+ private void addTests(ArrayTestListAdapter adapter, TestInfo[] tests) {
+ for (TestInfo info : tests) {
+
+ final int title = info.getTitle();
+ adapter.add(TestListItem.newTest(this, title, info.getTestId(),
+ new Intent(this, IntentDrivenTestActivity.class)
+ .putExtra(IntentDrivenTestActivity.EXTRA_ID, info.getTestId())
+ .putExtra(IntentDrivenTestActivity.EXTRA_TITLE, title)
+ .putExtra(IntentDrivenTestActivity.EXTRA_INFO, info.getInfoText())
+ .putExtra(IntentDrivenTestActivity.EXTRA_BUTTONS, info.getButtons()),
+ null));
+ }
+ }
+
/**
* Enable Pass Button when the all tests passed.
*/
private void updatePassButton() {
getPassButton().setEnabled(mAdapter.allTestsPassed());
}
+
+ public static class DeskClockIntentFactory implements IntentFactory {
+ @Override
+ public Intent[] createIntents(String testId, int buttonText) {
+ if (testId.equals(START_ALARM_TEST)) {
+ // Alarm should go off 2 minutes from now
+ final Calendar cal = Calendar.getInstance();
+ cal.setTimeInMillis(cal.getTimeInMillis() + 120000);
+ return new Intent[] {
+ new Intent(AlarmClock.ACTION_SET_ALARM)
+ .putExtra(AlarmClock.EXTRA_MESSAGE, "Start Alarm Test")
+ .putExtra(AlarmClock.EXTRA_SKIP_UI, true)
+ .putExtra(AlarmClock.EXTRA_VIBRATE, true)
+ .putExtra(AlarmClock.EXTRA_RINGTONE, AlarmClock.VALUE_RINGTONE_SILENT)
+ .putExtra(AlarmClock.EXTRA_HOUR, cal.get(Calendar.HOUR_OF_DAY))
+ .putExtra(AlarmClock.EXTRA_MINUTES, cal.get(Calendar.MINUTE)),
+ };
+ } else {
+ throw new IllegalArgumentException("Unknown test: " + testId);
+ }
+ }
+ }
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/deskclock/ShowAlarmsTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/deskclock/ShowAlarmsTestActivity.java
deleted file mode 100644
index 0ce8f51..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/deskclock/ShowAlarmsTestActivity.java
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2013 Google Inc. All Rights Reserved.
-
-package com.android.cts.verifier.deskclock;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.provider.AlarmClock;
-import android.view.View;
-import android.view.View.OnClickListener;
-
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-public class ShowAlarmsTestActivity extends PassFailButtons.Activity implements OnClickListener {
-
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.dc_show_alarms);
- setPassFailButtonClickListeners();
-
- final View button = findViewById(R.id.dc_show_alarms);
- button.setOnClickListener(this);
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- setResult(RESULT_CANCELED);
- }
-
- @Override
- public void onClick(View v) {
- startActivity(new Intent(AlarmClock.ACTION_SHOW_ALARMS));
- }
-}
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index 6851d94..ec588a4 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -684,6 +684,15 @@
</intent-filter>
</activity>
+ <activity android:name="android.webkit.cts.WebViewStartupStubActivity"
+ android:label="WebViewStartupStubActivity"
+ android:screenOrientation="nosensor">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+ </intent-filter>
+ </activity>
+
<activity android:name="android.app.cts.ChildActivity"
android:label="ChildActivity" />
diff --git a/tests/src/android/webkit/cts/WebViewStartupStubActivity.java b/tests/src/android/webkit/cts/WebViewStartupStubActivity.java
new file mode 100644
index 0000000..6d56efd
--- /dev/null
+++ b/tests/src/android/webkit/cts/WebViewStartupStubActivity.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2013 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.webkit.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.webkit.WebView;
+
+public class WebViewStartupStubActivity extends Activity {
+ private WebView mWebView;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ public WebView createAndAttachWebView() {
+ mWebView = new WebView(this);
+ setContentView(mWebView);
+ return mWebView;
+ }
+
+ public WebView getWebView() {
+ return mWebView;
+ }
+
+ public void detachAndDestroyWebView() {
+ setContentView(null);
+ if (mWebView != null) {
+ mWebView.destroy();
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ detachAndDestroyWebView();
+ super.onDestroy();
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorAccelerometerTest.java b/tests/tests/hardware/src/android/hardware/cts/SensorAccelerometerTest.java
new file mode 100644
index 0000000..51fd5f6
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorAccelerometerTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.hardware.cts;
+
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+
+public class SensorAccelerometerTest extends SensorCommonTests {
+ @Override
+ protected int getMaxFrequencySupportedInuS() {
+ return 10000; // 100Hz
+ }
+
+ @Override
+ protected int getSensorType() {
+ return Sensor.TYPE_ACCELEROMETER;
+ }
+
+ /**
+ * Regress:
+ * - b/9503957
+ * - b/9611609
+ */
+ @Override
+ public void testEventValidity() {
+ final float THRESHOLD = 0.25f; // m / s^2
+ validateSensorEvent(
+ 0 /*x-axis*/,
+ 0 /*y-axis*/,
+ SensorManager.STANDARD_GRAVITY /*z-axis*/,
+ THRESHOLD);
+ }
+
+ @Override
+ public void testVarianceWhileStatic() {
+ final float THRESHOLD = 0.25f; // m / s^2
+ validateVarianceWhileStatic(
+ 0 /*x-axis*/,
+ 0 /*y-axis*/,
+ SensorManager.STANDARD_GRAVITY /*z-axis*/,
+ THRESHOLD);
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorCommonTests.java b/tests/tests/hardware/src/android/hardware/cts/SensorCommonTests.java
new file mode 100644
index 0000000..5cc65bb
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorCommonTests.java
@@ -0,0 +1,695 @@
+/*
+ * 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.hardware.cts;
+
+import android.content.Context;
+
+import android.hardware.FlushCompleteListener;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.hardware.TriggerEvent;
+import android.hardware.TriggerEventListener;
+
+import android.os.PowerManager;
+
+import android.test.AndroidTestCase;
+
+import java.util.List;
+import android.util.Log;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import java.text.SimpleDateFormat;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Random;
+import java.util.concurrent.ConcurrentLinkedDeque;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Class is not marked public to avoid TestRunner to pick the tests in it
+ */
+abstract class SensorCommonTests extends AndroidTestCase {
+ protected final String LOG_TAG = "TestRunner";
+
+ protected SensorManager mSensorManager;
+ protected Sensor mSensorUnderTest;
+ protected TestSensorListener mEventListener;
+
+ private FlushCompleteListener mFlushListener;
+ private PowerManager.WakeLock mWakeLock;
+
+ protected SensorCommonTests() {}
+
+ /**
+ * Abstract methods needed by concrete sensor classes to provide
+ */
+ protected abstract int getSensorType();
+ protected abstract int getMaxFrequencySupportedInuS();
+
+ /**
+ * Abstract test methods that sensors need to verify
+ */
+ public abstract void testEventValidity();
+ public abstract void testVarianceWhileStatic();
+
+ /**
+ * Methods to control the behavior of the tests by concrete sensor tests
+ */
+ protected int getWaitTimeoutInSeconds() {
+ return 30;
+ }
+
+ protected int getHighNumberOfIterationsToExecute() {
+ return 100;
+ }
+
+ protected int getLowNumberOfIterationsToExecute() {
+ return 10;
+ }
+
+ protected int getNumberOfThreadsToUse() {
+ return 5;
+ }
+
+ /**
+ * Test execution methods
+ */
+ @Override
+ protected void setUp() throws Exception {
+ PowerManager powerManager = (PowerManager) this.getContext().getSystemService(
+ Context.POWER_SERVICE);
+ mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this.getLogTag());
+ mWakeLock.acquire();
+
+ mEventListener = new TestSensorListener();
+ mFlushListener = new TestFlushListener();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ mSensorManager.unregisterListener(mEventListener, mSensorUnderTest);
+
+ mFlushListener = null;
+ mEventListener = null;
+ mSensorUnderTest = null;
+
+ releaseWakeLock();
+ }
+
+ @Override
+ public void runBare() throws Throwable {
+ mSensorManager = (SensorManager) this.getContext().getSystemService(Context.SENSOR_SERVICE);
+ assertNotNull("getSystemService#Sensor_Service", mSensorManager);
+
+ List<Sensor> availableSensors = mSensorManager.getSensorList(this.getSensorType());
+ // it is OK if there are no sensors available
+ for(Sensor sensor : availableSensors) {
+ mSensorUnderTest = sensor;
+ super.runBare();
+ }
+ }
+
+ /**
+ * Test cases continuous mode.
+ */
+ public void testCanRegisterListener() {
+ boolean result = mSensorManager.registerListener(
+ mEventListener,
+ mSensorUnderTest,
+ SensorManager.SENSOR_DELAY_NORMAL);
+ assertTrue("registerListener", result);
+ }
+
+ public void testNotTriggerSensor() {
+ TestTriggerListener listener = new TestTriggerListener();
+ assertFalse(
+ "requestTriggerSensor",
+ mSensorManager.requestTriggerSensor(listener, mSensorUnderTest));
+ }
+
+ public void testCanReceiveEvents() {
+ boolean result = mSensorManager.registerListener(
+ mEventListener,
+ mSensorUnderTest,
+ SensorManager.SENSOR_DELAY_NORMAL);
+ assertTrue("registerListener", result);
+ mEventListener.waitForEvents(5);
+ }
+
+ public void testMaxFrequency() {
+ boolean result = mSensorManager.registerListener(
+ mEventListener,
+ mSensorUnderTest,
+ this.getMaxFrequencySupportedInuS());
+ assertTrue("registerListener", result);
+ }
+
+ public void testEventsArriveInOrder() {
+ boolean result = mSensorManager.registerListener(
+ mEventListener,
+ mSensorUnderTest,
+ SensorManager.SENSOR_DELAY_FASTEST);
+ assertTrue("registerListener", result);
+ mEventListener.waitForEvents(100);
+
+ SensorEventForTest[] events = mEventListener.getAllEvents();
+ for(int i = 1; i < events.length; ++i) {
+ long previousTimestamp = events[i-1].getTimestamp();
+ long timestamp = events[i].getTimestamp();
+ assertTrue(
+ String.format("[timestamp:%d] %d >= %d", i, previousTimestamp, timestamp),
+ previousTimestamp < timestamp);
+ }
+ }
+
+ public void testStartStopRepeatedly() {
+ for(int i = 0; i < this.getLowNumberOfIterationsToExecute(); ++i) {
+ String iterationInfo = String.format("registerListener:%d", i);
+ boolean result = mSensorManager.registerListener(
+ mEventListener,
+ mSensorUnderTest,
+ SensorManager.SENSOR_DELAY_FASTEST);
+ assertTrue(iterationInfo, result);
+ mEventListener.waitForEvents(1, iterationInfo);
+
+ mSensorManager.unregisterListener(mEventListener, mSensorUnderTest);
+ }
+ }
+
+ public void testUpdateRate() {
+ // the seed is constant for now, use a random seed when we can log the seed properly
+ final long seed = 0xABCDE012;
+ Random generator = new Random(seed);
+ for(int i = 0; i < this.getHighNumberOfIterationsToExecute(); ++i) {
+ int rate;
+ switch(generator.nextInt(5)) {
+ case 0:
+ rate = SensorManager.SENSOR_DELAY_FASTEST;
+ break;
+ case 1:
+ rate = SensorManager.SENSOR_DELAY_GAME;
+ break;
+ case 2:
+ rate = SensorManager.SENSOR_DELAY_NORMAL;
+ break;
+ case 3:
+ rate = SensorManager.SENSOR_DELAY_UI;
+ break;
+ case 4:
+ default:
+ rate = this.getMaxFrequencySupportedInuS() * generator.nextInt(10);
+ }
+
+ String iterationInfo = String.format("registerListener:%d, rate:%d", i, rate);
+ assertTrue(
+ iterationInfo,
+ mSensorManager.registerListener(mEventListener, mSensorUnderTest, rate));
+
+ mEventListener.waitForEvents(generator.nextInt(5) + 1, iterationInfo);
+ mEventListener.clearEvents();
+
+ mSensorManager.unregisterListener(mEventListener, mSensorUnderTest);
+ }
+ }
+
+ public void testSeveralClients() throws InterruptedException {
+ ArrayList<Thread> threads = new ArrayList<Thread>();
+ for(int i = 0; i < this.getNumberOfThreadsToUse(); ++i) {
+ threads.add(new Thread() {
+ @Override
+ public void run() {
+ testStartStopRepeatedly();
+ }
+ });
+ }
+
+ while(!threads.isEmpty()) {
+ Thread thread = threads.remove(0);
+ thread.join();
+ }
+ }
+
+ /**
+ * Test cases batching mode.
+ */
+ public void testRegisterForBatchingZeroReport() {
+ releaseWakeLock();
+
+ boolean result = mSensorManager.registerListener(
+ mEventListener,
+ mSensorUnderTest,
+ SensorManager.SENSOR_DELAY_NORMAL,
+ 0 /*maxBatchReportLatencyUs*/,
+ 0 /*reservedFlags*/,
+ mFlushListener);
+ assertTrue("registerListener", result);
+ mEventListener.waitForEvents(10);
+ }
+
+ public void testCanReceiveBatchEvents() {
+ releaseWakeLock();
+
+ // TODO: refactor out common code across tests that register for events and do post-process
+ boolean result = mSensorManager.registerListener(
+ mEventListener,
+ mSensorUnderTest,
+ SensorManager.SENSOR_DELAY_NORMAL,
+ 5 * 1000000 /*maxBatchReportLatencyUs*/,
+ 0 /*reservedFlags*/,
+ mFlushListener);
+ assertTrue("registerListener", result);
+ mEventListener.waitForEvents(10);
+ }
+
+ public void testBatchEventsArriveInOrder() {
+ releaseWakeLock();
+
+ boolean result = mSensorManager.registerListener(
+ mEventListener,
+ mSensorUnderTest,
+ SensorManager.SENSOR_DELAY_NORMAL,
+ 5 * 1000000 /*maxBatchReportLatencyUs*/,
+ 0 /*reservedFlags*/,
+ mFlushListener);
+ assertTrue("registerListener", result);
+ mEventListener.waitForEvents(100);
+
+ SensorEventForTest[] events = mEventListener.getAllEvents();
+ for(int i = 1; i < events.length; ++i) {
+ long previousTimestamp = events[i-1].getTimestamp();
+ long timestamp = events[i].getTimestamp();
+ assertTrue(
+ String.format("[timestamp:%d] %d >= %d", i, previousTimestamp, timestamp),
+ previousTimestamp < timestamp);
+ }
+ }
+
+ public void testStartStopBatchingRepeatedly() {
+ releaseWakeLock();
+
+ for(int i = 0; i < this.getLowNumberOfIterationsToExecute(); ++i) {
+ String iterationInfo = String.format("registerListener:%d", i);
+ boolean result = mSensorManager.registerListener(
+ mEventListener,
+ mSensorUnderTest,
+ SensorManager.SENSOR_DELAY_FASTEST,
+ 5 * 1000000 /*maxBatchReportLatencyUs*/,
+ 0 /*reservedFlags*/,
+ mFlushListener);
+
+ assertTrue(iterationInfo, result);
+ mEventListener.waitForEvents(5, iterationInfo);
+
+ mSensorManager.unregisterListener(mEventListener, mSensorUnderTest);
+ }
+ }
+
+ public void testUpdateBatchRate() {
+ releaseWakeLock();
+
+ // use a constant seed until it can be logged properly
+ final long seed = 0xFEDCBA98;
+ Random generator = new Random(seed);
+ for(int i = 0; i < this.getHighNumberOfIterationsToExecute(); ++i) {
+ int rate;
+ switch(generator.nextInt(5)) {
+ case 0:
+ rate = SensorManager.SENSOR_DELAY_FASTEST;
+ break;
+ case 1:
+ rate = SensorManager.SENSOR_DELAY_GAME;
+ break;
+ case 2:
+ rate = SensorManager.SENSOR_DELAY_NORMAL;
+ break;
+ case 3:
+ rate = SensorManager.SENSOR_DELAY_UI;
+ break;
+ case 4:
+ default:
+ rate = this.getMaxFrequencySupportedInuS() * generator.nextInt(10);
+ }
+
+ String iterationInfo = String.format("registerListener:%d, rate:%d", i, rate);
+ boolean result = mSensorManager.registerListener(
+ mEventListener,
+ mSensorUnderTest,
+ rate,
+ generator.nextInt(5 * 1000000),
+ 0 /*reservedFlags*/,
+ mFlushListener);
+ assertTrue(iterationInfo, result);
+
+ mEventListener.waitForEvents(generator.nextInt(5) + 1, iterationInfo);
+ mSensorManager.unregisterListener(mEventListener, mSensorUnderTest);
+ mEventListener.clearEvents();
+ }
+ }
+
+ public void testSeveralClientsBatching() {
+ ArrayList<Thread> threads = new ArrayList<Thread>();
+ for(int i = 0; i < this.getNumberOfThreadsToUse(); ++i) {
+ threads.add(new Thread() {
+ @Override
+ public void run() {
+ testStartStopBatchingRepeatedly();
+ }
+ });
+ }
+
+ while(!threads.isEmpty()) {
+ Thread thread = threads.remove(0);
+ try {
+ thread.join();
+ } catch(InterruptedException e) {
+ // just continue
+ }
+ }
+ }
+
+ /**
+ * Tests for sensor characteristics.
+ */
+ public void testEventJittering() {
+ final long EXPECTED_TIMESTAMP_NS = this.getMaxFrequencySupportedInuS() * 1000;
+ final long THRESHOLD_IN_NS = EXPECTED_TIMESTAMP_NS / 10; // 10%
+ boolean result = mSensorManager.registerListener(
+ mEventListener,
+ mSensorUnderTest,
+ this.getMaxFrequencySupportedInuS());
+ assertTrue("registerListener", result);
+ mEventListener.waitForEvents(100);
+
+ SensorEventForTest[] events = mEventListener.getAllEvents();
+ ArrayList<Long> timestampDeltas = new ArrayList<Long>();
+ for(int i = 1; i < events.length; ++i) {
+ long previousTimestamp = events[i-1].getTimestamp();
+ long timestamp = events[i].getTimestamp();
+ long delta = timestamp - previousTimestamp;
+ long jitterValue = Math.abs(EXPECTED_TIMESTAMP_NS - delta);
+ timestampDeltas.add(jitterValue);
+ }
+
+ Collections.sort(timestampDeltas);
+ long percentile95InNs = timestampDeltas.get(95);
+ long actualPercentValue = (percentile95InNs * 100) / EXPECTED_TIMESTAMP_NS;
+
+ if(percentile95InNs > THRESHOLD_IN_NS) {
+ for(long jitter : timestampDeltas) {
+ Log.e(LOG_TAG, "Jittering delta: " + jitter);
+ }
+ String message = String.format(
+ "95%%Jitter| 10%%:%dns, observed:%dns(%d%%)",
+ THRESHOLD_IN_NS,
+ percentile95InNs,
+ actualPercentValue);
+ fail(message);
+ }
+ }
+
+ /**
+ * Private helpers.
+ */
+ private String getLogTag() {
+ return this.getClass().getSimpleName();
+ }
+
+ private void releaseWakeLock() {
+ PowerManager.WakeLock wakeLock = mWakeLock;
+ mWakeLock = null;
+
+ if(wakeLock != null) {
+ wakeLock.release();
+ }
+ }
+
+ private void collectBugreport() {
+ String commands[] = new String[] {
+ "dumpstate",
+ "dumpsys",
+ "logcat -d -v threadtime",
+ "exit"
+ };
+
+ SimpleDateFormat dateFormat = new SimpleDateFormat("M-d-y_H:m:s.S");
+ String outputFile = String.format(
+ "%s/%s_%s",
+ this.getLogTag(),
+ "/sdcard/Download",
+ dateFormat.format(new Date()));
+
+ DataOutputStream processOutput = null;
+ try {
+ Process process = Runtime.getRuntime().exec("/system/bin/sh -");
+ processOutput = new DataOutputStream(process.getOutputStream());
+
+ for(String command : commands) {
+ processOutput.writeBytes(String.format("%s >> %s\n", command, outputFile));
+ }
+
+ processOutput.flush();
+ process.waitFor();
+
+ Log.d(this.getLogTag(), String.format("Bug-Report collected at: %s", outputFile));
+ } catch (IOException e) {
+ fail("Unable to collect Bug Report. " + e.toString());
+ } catch (InterruptedException e) {
+ fail("Unable to collect Bug Report. " + e.toString());
+ } finally {
+ if(processOutput != null) {
+ try {
+ processOutput.close();
+ } catch(IOException e) {}
+ }
+ }
+ }
+
+ /**
+ * Test method helper implementations
+ */
+ protected void validateSensorEvent(
+ float expectedX,
+ float expectedY,
+ float expectedZ,
+ float threshold) {
+ boolean result = mSensorManager.registerListener(
+ mEventListener,
+ mSensorUnderTest,
+ SensorManager.SENSOR_DELAY_FASTEST);
+
+ assertTrue("registerListener", result);
+ mEventListener.waitForEvents(1);
+ SensorEventForTest event = mEventListener.getLastEvent();
+
+ float xValue = event.getX();
+ assertTrue(
+ String.format("x-axis| expected:%f, actual:%f, threshold:%f", expectedX, xValue, threshold),
+ Math.abs(expectedX - xValue) <= threshold);
+
+ float yValue = event.getY();
+ assertTrue(
+ String.format("y-axis| expected:%f, actual:%f, threshold:%f", expectedY, yValue, threshold),
+ Math.abs(expectedY - yValue) <= threshold);
+
+ float zValue = event.getZ();
+ assertTrue(
+ String.format("z-axis| expected:%f, actual:%f, threshold:%f", expectedZ, zValue, threshold),
+ Math.abs(expectedZ - zValue) <= threshold);
+ }
+
+ protected void validateVarianceWhileStatic(
+ float referenceX,
+ float referenceY,
+ float referenceZ,
+ float threshold) {
+ boolean result = mSensorManager.registerListener(
+ mEventListener,
+ mSensorUnderTest,
+ this.getMaxFrequencySupportedInuS());
+ assertTrue("registerListener", result);
+ mEventListener.waitForEvents(100);
+
+ SensorEventForTest[] events = mEventListener.getAllEvents();
+ ArrayList<Float> deltaValuesX = new ArrayList<Float>();
+ ArrayList<Float> deltaValuesY = new ArrayList<Float>();
+ ArrayList<Float> deltaValuesZ = new ArrayList<Float>();
+ for(int i = 0; i < events.length; ++i) {
+ SensorEventForTest event = events[i];
+ deltaValuesX.add(Math.abs(event.getX() - referenceX));
+ deltaValuesY.add(Math.abs(event.getY() - referenceY));
+ deltaValuesZ.add(Math.abs(event.getZ() - referenceZ));
+ }
+
+ Collections.sort(deltaValuesX);
+ float percentile95X = deltaValuesX.get(95);
+ if(percentile95X > threshold) {
+ for(float valueX : deltaValuesX) {
+ Log.e(LOG_TAG, "Variance|X delta: " + valueX);
+ }
+ String message = String.format(
+ "95%%Variance|X expected:%f, observed:%f",
+ threshold,
+ percentile95X);
+ fail(message);
+ }
+
+ Collections.sort(deltaValuesY);
+ float percentile95Y = deltaValuesY.get(95);
+ if(percentile95Y > threshold) {
+ for(float valueY : deltaValuesY) {
+ Log.e(LOG_TAG, "Variance|Y delta: " + valueY);
+ }
+ String message = String.format(
+ "95%%Variance|Y expected:%f, observed:%f",
+ threshold,
+ percentile95Y);
+ fail(message);
+ }
+
+ Collections.sort(deltaValuesZ);
+ float percentile95Z = deltaValuesZ.get(95);
+ if(percentile95Z > threshold) {
+ for(float valueZ : deltaValuesZ) {
+ Log.e(LOG_TAG, "Variance|Z delta: " + valueZ);
+ }
+ String message = String.format(
+ "95%%Variance|Z expected:%f, observed:%f",
+ threshold,
+ percentile95Z);
+ fail(message);
+ }
+ }
+
+ /**
+ * Private class definitions to support test of event handlers.
+ */
+ protected class SensorEventForTest {
+ private Sensor mSensor;
+ private long mTimestamp;
+ private int mAccuracy;
+
+ private float mValueX;
+ private float mValueY;
+ private float mValueZ;
+
+ public SensorEventForTest(SensorEvent event) {
+ mSensor = event.sensor;
+ mTimestamp = event.timestamp;
+ mAccuracy = event.accuracy;
+ mValueX = event.values[0];
+ mValueY = event.values[1];
+ mValueZ = event.values[2];
+ }
+
+ public Sensor getSensor() {
+ return mSensor;
+ }
+
+ public int getAccuracy() {
+ return mAccuracy;
+ }
+
+ public float getX() {
+ return mValueX;
+ }
+
+ public float getY() {
+ return mValueY;
+ }
+
+ public float getZ() {
+ return mValueZ;
+ }
+
+ public long getTimestamp() {
+ return mTimestamp;
+ }
+ }
+
+ protected class TestSensorListener implements SensorEventListener {
+ private final ConcurrentLinkedDeque<SensorEventForTest> mSensorEventsList =
+ new ConcurrentLinkedDeque<SensorEventForTest>();
+ private volatile CountDownLatch mEventLatch;
+
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ // copy the event because there is no better way to do this in the platform
+ mSensorEventsList.addLast(new SensorEventForTest(event));
+
+ CountDownLatch latch = mEventLatch;
+ if(latch != null) {
+ latch.countDown();
+ }
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ }
+
+ public void waitForEvents(int eventCount) {
+ waitForEvents(eventCount, null);
+ }
+
+ public void waitForEvents(int eventCount, String timeoutInfo) {
+ mEventLatch = new CountDownLatch(eventCount);
+ try {
+ boolean awaitCompleted = mEventLatch.await(getWaitTimeoutInSeconds(), TimeUnit.SECONDS);
+ if(!awaitCompleted) {
+ collectBugreport();
+ }
+
+ String assertMessage = String.format(
+ "WaitForEvents:%d, available:%d, %s",
+ eventCount,
+ mSensorEventsList.size(),
+ timeoutInfo);
+ assertTrue(assertMessage, awaitCompleted);
+ } catch(InterruptedException e) { }
+ }
+
+ public SensorEventForTest getLastEvent() {
+ return mSensorEventsList.getLast();
+ }
+
+ public SensorEventForTest[] getAllEvents() {
+ return mSensorEventsList.toArray(new SensorEventForTest[0]);
+ }
+
+ public void clearEvents() {
+ mSensorEventsList.clear();
+ }
+ }
+
+ private class TestTriggerListener extends TriggerEventListener {
+ @Override
+ public void onTrigger(TriggerEvent event) {
+ }
+ }
+
+ private class TestFlushListener implements FlushCompleteListener {
+ @Override
+ public void onFlushCompleted(Sensor sensor) {
+ }
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorGyroscopeTest.java b/tests/tests/hardware/src/android/hardware/cts/SensorGyroscopeTest.java
new file mode 100644
index 0000000..d3d72a3
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorGyroscopeTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.hardware.cts;
+
+import android.hardware.Sensor;
+
+public class SensorGyroscopeTest extends SensorCommonTests {
+ @Override
+ protected int getMaxFrequencySupportedInuS() {
+ return 10000; // 100Hz
+ }
+
+ @Override
+ protected int getSensorType() {
+ return Sensor.TYPE_GYROSCOPE;
+ }
+
+ @Override
+ public void testEventValidity() {
+ final float THRESHOLD = 0.1f; // dps
+ validateSensorEvent(
+ 0 /*x-axis*/,
+ 0 /*y-axis*/,
+ 0 /*z-axis*/,
+ THRESHOLD);
+ }
+
+ @Override
+ public void testVarianceWhileStatic() {
+ final float THRESHOLD = 0.1f; // dps
+ validateVarianceWhileStatic(
+ 0 /*x-axis*/,
+ 0 /*y-axis*/,
+ 0 /*z-axis*/,
+ THRESHOLD);
+ }
+}
diff --git a/tests/tests/hardware/src/android/hardware/cts/SensorMagneticFieldTest.java b/tests/tests/hardware/src/android/hardware/cts/SensorMagneticFieldTest.java
new file mode 100644
index 0000000..10cabb8
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/cts/SensorMagneticFieldTest.java
@@ -0,0 +1,109 @@
+/*
+ * 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.hardware.cts;
+
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Collections;
+
+public class SensorMagneticFieldTest extends SensorCommonTests {
+ @Override
+ protected int getMaxFrequencySupportedInuS() {
+ return 100000; // 10Hz
+ }
+
+ @Override
+ protected int getSensorType() {
+ return Sensor.TYPE_MAGNETIC_FIELD;
+ }
+
+ @Override
+ public void testEventValidity() {
+ validateSensorEvent(
+ 0 /*x-axis*/,
+ 0 /*y-axis*/,
+ 0 /*z-axis*/,
+ SensorManager.MAGNETIC_FIELD_EARTH_MAX);
+ }
+
+ @Override
+ public void testVarianceWhileStatic() {
+ float THRESHOLD_IN_UT = SensorManager.MAGNETIC_FIELD_EARTH_MAX / 10;
+ boolean result = mSensorManager.registerListener(
+ mEventListener,
+ mSensorUnderTest,
+ this.getMaxFrequencySupportedInuS());
+ assertTrue("registerListener", result);
+ mEventListener.waitForEvents(100);
+
+ SensorEventForTest[] events = mEventListener.getAllEvents();
+ ArrayList<Float> deltaValuesX = new ArrayList<Float>();
+ ArrayList<Float> deltaValuesY = new ArrayList<Float>();
+ ArrayList<Float> deltaValuesZ = new ArrayList<Float>();
+ for(int i = 1; i < events.length; ++i) {
+ SensorEventForTest previousEvent = events[i-1];
+ SensorEventForTest event = events[i];
+
+ deltaValuesX.add(Math.abs(event.getX() - previousEvent.getX()));
+ deltaValuesY.add(Math.abs(event.getY() - previousEvent.getY()));
+ deltaValuesZ.add(Math.abs(event.getZ() - previousEvent.getZ()));
+ }
+
+ Collections.sort(deltaValuesX);
+ float percentile95X = deltaValuesX.get(95);
+ if(percentile95X > THRESHOLD_IN_UT) {
+ for(float valueX : deltaValuesX) {
+ Log.e(LOG_TAG, "Variance|X delta: " + valueX);
+ }
+ String message = String.format(
+ "95%%Variance|X expected:%f, observed:%f",
+ THRESHOLD_IN_UT,
+ percentile95X);
+ fail(message);
+ }
+
+ Collections.sort(deltaValuesY);
+ float percentile95Y = deltaValuesY.get(95);
+ if(percentile95Y > THRESHOLD_IN_UT) {
+ for(float valueY : deltaValuesY) {
+ Log.e(LOG_TAG, "Variance|Y delta: " + valueY);
+ }
+ String message = String.format(
+ "95%%Variance|Y expected:%f, observed:%f",
+ THRESHOLD_IN_UT,
+ percentile95Y);
+ fail(message);
+ }
+
+ Collections.sort(deltaValuesZ);
+ float percentile95Z = deltaValuesZ.get(95);
+ if(percentile95Z > THRESHOLD_IN_UT) {
+ for(float valueZ : deltaValuesZ) {
+ Log.e(LOG_TAG, "Variance|Z delta: " + valueZ);
+ }
+ String message = String.format(
+ "95%%Variance|Z expected:%f, observed:%f",
+ THRESHOLD_IN_UT,
+ percentile95Z);
+ fail(message);
+ }
+ }
+}
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewStartupTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewStartupTest.java
new file mode 100644
index 0000000..a7ee974
--- /dev/null
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewStartupTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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 android.webkit.cts;
+
+
+import android.content.Context;
+import android.cts.util.PollingCheck;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.util.Log;
+import android.webkit.CookieManager;
+import android.webkit.CookieSyncManager;
+import android.webkit.WebView;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class WebViewStartupTest
+ extends ActivityInstrumentationTestCase2<WebViewStartupStubActivity> {
+
+ private static final int TEST_TIMEOUT = 5000;
+ private static final String TAG = "WebViewStartupTest";
+
+ private WebViewStartupStubActivity mActivity;
+
+ public WebViewStartupTest() {
+ super("com.android.cts.stub", WebViewStartupStubActivity.class);
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ mActivity = getActivity();
+ }
+
+ @UiThreadTest
+ public void testCookieManagerBlockingUiThread() throws Throwable {
+ CtsTestServer server = new CtsTestServer(mActivity, false);
+ final String url = server.getCookieUrl("death.html");
+
+ Thread background = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ CookieSyncManager csm = CookieSyncManager.createInstance(mActivity);
+ CookieManager cookieManager = CookieManager.getInstance();
+
+ cookieManager.removeAllCookie();
+ cookieManager.setAcceptCookie(true);
+ cookieManager.setCookie(url, "count=41");
+ Log.i(TAG, "done setting cookie before creating webview");
+ }
+ });
+ background.start();
+ background.join();
+
+ // Now create WebView and test that setting the cookie beforehand really worked.
+ mActivity.createAndAttachWebView();
+ WebViewOnUiThread onUiThread = new WebViewOnUiThread(this, mActivity.getWebView());
+ onUiThread.loadUrlAndWaitForCompletion(url);
+ assertEquals("1|count=41", onUiThread.getTitle()); // outgoing cookie
+ CookieManager cookieManager = CookieManager.getInstance();
+ String cookie = cookieManager.getCookie(url);
+ assertNotNull(cookie);
+ final Pattern pat = Pattern.compile("count=(\\d+)");
+ Matcher m = pat.matcher(cookie);
+ assertTrue(m.matches());
+ assertEquals("42", m.group(1)); // value got incremented
+ }
+
+}