Merge "Camera2: modified video snapshot test" into lmp-dev
diff --git a/CtsBuild.mk b/CtsBuild.mk
index 86ecde8..dbe93c7 100644
--- a/CtsBuild.mk
+++ b/CtsBuild.mk
@@ -47,7 +47,7 @@
endef
define cts-get-native-paths
- $(foreach exe,$(1),$(call intermediates-dir-for,EXECUTABLES,$(exe))/$(exe))
+ $(foreach exe,$(1),$(call intermediates-dir-for,EXECUTABLES,$(exe),,,$(3))/$(exe)$(2))
endef
define cts-get-package-paths
@@ -61,3 +61,7 @@
define cts-get-executable-paths
$(foreach executable,$(1),$(CTS_TESTCASES_OUT)/$(executable))
endef
+
+define cts-get-deqp-test-xmls
+ $(foreach api,$(1),$(CTS_TESTCASES_OUT)/com.drawelements.deqp.$(api).xml)
+endef
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index ce67d37..a31014d 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -69,6 +69,7 @@
CtsDeviceTaskswitchingControl \
CtsDeviceUi \
CtsIntentReceiverApp \
+ CtsIntentSenderApp \
CtsManagedProfileApp \
CtsMonkeyApp \
CtsMonkeyApp2 \
@@ -177,13 +178,16 @@
CtsSecurityHostTestCases \
CtsUsbTests
-# Native test executables that need to have associated test XMLs.
-cts_native_exes := \
+# List of native tests. For 32 bit targets, assumes that there will be
+# one test executable, and it will end in 32. For 64 bit targets, assumes
+# that there will be two executables, one that ends in 32 for the 32
+# bit executable and one that ends in 64 for the 64 bit executable.
+cts_native_tests := \
NativeMediaTest_SL \
NativeMediaTest_XA \
ifeq ($(HOST_OS)-$(HOST_ARCH),$(filter $(HOST_OS)-$(HOST_ARCH),linux-x86 linux-x86_64))
-cts_native_exes += bionic-unit-tests-cts
+cts_native_tests += bionic-unit-tests-cts
endif
cts_ui_tests := \
@@ -199,25 +203,38 @@
cts_target_junit_tests := \
CtsJdwp
+cts_deqp_test_apis := \
+ gles3 \
+ gles31
+
# All the files that will end up under the repository/testcases
# directory of the final CTS distribution.
CTS_TEST_CASES := $(call cts-get-lib-paths,$(cts_host_libraries)) \
$(call cts-get-package-paths,$(cts_test_packages)) \
- $(call cts-get-native-paths,$(cts_native_exes)) \
$(call cts-get-ui-lib-paths,$(cts_ui_tests)) \
$(call cts-get-ui-lib-paths,$(cts_device_jars)) \
$(call cts-get-ui-lib-paths,$(cts_target_junit_tests)) \
$(call cts-get-executable-paths,$(cts_device_executables))
+# NOTE: If compiling on a 64 bit target, TARGET_2ND_ARCH will be non-empty
+# and will cause the function to expand to the secondary arch object
+# directory. If compiling on a 32 bit target, TARGET_2ND_ARCH will be
+# empty and will cause the function to expand to the primary arch object
+# directory.
+CTS_TEST_CASES += $(call cts-get-native-paths,$(cts_native_tests),32,$(TARGET_2ND_ARCH))
+
+ifeq ($(TARGET_IS_64_BIT),true)
+CTS_TEST_CASES += $(call cts-get-native-paths,$(cts_native_tests),64)
+endif
+
# All the XMLs that will end up under the repository/testcases
# and that need to be created before making the final CTS distribution.
CTS_TEST_XMLS := $(call cts-get-test-xmls,$(cts_host_libraries)) \
$(call cts-get-test-xmls,$(cts_test_packages)) \
- $(call cts-get-test-xmls,$(cts_native_exes)) \
+ $(call cts-get-test-xmls,$(cts_native_tests)) \
$(call cts-get-test-xmls,$(cts_target_junit_tests)) \
$(call cts-get-test-xmls,$(cts_ui_tests)) \
- external/deqp/android/cts/com.drawelements.deqp.gles3.xml \
- external/deqp/android/cts/com.drawelements.deqp.gles31.xml
+ $(call cts-get-deqp-test-xmls,$(cts_deqp_test_apis))
# The following files will be placed in the tools directory of the CTS distribution
CTS_TOOLS_LIST :=
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index c78e1d9..bba42ad 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -349,17 +349,6 @@
<meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BluetoothTestActivity" />
</activity>
- <activity android:name=".bluetooth.BleScannerPrivacyMacActivity"
- android:label="@string/ble_privacy_mac_name"
- android:configChanges="keyboardHidden|orientation|screenSize">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
- <meta-data android:name="test_category" android:value="@string/bt_le" />
- <meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BleScannerTestActivity" />
- </activity>
-
<activity android:name=".bluetooth.BleScannerPowerLevelActivity"
android:label="@string/ble_power_level_name"
android:configChanges="keyboardHidden|orientation|screenSize">
@@ -393,17 +382,6 @@
<meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BluetoothTestActivity" />
</activity>
- <activity android:name=".bluetooth.BleAdvertiserPrivacyMacActivity"
- android:label="@string/ble_privacy_mac_name"
- android:configChanges="keyboardHidden|orientation|screenSize">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
- <meta-data android:name="test_category" android:value="@string/bt_le" />
- <meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BleAdvertiserTestActivity" />
- </activity>
-
<activity android:name=".bluetooth.BleAdvertiserPowerLevelActivity"
android:label="@string/ble_power_level_name"
android:configChanges="keyboardHidden|orientation|screenSize">
diff --git a/apps/CtsVerifier/res/layout/ble_advertiser_privacy_mac.xml b/apps/CtsVerifier/res/layout/ble_advertiser_privacy_mac.xml
deleted file mode 100644
index 1c68b98..0000000
--- a/apps/CtsVerifier/res/layout/ble_advertiser_privacy_mac.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:padding="10dip"
- >
- <TextView android:text="@string/ble_advertiser_privacy_mac_instruction"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- />
- <LinearLayout android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- >
- <Button android:id="@+id/ble_privacy_mac_start"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/ble_advertiser_start"
- />
- <Button android:id="@+id/ble_privacy_mac_stop"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/ble_advertiser_stop"
- />
- </LinearLayout>
-
- <include android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- layout="@layout/pass_fail_buttons"
- />
-</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/ble_scanner_power_level.xml b/apps/CtsVerifier/res/layout/ble_scanner_power_level.xml
index 970b03a..b240db6 100644
--- a/apps/CtsVerifier/res/layout/ble_scanner_power_level.xml
+++ b/apps/CtsVerifier/res/layout/ble_scanner_power_level.xml
@@ -22,11 +22,14 @@
<TextView android:text="@string/ble_scanner_power_level_instruction"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:id="@+id/ble_scanner_power_level_instruction"
/>
<LinearLayout android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:layout_below="@+id/ble_scanner_power_level_instruction"
android:layout_centerInParent="true"
+ android:padding="10dp"
>
<LinearLayout android:orientation="horizontal"
android:layout_width="match_parent"
@@ -156,6 +159,9 @@
android:layout_height="wrap_content"
/>
</LinearLayout>
+ <TextView android:id="@+id/ble_timer"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" />
</LinearLayout>
<include android:layout_width="match_parent"
diff --git a/apps/CtsVerifier/res/layout/ble_scanner_privacy_mac.xml b/apps/CtsVerifier/res/layout/ble_scanner_privacy_mac.xml
deleted file mode 100644
index cad78a3..0000000
--- a/apps/CtsVerifier/res/layout/ble_scanner_privacy_mac.xml
+++ /dev/null
@@ -1,80 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:padding="10dip"
- >
-
- <TextView
- android:text="@string/ble_scanner_privacy_mac_instruction"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- />
- <LinearLayout android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- >
- <LinearLayout android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- >
- <TextView android:text="@string/ble_address"
- android:layout_width="100dp"
- android:layout_height="wrap_content"
- />
- <TextView android:id="@+id/ble_mac_address"
- android:layout_weight="1"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- />
- </LinearLayout>
- <LinearLayout android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- >
- <TextView android:id="@+id/ble_mac_count"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- />
- <TextView android:id="@+id/ble_resp_count"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/ble_mac_count"
- />
- </LinearLayout>
- <LinearLayout android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- >
- <TextView android:id="@+id/ble_timer"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- />
- </LinearLayout>
- </LinearLayout>
-
- <include android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- layout="@layout/pass_fail_buttons"
- />
-</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/pa_main.xml b/apps/CtsVerifier/res/layout/pa_main.xml
index b6b8e4b..76cb7d4 100644
--- a/apps/CtsVerifier/res/layout/pa_main.xml
+++ b/apps/CtsVerifier/res/layout/pa_main.xml
@@ -17,11 +17,15 @@
android:layout_width="match_parent"
android:layout_height="match_parent" >
+ <include
+ android:id="@+id/pass_fail_buttons"
+ android:layout_gravity="top"
+ layout="@layout/pass_fail_buttons" />
+
<TextureView
android:id="@+id/texture_view"
android:layout_width="match_parent"
- android:layout_height="match_parent" />
-
- <include layout="@layout/pass_fail_buttons" />
+ android:layout_height="match_parent"
+ android:layout_below="@id/pass_fail_buttons" />
</RelativeLayout>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 22e0cff..2a236d1 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -238,7 +238,7 @@
<string name="ble_power_level_info">BLE Advertiser advertises in 4 different power levels. Scanner should receive them in different strength of Rssi, cannot receive weak signals beyond several feet.</string>
<string name="ble_advertiser_power_level_instruction">Click start to start multi-advertising. Data packets are advertised in 4 different power levels. You may receive message that this device does not support multi advertising. If advertiser does not advertise in 4 power levels, neither you receive the error message, you may not stop the advertising in previous test, or this device does not support 4 advertisers at the same time. Try rebooting the device and run the test to free those advertisers in use.</string>
<string name="ble_advertiser_scan_filter_name">BLE Hardware Scan Filter</string>
- <string name="ble_advertiser_scan_filter_info">BLE Advertiser advertises with 2 different data separately. One can wake up the scanner, the other cannot.</string>
+ <string name="ble_advertiser_scan_filter_info">BLE Advertiser advertises with 2 different data separately. One can wake up the scanner, the other cannot. This test cares about behavior on scanner only.</string>
<string name="ble_advertiser_scannable">Scannable advertising</string>
<string name="ble_advertiser_scannable_instruction">Start scannable advertising, expect scanner consume more power on Monsoon monitor, or see log of GattService from scanner logcat.</string>
<string name="ble_advertiser_unscannable">Unscannble advertising</string>
@@ -256,7 +256,7 @@
<string name="ble_low">Low</string>
<string name="ble_medium">Medium</string>
<string name="ble_high">High</string>
- <string name="ble_scanner_power_level_instruction">Count: Ultra low < low < medium < high\nRssi: Ultra low < low < medium < high\nDistance to see count freezing: Ultra low < low < medium < high\nA common error is ultra low, low and medium behave similarly, with similar rssi, freeze at similar distance.</string>
+ <string name="ble_scanner_power_level_instruction">Count: Ultra low < low < medium < high\nRssi: Ultra low < low < medium < high\nDistance to see count freezing: Ultra low < low < medium < high\nA common error is ultra low, low and medium behave similarly, with similar rssi, freeze at similar distance.\n\n All power level receive a different mac address. After 15 mins, a green text "Get a new Mac address" will show up.</string>
<string name="ble_scanner_scan_filter_name">BLE Hardware Scan Filter</string>
<string name="ble_scanner_scan_filter_info">Lock the screen of scanner, and connect to monsoon. It will not wake up when advertiser is advertising unscannable, and scanner is scanning with filter.</string>
<string name="ble_scanner_scan_filter_instruction">For monsoon test:\n\tClick scan with filter, lock the screen, connect to monsoon. It will not wake up when advertiser is advertising unscannable data packets, but will show a peak in power usage when advertiser is advertising scannable data.\nFor logcat test:\n\tClick scan with filter, logcat the scanner. No data will be received by GattService when advertiser is advertising unscannable data.</string>
@@ -469,7 +469,7 @@
<string name="snsr_test_pass">PASS</string>
<string name="snsr_test_skipped">SKIPPED</string>
<string name="snsr_test_fail">FAIL</string>
- <string name="snsr_executing_test">\nExecuting test case \'%1$s\'..\n</string>
+ <string name="snsr_execution_time">Test execution time %1$s sec</string>
<!-- Strings to interact with users in Sensor Tests -->
<string name="snsr_test_play_sound">A sound will be played once the verification is complete...</string>
@@ -479,10 +479,10 @@
<string name="snsr_keep_device_rotating_clockwise">Once the test begins, you will have to keep rotating the device clockwise.</string>
<string name="snsr_wait_for_user">Press \'Next\' to continue.</string>
<string name="snsr_wait_to_begin">Press \'Next\' to begin.</string>
- <string name="snsr_wait_to_complete">Press \'Next\' to complete.</string>
<string name="snsr_on_complete_return">After completing the task, go back to this test.</string>
<string name="snsr_movement_expected">Movement was expected during the test. Found=%1$b.</string>
- <string name="snsr_sensor_feature_deactivation">Additionally, turn off any other features installed in the device, that register for sensors. Once you are done, you can continue the test.</string>
+ <string name="snsr_sensor_feature_deactivation">Turn off any special features installed in the
+ device that register for sensors. Once you are done, you can begin the test.</string>
<string name="snsr_setting_mode_request">You will be redirected to set \'%1$s\' to: %2$s.</string>
<string name="snsr_setting_mode_set">\'%1$s\' set to: %2$s.</string>
<string name="snsr_setting_mode_not_set">\'%1$s\' not set to: %2$s.</string>
@@ -491,7 +491,6 @@
<string name="snsr_setting_auto_rotate_screen_mode">Auto-rotate screen</string>
<string name="snsr_setting_keep_screen_on">Stay awake</string>
<string name="snsr_setting_location_mode">Location</string>
- <string name="snsr_setting_auto_screen_off_mode">Display Sleep</string>
<string name="snsr_pass_on_error">Pass Anyway</string>
<string name="snsr_run_automated_tests">The screen will be turned off to execute the tests,
when tests complete, the device will vibrate and the screen will be turned back on.</string>
@@ -526,7 +525,6 @@
facing the ceiling. Read the instructions for each scenario, before you perform the
test.</string>
<string name="snsr_gyro_device_static">Leave the device static.</string>
- <string name="snsr_gyro_rotate_clockwise">Rotate the device clockwise.</string>
<string name="snsr_gyro_rotate_device">Once you begin the test, you will need to rotate the
device 360deg (one time) in the direction show by the animation, then place it back on the
flat surface.</string>
@@ -550,20 +548,15 @@
<string name="snsr_mag_measurement">-> (%1$.2f, %2$.2f, %3$.2f) : %4$.2f uT</string>
<!-- Sensor Value Accuracy -->
- <string name="snsr_val_acc_test">Sensor Value Accuracy Tests</string>
<string name="snsr_rot_vec_test">Rotation Vector Accuracy Test</string>
- <string name="snsr_collected_events_length">Sensor(%2$s). Collected events expected to be greater than zero. Found=%1$d.</string>
<string name="snsr_event_length">Sensor(%3$s). Event values expected to have size=%1$d. Found=%2$d.</string>
- <string name="snsr_event_length_positive">Sensor(%2$s). Event values expected to have size > 0. Found=%1$d</string>
<string name="snsr_event_value">Sensor(%3$s). Event value[0] expected to be of value=%1$f. Found=%2$f.</string>
<string name="snsr_event_time">Sensor(%5$s). Event timestamp expected to be synchronized with SystemClock.elapsedRealtimeNanos(). Event received at=%1$d. Event timestamp=%2$d. Delta=%3$d. Threshold=%4$d.</string>
- <string name="snsr_event_time_positive">Sensor(%2$s). Event timestamp expected to positive (> 0). Found=%1$d.</string>
<!-- Sensor Batching -->
<string name="snsr_batch_test">Sensor Batching Tests</string>
<string name="snsr_batching_walking_needed">Once the test begins, you will have to take the
device in your hand and walk.</string>
- <string name="snsr_batching_fifo_count">FifoReservedEventCount=%1$d. Expected to be at most FifoMaxEventCount=%2$d.</string>
<!-- Sensor Synchronization -->
<string name="snsr_synch_test">Sensor Synchronization Test</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertiserPrivacyMacActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertiserPrivacyMacActivity.java
deleted file mode 100644
index 87879bd..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertiserPrivacyMacActivity.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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 com.android.cts.verifier.bluetooth;
-
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Bundle;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.Toast;
-
-public class BleAdvertiserPrivacyMacActivity extends PassFailButtons.Activity {
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.ble_advertiser_privacy_mac);
- setPassFailButtonClickListeners();
- setInfoResources(R.string.ble_privacy_mac_name,
- R.string.ble_privacy_mac_info, -1);
-
- ((Button) findViewById(R.id.ble_privacy_mac_start))
- .setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(BleAdvertiserPrivacyMacActivity.this,
- BleAdvertiserService.class);
- intent.putExtra(BleAdvertiserService.EXTRA_COMMAND,
- BleAdvertiserService.COMMAND_START_ADVERTISE);
- startService(intent);
- }
- });
- ((Button) findViewById(R.id.ble_privacy_mac_stop))
- .setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- stopAdvertising();
- }
- });
-
- }
-
- @Override
- public void onResume() {
- super.onResume();
- IntentFilter filter = new IntentFilter();
- filter.addAction(BleAdvertiserService.BLE_START_ADVERTISE);
- filter.addAction(BleAdvertiserService.BLE_STOP_ADVERTISE);
- registerReceiver(onBroadcast, filter);
- }
-
- @Override
- public void onPause() {
- super.onPause();
- unregisterReceiver(onBroadcast);
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- stopAdvertising();
- }
-
- private void showMessage(String msg) {
- Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
- }
-
- private void stopAdvertising() {
- Intent intent = new Intent(BleAdvertiserPrivacyMacActivity.this,
- BleAdvertiserService.class);
- intent.putExtra(BleAdvertiserService.EXTRA_COMMAND,
- BleAdvertiserService.COMMAND_STOP_ADVERTISE);
- startService(intent);
- }
-
- private BroadcastReceiver onBroadcast = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- switch (intent.getAction()) {
- case BleAdvertiserService.BLE_START_ADVERTISE:
- showMessage("Start advertising, please hold for 15 min");
- break;
- case BleAdvertiserService.BLE_STOP_ADVERTISE:
- showMessage("Stop advertising");
- break;
- }
- }
- };
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerPowerLevelActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerPowerLevelActivity.java
index 925c766..a6489c1 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerPowerLevelActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerPowerLevelActivity.java
@@ -19,6 +19,7 @@
import com.android.cts.verifier.PassFailButtons;
import com.android.cts.verifier.R;
+import java.lang.Math;
import java.util.Set;
import java.util.Map;
import java.util.HashMap;
@@ -29,6 +30,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
+import android.os.CountDownTimer;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
@@ -44,6 +46,10 @@
private Map<Integer, Integer> mCount;
private int[] mPowerLevel;
+ private TextView mTimerText;
+ private CountDownTimer mTimer;
+ private static final long REFRESH_MAC_TIME = 930000; // 15.5 min
+
private static final int[] POWER_DBM = {-21, -15, -7, 1, 9};
@Override
@@ -54,9 +60,25 @@
setInfoResources(R.string.ble_power_level_name,
R.string.ble_power_level_info, -1);
- mCount = new HashMap<Integer, Integer>();
+ mTimerText = (TextView)findViewById(R.id.ble_timer);
+ mTimer = new CountDownTimer(REFRESH_MAC_TIME, 1000) {
+ @Override
+ public void onTick(long millis) {
+ int min = (int)millis / 60000;
+ int sec = ((int)millis / 1000) % 60;
+ mTimerText.setText(min + ":" + sec);
+ }
+
+ @Override
+ public void onFinish() {
+ mTimerText.setTextColor(getResources().getColor(R.color.red));
+ mTimerText.setText("Time is up!");
+ }
+ };
+
mRssiText = new HashMap<Integer, TextView>();
mCountText = new HashMap<Integer, TextView>();
+ mCount = null;
mMacText = new HashMap<Integer, TextView>();
mSetPowerText = new HashMap<Integer, TextView>();
mPowerLevel = new int[]{AdvertiseSettings.ADVERTISE_TX_POWER_ULTRA_LOW,
@@ -64,9 +86,6 @@
AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM,
AdvertiseSettings.ADVERTISE_TX_POWER_HIGH};
- for (int i : mPowerLevel) {
- mCount.put(i, 0);
- }
mMacText.put(AdvertiseSettings.ADVERTISE_TX_POWER_ULTRA_LOW,
(TextView)findViewById(R.id.ble_ultra_low_mac));
mMacText.put(AdvertiseSettings.ADVERTISE_TX_POWER_LOW,
@@ -114,6 +133,7 @@
IntentFilter filter = new IntentFilter();
filter.addAction(BleScannerService.BLE_POWER_LEVEL);
+ filter.addAction(BleScannerService.BLE_PRIVACY_NEW_MAC_RECEIVE);
registerReceiver(onBroadcast, filter);
}
@@ -135,26 +155,43 @@
switch (intent.getAction()) {
case BleScannerService.BLE_POWER_LEVEL:
int powerLevelBit = intent.getIntExtra(
- BleScannerService.EXTRA_POWER_LEVEL_BIT, -1);
+ BleScannerService.EXTRA_POWER_LEVEL_BIT, -1);
int powerLevel = intent.getIntExtra(BleScannerService.EXTRA_POWER_LEVEL, -2);
if (powerLevelBit < 0 || powerLevelBit > 3) {
- Toast.makeText(context, "Invalid power level", Toast.LENGTH_SHORT).show();
- break;
+ Toast.makeText(context, "Invalid power level", Toast.LENGTH_SHORT).show();
+ break;
+ }
+
+ if (mCount == null) {
+ mCount = new HashMap<Integer, Integer>();
+ for (int i : mPowerLevel) {
+ mCount.put(i, 0);
+ }
+ mTimer.start();
}
Integer t = mCount.get(powerLevelBit) + 1;
mCount.put(powerLevelBit, t);
mCountText.get(powerLevelBit).setText(t.toString());
+
mMacText.get(powerLevelBit)
.setText(intent.getStringExtra(BleScannerService.EXTRA_MAC_ADDRESS));
mRssiText.get(powerLevelBit)
.setText(intent.getStringExtra(BleScannerService.EXTRA_RSSI));
- if (POWER_DBM[powerLevelBit] == powerLevel) {
+ if (Math.abs(POWER_DBM[powerLevelBit] - powerLevel) < 2) {
mSetPowerText.get(powerLevelBit).setText("Valid power level");
} else {
mSetPowerText.get(powerLevelBit)
.setText("Unknown BLe advertise tx power: " + powerLevel);
}
break;
+ case BleScannerService.BLE_PRIVACY_NEW_MAC_RECEIVE:
+ Toast.makeText(context, "New MAC address detected", Toast.LENGTH_SHORT)
+ .show();
+ mTimerText.setTextColor(getResources().getColor(R.color.green));
+ mTimerText.append(" Get new MAC address.");
+ mTimer.cancel();
+ getPassButton().setEnabled(true);
+ break;
}
}
};
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerPrivacyMacActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerPrivacyMacActivity.java
deleted file mode 100644
index b7e4129..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerPrivacyMacActivity.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * 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 com.android.cts.verifier.bluetooth;
-
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Bundle;
-import android.os.CountDownTimer;
-import android.widget.TextView;
-import android.widget.Toast;
-
-public class BleScannerPrivacyMacActivity extends PassFailButtons.Activity {
-
- private static final String TAG = "BleScannerPrivacyMac";
-
- private int mMacCount;
- private int mRespCount;
- private TextView mMacText;
- private TextView mCountText;
- private TextView mRespText;
- private TextView mTimerText;
- private CountDownTimer mTimer;
- private static final long REFRESH_MAC_TIME = 930000; // 15.5 min
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.ble_scanner_privacy_mac);
- setPassFailButtonClickListeners();
- setInfoResources(R.string.ble_privacy_mac_name,
- R.string.ble_privacy_mac_info, -1);
- getPassButton().setEnabled(false);
- mMacCount = 0;
- mRespCount = 0;
- mMacText = (TextView)findViewById(R.id.ble_mac_address);
- mCountText = (TextView)findViewById(R.id.ble_mac_count);
- mRespText = (TextView)findViewById(R.id.ble_resp_count);
- mTimerText = (TextView)findViewById(R.id.ble_timer);
-
- mTimer = new CountDownTimer(REFRESH_MAC_TIME, 1000) {
- @Override
- public void onTick(long millis) {
- int min = (int)millis / 60000;
- int sec = ((int)millis / 1000) % 60;
- mTimerText.setText(min + ":" + sec);
- }
-
- @Override
- public void onFinish() {
- mTimerText.setTextColor(getResources().getColor(R.color.red));
- mTimerText.setText("Time is up!");
- stop();
- }
- };
-
- }
-
- @Override
- public void onResume() {
- super.onResume();
-
- IntentFilter filter = new IntentFilter();
- filter.addAction(BleScannerService.BLE_PRIVACY_NEW_MAC_RECEIVE);
- filter.addAction(BleScannerService.BLE_MAC_ADDRESS);
- filter.addAction(BleScannerService.BLE_SCAN_RESP);
- registerReceiver(onBroadcast, filter);
-
- if (mMacCount == 0) {
- Intent intent = new Intent(this, BleScannerService.class);
- intent.putExtra(BleScannerService.EXTRA_COMMAND, BleScannerService.COMMAND_PRIVACY_MAC);
- startService(intent);
- }
- }
-
-
- private BroadcastReceiver onBroadcast = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- switch (intent.getAction()) {
- case BleScannerService.BLE_PRIVACY_NEW_MAC_RECEIVE:
- mMacText.append(", " + intent.getStringExtra(BleScannerService.EXTRA_MAC_ADDRESS));
- Toast.makeText(context, "New MAC address detected", Toast.LENGTH_SHORT).show();
- mTimerText.setTextColor(getResources().getColor(R.color.green));
- mTimerText.append(" Get new MAC address.");
- mTimer.cancel();
- getPassButton().setEnabled(true);
- break;
- case BleScannerService.BLE_MAC_ADDRESS:
- if (mMacCount == 0) {
- mMacText.setText(intent.getStringExtra(BleScannerService.EXTRA_MAC_ADDRESS));
- mTimer.start();
- }
- mMacCount++;
- mCountText.setText("Count: " + mMacCount);
- break;
- case BleScannerService.BLE_SCAN_RESP:
- mRespCount++;
- mRespText.setText("Response: " + mRespCount);
- break;
- }
- }
- };
-
- @Override
- public void onPause() {
- super.onPause();
- unregisterReceiver(onBroadcast);
- }
-
- private void stop() {
- stopService(new Intent(this, BleScannerService.class));
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- stop();
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerService.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerService.java
index c8e7953..d3d96ac 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerService.java
@@ -19,6 +19,7 @@
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
+import android.bluetooth.le.AdvertiseSettings;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
@@ -44,7 +45,6 @@
public static final boolean DEBUG = true;
public static final String TAG = "BleScannerService";
- public static final int COMMAND_PRIVACY_MAC = 0;
public static final int COMMAND_POWER_LEVEL = 1;
public static final int COMMAND_SCAN_WITH_FILTER = 2;
public static final int COMMAND_SCAN_WITHOUT_FILTER = 3;
@@ -105,21 +105,6 @@
int command = intent.getIntExtra(EXTRA_COMMAND, -1);
switch (command) {
- case COMMAND_PRIVACY_MAC:
- filters.add(new ScanFilter.Builder()
- .setManufacturerData(MANUFACTURER_TEST_ID,
- new byte[]{MANUFACTURER_TEST_ID, 0})
- .setServiceData(new ParcelUuid(BleAdvertiserService.PRIVACY_MAC_UUID),
- BleAdvertiserService.PRIVACY_MAC_DATA)
- .build());
- filters.add(new ScanFilter.Builder()
- .setManufacturerData(MANUFACTURER_TEST_ID,
- new byte[]{MANUFACTURER_TEST_ID, 0})
- .setServiceData(new ParcelUuid(BleAdvertiserService.SCAN_RESP_UUID),
- BleAdvertiserService.PRIVACY_RESPONSE)
- .build());
- settingBuilder.setScanMode(ScanSettings.SCAN_MODE_BALANCED);
- break;
case COMMAND_POWER_LEVEL:
filters.add(new ScanFilter.Builder()
.setManufacturerData(MANUFACTURER_TEST_ID,
@@ -182,21 +167,6 @@
String mac = result.getDevice().getAddress();
Map<ParcelUuid, byte[]> serviceData = record.getServiceData();
- if (serviceData.get(new ParcelUuid(BleAdvertiserService.PRIVACY_MAC_UUID)) != null) {
- Intent privacyIntent = new Intent(BLE_MAC_ADDRESS);
- privacyIntent.putExtra(EXTRA_MAC_ADDRESS, mac);
- sendBroadcast(privacyIntent);
-
- if (mOldMac == null) {
- mOldMac = mac;
- } else if (!mOldMac.equals(mac)) {
- mOldMac = mac;
- Intent newIntent = new Intent(BLE_PRIVACY_NEW_MAC_RECEIVE);
- newIntent.putExtra(EXTRA_MAC_ADDRESS, mac);
- sendBroadcast(newIntent);
- }
- }
-
if (serviceData.get(new ParcelUuid(BleAdvertiserService.POWER_LEVEL_UUID)) != null) {
byte[] data =
serviceData.get(new ParcelUuid(BleAdvertiserService.POWER_LEVEL_UUID));
@@ -207,6 +177,18 @@
powerIntent.putExtra(EXTRA_RSSI, new Integer(result.getRssi()).toString());
powerIntent.putExtra(EXTRA_POWER_LEVEL_BIT, (int)data[2]);
sendBroadcast(powerIntent);
+
+ // Check privacy mac.
+ if (data[2] == AdvertiseSettings.ADVERTISE_TX_POWER_HIGH) {
+ String newMac = result.getDevice().getAddress();
+ if (mOldMac == null) {
+ mOldMac = newMac;
+ } else if (!mOldMac.equals(mac)) {
+ mOldMac = newMac;
+ Intent newIntent = new Intent(BLE_PRIVACY_NEW_MAC_RECEIVE);
+ sendBroadcast(newIntent);
+ }
+ }
}
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/projection/offscreen/ProjectionOffscreenActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/projection/offscreen/ProjectionOffscreenActivity.java
index f992618..510a03b 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/projection/offscreen/ProjectionOffscreenActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/projection/offscreen/ProjectionOffscreenActivity.java
@@ -26,6 +26,9 @@
import android.graphics.PixelFormat;
import android.media.Image;
import android.media.ImageReader;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -68,7 +71,7 @@
protected TestStatus mTestStatus = TestStatus.RUNNING;
private final Runnable sendKeyEventRunnable = new Runnable() {
- @Override
+ @Override
public void run() {
try {
mService.onKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_DOWN));
@@ -79,15 +82,28 @@
}
};
+ private final Runnable playNotificationRunnable = new Runnable() {
+
+ @Override
+ public void run() {
+ Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
+ Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
+ r.play();
+ }
+ };
+
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
- new Handler(Looper.getMainLooper()).postDelayed(
+ Handler handler = new Handler(Looper.getMainLooper());
+ handler.postDelayed(
sendKeyEventRunnable, DELAYED_RUNNABLE_TIME);
mStatusView.setText("Running test...");
mTimeScreenTurnedOff = SystemClock.uptimeMillis();
+ // Notify user its safe to turn screen back on after 5s + fudge factor
+ handler.postDelayed(playNotificationRunnable, TIME_SCREEN_OFF + 500);
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
if (SystemClock.uptimeMillis() - mTimeScreenTurnedOff < TIME_SCREEN_OFF) {
mStatusView.setText("ERROR: Turned on screen too early");
@@ -121,8 +137,9 @@
filter.addAction(Intent.ACTION_SCREEN_ON);
registerReceiver(mReceiver, filter);
- mStatusView.setText(
- "Please turn off your screen and turn it back on after 5 seconds");
+ mStatusView.setText("Please turn off your screen and turn it back on after " +
+ "5 seconds. A sound will be played when it is safe to turn the " +
+ "screen back on");
}
});
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/BatchingTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/BatchingTestActivity.java
index 4ba38a9..6f0a7aa 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/BatchingTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/BatchingTestActivity.java
@@ -19,15 +19,12 @@
import com.android.cts.verifier.R;
import com.android.cts.verifier.sensors.base.SensorCtsVerifierTestActivity;
-import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.hardware.cts.helpers.TestSensorEnvironment;
import android.hardware.cts.helpers.sensoroperations.TestSensorFlushOperation;
import android.hardware.cts.helpers.sensoroperations.TestSensorOperation;
import android.hardware.cts.helpers.sensoroperations.VerifiableSensorOperation;
-import android.os.Bundle;
-import android.os.PowerManager;
import java.util.concurrent.TimeUnit;
@@ -51,27 +48,9 @@
// such events to generate
private static final int REPORT_LATENCY_25_SEC = 25;
- private PowerManager.WakeLock mWakeLock;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- }
-
- @Override
- protected void activitySetUp() throws InterruptedException {
- PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
- mWakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "BatchingTests");
- mWakeLock.acquire();
- }
-
- @Override
- protected void activityCleanUp() throws InterruptedException {
- mWakeLock.release();
- }
-
// TODO: refactor to discover all available sensors of each type and dynamically generate test
// cases for all of them
+ @SuppressWarnings("unused")
public String testStepCounter_batching() throws Throwable {
return runBatchTest(
Sensor.TYPE_STEP_COUNTER,
@@ -79,6 +58,7 @@
R.string.snsr_batching_walking_needed);
}
+ @SuppressWarnings("unused")
public String testStepCounter_flush() throws Throwable {
return runFlushTest(
Sensor.TYPE_STEP_COUNTER,
@@ -86,6 +66,7 @@
R.string.snsr_batching_walking_needed);
}
+ @SuppressWarnings("unused")
public String testStepDetector_batching() throws Throwable {
return runBatchTest(
Sensor.TYPE_STEP_DETECTOR,
@@ -93,6 +74,7 @@
R.string.snsr_batching_walking_needed);
}
+ @SuppressWarnings("unused")
public String testStepDetector_flush() throws Throwable {
return runFlushTest(
Sensor.TYPE_STEP_DETECTOR,
@@ -100,6 +82,7 @@
R.string.snsr_batching_walking_needed);
}
+ @SuppressWarnings("unused")
public String testProximity_batching() throws Throwable {
return runBatchTest(
Sensor.TYPE_PROXIMITY,
@@ -107,6 +90,7 @@
R.string.snsr_interaction_needed);
}
+ @SuppressWarnings("unused")
public String testProximity_flush() throws Throwable {
return runFlushTest(
Sensor.TYPE_PROXIMITY,
@@ -114,6 +98,7 @@
R.string.snsr_interaction_needed);
}
+ @SuppressWarnings("unused")
public String testLight_batching() throws Throwable {
return runBatchTest(
Sensor.TYPE_LIGHT,
@@ -121,6 +106,7 @@
R.string.snsr_interaction_needed);
}
+ @SuppressWarnings("unused")
public String testLight_flush() throws Throwable {
return runFlushTest(
Sensor.TYPE_LIGHT,
@@ -164,7 +150,7 @@
return executeTest(operation);
}
- private String executeTest(VerifiableSensorOperation operation) {
+ private String executeTest(VerifiableSensorOperation operation) throws InterruptedException {
operation.addDefaultVerifications();
operation.setLogEvents(true);
operation.execute();
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/GyroscopeMeasurementTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/GyroscopeMeasurementTestActivity.java
index ac63780..4b2a7f4 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/GyroscopeMeasurementTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/GyroscopeMeasurementTestActivity.java
@@ -51,7 +51,7 @@
}
@Override
- protected void activitySetUp() {
+ protected void activitySetUp() throws InterruptedException {
getTestLogger().logInstructions(R.string.snsr_gyro_device_placement);
waitForUserToContinue();
initializeGlSurfaceView(mRenderer);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/MagneticFieldMeasurementTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/MagneticFieldMeasurementTestActivity.java
index bd18a95..553147b 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/MagneticFieldMeasurementTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/MagneticFieldMeasurementTestActivity.java
@@ -46,7 +46,7 @@
}
@Override
- public void activitySetUp() {
+ public void activitySetUp() throws InterruptedException {
calibrateMagnetometer();
}
@@ -165,7 +165,7 @@
/**
* A routine to help operators calibrate the magnetometer.
*/
- private void calibrateMagnetometer() {
+ private void calibrateMagnetometer() throws InterruptedException {
SensorEventListener2 listener = new SensorEventListener2() {
@Override
public void onSensorChanged(SensorEvent event) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RotationVectorTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RotationVectorTestActivity.java
index cd94128..6b804dd 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RotationVectorTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RotationVectorTestActivity.java
@@ -87,7 +87,7 @@
// TODO: take reference value automatically when device is 'still'
clearText();
appendText(R.string.snsr_rotation_vector_set_reference);
- waitForUser();
+ waitForUserToContinue();
clearText();
for (int i = 0; i < MAX_SENSORS_AVAILABLE; ++i) {
@@ -104,7 +104,7 @@
// TODO: take final value automatically when device becomes 'still' at the end
clearText();
appendText(R.string.snsr_rotation_vector_set_final);
- waitForUser();
+ waitForUserToContinue();
clearText();
closeGlSurfaceView();
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorPowerTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorPowerTestActivity.java
index cfc4db0..8370d3e 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorPowerTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorPowerTestActivity.java
@@ -34,11 +34,10 @@
super(SensorPowerTestActivity.class);
}
-
@Override
- public void waitForUserAcknowledgement(final String message) {
+ public void waitForUserAcknowledgement(final String message) throws InterruptedException {
appendText(message);
- waitForUser();
+ waitForUserToContinue();
}
@Override
@@ -63,7 +62,7 @@
}
@Override
- protected void activitySetUp() {
+ protected void activitySetUp() throws InterruptedException {
mScreenManipulator = new SensorTestScreenManipulator(getApplicationContext());
mScreenManipulator.initialize(this);
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorSynchronizationTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorSynchronizationTestActivity.java
index 1dd5984..683430c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorSynchronizationTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SensorSynchronizationTestActivity.java
@@ -7,7 +7,6 @@
import android.annotation.TargetApi;
import android.content.Context;
-import android.graphics.Color;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
@@ -137,9 +136,9 @@
public String testCrossSensorSynchronization() throws Throwable {
appendText("This test provides a rough indication of cross-sensor timestamp synchronization.");
appendText("Hold device still in hand and click 'Next'");
- waitForUser();
+ waitForUserToBegin();
clearText();
- appendText("Quickly twist device upside-down and back", Color.GREEN);
+ appendText("Quickly twist device upside-down and back");
startDataCollection();
Thread.sleep(DATA_COLLECTION_TIME_IN_MS);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SignificantMotionTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SignificantMotionTestActivity.java
index a84a045..faba445 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SignificantMotionTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/SignificantMotionTestActivity.java
@@ -59,6 +59,8 @@
/**
* Test cases.
*/
+
+ @SuppressWarnings("unused")
public String testTrigger() throws Throwable {
return runTest(
R.string.snsr_significant_motion_test_trigger,
@@ -67,6 +69,7 @@
false /* vibrate */);
}
+ @SuppressWarnings("unused")
public String testNotTriggerAfterCancel() throws Throwable {
return runTest(
R.string.snsr_significant_motion_test_cancel,
@@ -78,6 +81,7 @@
/**
* Verifies that Significant Motion is not trigger by the vibrator motion.
*/
+ @SuppressWarnings("unused")
public String testVibratorDoesNotTrigger() throws Throwable {
return runTest(
R.string.snsr_significant_motion_test_vibration,
@@ -90,6 +94,7 @@
* Verifies that the natural motion of keeping the device in hand does not change the location.
* It ensures that Significant Motion will not trigger in that scenario.
*/
+ @SuppressWarnings("unused")
public String testInHandDoesNotTrigger() throws Throwable {
return runTest(
R.string.snsr_significant_motion_test_in_hand,
@@ -98,6 +103,7 @@
false /* vibrate */);
}
+ @SuppressWarnings("unused")
public String testSittingDoesNotTrigger() throws Throwable {
return runTest(
R.string.snsr_significant_motion_test_sitting,
@@ -106,6 +112,7 @@
false /* vibrate */);
}
+ @SuppressWarnings("unused")
public String testTriggerDeactivation() throws Throwable {
SensorTestLogger logger = getTestLogger();
logger.logInstructions(R.string.snsr_significant_motion_test_deactivation);
@@ -167,6 +174,7 @@
}
} finally {
mSensorManager.cancelTriggerSensor(verifier, mSensorSignificantMotion);
+ playSound();
}
return result;
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/StepCounterTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/StepCounterTestActivity.java
index 76d12d9..98368c6 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/StepCounterTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/StepCounterTestActivity.java
@@ -33,7 +33,6 @@
import android.os.SystemClock;
import android.view.MotionEvent;
import android.view.View;
-import android.widget.ScrollView;
import java.util.ArrayList;
import java.util.List;
@@ -86,8 +85,7 @@
"Sensors Step Counter/Detector are not supported.");
}
- ScrollView scrollView = (ScrollView) findViewById(R.id.log_scroll_view);
- scrollView.setOnTouchListener(new View.OnTouchListener() {
+ setLogScrollViewListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// during movement of the device, the ScrollView will detect user taps as attempts
@@ -95,14 +93,27 @@
// to overcome the fact that a ScrollView cannot be disabled from scrolling, we
// listen for ACTION_UP events instead of click events in the child layout
long elapsedTime = SystemClock.elapsedRealtimeNanos();
- if (event.getAction() == MotionEvent.ACTION_UP) {
+ if (event.getAction() != MotionEvent.ACTION_UP) {
+ return false;
+ }
+
+ try {
logUserReportedStep(elapsedTime);
+ } catch (InterruptedException e) {
+ // we cannot propagate the exception in the main thread, so we just catch and
+ // restore the status, we don't need to log as we are terminating anyways
+ Thread.currentThread().interrupt();
}
return false;
}
});
}
+ @Override
+ protected void activityCleanUp() {
+ setLogScrollViewListener(null /* listener */);
+ }
+
public String testWalking() throws Throwable {
return runTest(
R.string.snsr_step_counter_test_walking,
@@ -323,11 +334,10 @@
// TODO: with delayed assertions check events of other types are tracked
}
- private void logUserReportedStep(long timestamp) {
+ private void logUserReportedStep(long timestamp) throws InterruptedException {
if (!mCheckForMotion) {
return;
}
-
playSound();
mTimestampsUserReported.add(timestamp);
getTestLogger().logMessage(R.string.snsr_step_reported, timestamp);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/BaseSensorTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/BaseSensorTestActivity.java
index d1c06cb..0bf9636 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/BaseSensorTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/BaseSensorTestActivity.java
@@ -28,13 +28,14 @@
import android.content.Context;
import android.content.Intent;
import android.hardware.cts.helpers.ActivityResultMultiplexedLatch;
-import android.hardware.cts.helpers.SensorTestStateNotSupportedException;
import android.media.MediaPlayer;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
+import android.os.SystemClock;
import android.os.Vibrator;
import android.provider.Settings;
import android.text.TextUtils;
+import android.text.format.DateUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
@@ -42,8 +43,11 @@
import android.widget.ScrollView;
import android.widget.TextView;
-import java.security.InvalidParameterException;
-import java.util.concurrent.Semaphore;
+import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
/**
* A base Activity that is used to build different methods to execute tests inside CtsVerifier.
@@ -76,10 +80,11 @@
private final int mLayoutId;
private final SensorFeaturesDeactivator mSensorFeaturesDeactivator;
- private final Semaphore mSemaphore = new Semaphore(0);
+ private final ExecutorService mExecutorService = Executors.newSingleThreadExecutor();
private final SensorTestLogger mTestLogger = new SensorTestLogger();
private final ActivityResultMultiplexedLatch mActivityResultMultiplexedLatch =
new ActivityResultMultiplexedLatch();
+ private final ArrayList<CountDownLatch> mWaitForUserLatches = new ArrayList<CountDownLatch>();
private ScrollView mLogScrollView;
private LinearLayout mLogLayout;
@@ -128,7 +133,13 @@
mGLSurfaceView = (GLSurfaceView) findViewById(R.id.gl_surface_view);
updateNextButton(false /*enabled*/);
- new Thread(this).start();
+ mExecutorService.execute(this);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mExecutorService.shutdownNow();
}
@Override
@@ -149,7 +160,12 @@
@Override
public void onClick(View target) {
- mSemaphore.release();
+ synchronized (mWaitForUserLatches) {
+ for (CountDownLatch latch : mWaitForUserLatches) {
+ latch.countDown();
+ }
+ mWaitForUserLatches.clear();
+ }
}
@Override
@@ -167,40 +183,36 @@
*/
@Override
public void run() {
+ long startTimeNs = SystemClock.elapsedRealtimeNanos();
String testName = getTestClassName();
- // guarantee the proper clean up of tests based on the operations that successfully ran
- SensorTestDetails testDetails = deactivateSensorFeatures();
- if (testDetails.getResultCode() == SensorTestDetails.ResultCode.PASS) {
- // sensor features
- testDetails = executeActivitySetUp();
- if (testDetails.getResultCode() == SensorTestDetails.ResultCode.PASS) {
- // activity set up
- // TODO: implement execution filters:
- // - execute all tests and report results officially
- // - execute single test or failed tests only
- testDetails = executeTests();
- try {
- activityCleanUp();
- } catch (Throwable e) {
- testDetails = new SensorTestDetails(
- testName,
- SensorTestDetails.ResultCode.FAIL,
- "[ActivityCleanUp] " + e.getMessage());
- }
- // end activity set up
- }
- try {
- mSensorFeaturesDeactivator.requestToRestoreFeatures();
- } catch (Throwable e) {
- testDetails = new SensorTestDetails(
- testName,
- SensorTestDetails.ResultCode.FAIL,
- "[RestoreSensorFeatures] " + e.getMessage());
- }
- // end sensor features
+ SensorTestDetails testDetails;
+ try {
+ mSensorFeaturesDeactivator.requestDeactivationOfFeatures();
+ testDetails = new SensorTestDetails(testName, SensorTestDetails.ResultCode.PASS);
+ } catch (Throwable e) {
+ testDetails = new SensorTestDetails(testName, "DeactivateSensorFeatures", e);
}
+
+ SensorTestDetails.ResultCode resultCode = testDetails.getResultCode();
+ if (resultCode == SensorTestDetails.ResultCode.SKIPPED) {
+ // this is an invalid state at this point of the test setup
+ throw new IllegalStateException("Deactivation of features cannot skip the test.");
+ }
+ if (resultCode == SensorTestDetails.ResultCode.PASS) {
+ testDetails = executeActivityTests(testName);
+ }
+
+ // we consider all remaining states at this point, because we could have been half way
+ // deactivating features
+ try {
+ mSensorFeaturesDeactivator.requestToRestoreFeatures();
+ } catch (Throwable e) {
+ testDetails = new SensorTestDetails(testName, "RestoreSensorFeatures", e);
+ }
+
mTestLogger.logTestDetails(testDetails);
+ mTestLogger.logExecutionTime(startTimeNs);
// because we cannot enforce test failures in several devices, set the test UI so the
// operator can report the result of the test
@@ -210,6 +222,9 @@
/**
* A general set up routine. It executes only once before the first test case.
*
+ * NOTE: implementers must be aware of the interrupted status of the worker thread, and let
+ * {@link InterruptedException} propagate.
+ *
* @throws Throwable An exception that denotes the failure of set up. No tests will be executed.
*/
protected void activitySetUp() throws Throwable {}
@@ -218,6 +233,11 @@
* A general clean up routine. It executes upon successful execution of {@link #activitySetUp()}
* and after all the test cases.
*
+ * NOTE: implementers must be aware of the interrupted status of the worker thread, and handle
+ * it in two cases:
+ * - let {@link InterruptedException} propagate
+ * - if it is invoked with the interrupted status, prevent from showing any UI
+
* @throws Throwable An exception that will be logged and ignored, for ease of implementation
* by subclasses.
*/
@@ -229,7 +249,7 @@
*
* @return A {@link SensorTestDetails} object containing information about the executed tests.
*/
- protected abstract SensorTestDetails executeTests();
+ protected abstract SensorTestDetails executeTests() throws InterruptedException;
@Override
public SensorTestLogger getTestLogger() {
@@ -237,11 +257,6 @@
}
@Deprecated
- protected void appendText(String text, int textColor) {
- appendText(text);
- }
-
- @Deprecated
protected void appendText(int resId) {
mTestLogger.logInstructions(resId);
}
@@ -268,21 +283,22 @@
*
* @param waitMessageResId The action requested to the operator.
*/
- protected void waitForUser(int waitMessageResId) {
+ protected void waitForUser(int waitMessageResId) throws InterruptedException {
+ CountDownLatch latch = new CountDownLatch(1);
+ synchronized (mWaitForUserLatches) {
+ mWaitForUserLatches.add(latch);
+ }
+
mTestLogger.logInstructions(waitMessageResId);
updateNextButton(true);
- try {
- mSemaphore.acquire();
- } catch (InterruptedException e) {
- Log.e(LOG_TAG, "Error on waitForUser", e);
- }
+ latch.await();
updateNextButton(false);
}
/**
* Waits for the operator to acknowledge to begin execution.
*/
- protected void waitForUserToBegin() {
+ protected void waitForUserToBegin() throws InterruptedException {
waitForUser(R.string.snsr_wait_to_begin);
}
@@ -290,20 +306,15 @@
* {@inheritDoc}
*/
@Override
- public void waitForUserToContinue() {
+ public void waitForUserToContinue() throws InterruptedException {
waitForUser(R.string.snsr_wait_for_user);
}
- @Deprecated
- protected void waitForUser() {
- waitForUserToContinue();
- }
-
/**
* {@inheritDoc}
*/
@Override
- public int executeActivity(String action) {
+ public int executeActivity(String action) throws InterruptedException {
return executeActivity(new Intent(action));
}
@@ -311,7 +322,7 @@
* {@inheritDoc}
*/
@Override
- public int executeActivity(Intent intent) {
+ public int executeActivity(Intent intent) throws InterruptedException {
ActivityResultMultiplexedLatch.Latch latch = mActivityResultMultiplexedLatch.bindThread();
startActivityForResult(intent, latch.getRequestCode());
return latch.await();
@@ -352,18 +363,15 @@
/**
* Plays a (default) sound as a notification for the operator.
*/
- protected void playSound() {
+ protected void playSound() throws InterruptedException {
MediaPlayer player = MediaPlayer.create(this, Settings.System.DEFAULT_NOTIFICATION_URI);
if (player == null) {
Log.e(LOG_TAG, "MediaPlayer unavailable.");
return;
}
-
player.start();
try {
Thread.sleep(500);
- } catch(InterruptedException e) {
- Log.d(LOG_TAG, "Error on playSound", e);
} finally {
player.stop();
}
@@ -411,10 +419,16 @@
return mTestClass.getName();
}
+ protected void setLogScrollViewListener(View.OnTouchListener listener) {
+ mLogScrollView.setOnTouchListener(listener);
+ }
+
private void setTestResult(SensorTestDetails testDetails) {
+ // the name here, must be the Activity's name because it is what CtsVerifier expects
+ String name = super.getClass().getName();
String summary = mTestLogger.getOverallSummary();
- String name = testDetails.getName();
- switch(testDetails.getResultCode()) {
+ SensorTestDetails.ResultCode resultCode = testDetails.getResultCode();
+ switch(resultCode) {
case SKIPPED:
TestResult.setPassedResult(this, name, summary);
break;
@@ -424,48 +438,50 @@
case FAIL:
TestResult.setFailedResult(this, name, summary);
break;
+ case INTERRUPTED:
+ // do not set a result, just return so the test can complete
+ break;
+ default:
+ throw new IllegalStateException("Unknown ResultCode: " + resultCode);
}
}
- private SensorTestDetails deactivateSensorFeatures() {
- String testName = getTestClassName();
- try {
- mSensorFeaturesDeactivator.requestDeactivationOfFeatures();
- } catch (Throwable e) {
- return new SensorTestDetails(
- testName,
- SensorTestDetails.ResultCode.FAIL,
- "[DeactivateSensorFeatures] " + e.getMessage());
- }
- return new SensorTestDetails(
- testName,
- SensorTestDetails.ResultCode.PASS,
- null /* summary */);
- }
-
- private SensorTestDetails executeActivitySetUp() {
- String testName = getTestClassName();
+ private SensorTestDetails executeActivityTests(String testName) {
+ SensorTestDetails testDetails;
try {
activitySetUp();
- } catch (SensorTestStateNotSupportedException e) {
- return new SensorTestDetails(
- testName,
- SensorTestDetails.ResultCode.SKIPPED,
- e.getMessage());
+ testDetails = new SensorTestDetails(testName, SensorTestDetails.ResultCode.PASS);
} catch (Throwable e) {
- return new SensorTestDetails(
- testName,
- SensorTestDetails.ResultCode.FAIL,
- "[ActivitySetUp] " + e.getMessage());
+ testDetails = new SensorTestDetails(testName, "ActivitySetUp", e);
}
- return new SensorTestDetails(
- testName,
- SensorTestDetails.ResultCode.PASS,
- null /* summary */);
+
+ SensorTestDetails.ResultCode resultCode = testDetails.getResultCode();
+ if (resultCode == SensorTestDetails.ResultCode.PASS) {
+ // TODO: implement execution filters:
+ // - execute all tests and report results officially
+ // - execute single test or failed tests only
+ try {
+ testDetails = executeTests();
+ } catch (Throwable e) {
+ // we catch and continue because we have to guarantee a proper clean-up sequence
+ testDetails = new SensorTestDetails(testName, "TestExecution", e);
+ }
+ }
+
+ // clean-up executes for all states, even on SKIPPED and INTERRUPTED there might be some
+ // intermediate state that needs to be taken care of
+ try {
+ activityCleanUp();
+ } catch (Throwable e) {
+ testDetails = new SensorTestDetails(testName, "ActivityCleanUp", e);
+ }
+
+ return testDetails;
}
private void promptUserToSetResult(SensorTestDetails testDetails) {
- if (testDetails.getResultCode() == SensorTestDetails.ResultCode.FAIL) {
+ SensorTestDetails.ResultCode resultCode = testDetails.getResultCode();
+ if (resultCode == SensorTestDetails.ResultCode.FAIL) {
mTestLogger.logInstructions(R.string.snsr_test_complete_with_errors);
enableTestResultButton(
mPassButton,
@@ -475,7 +491,7 @@
mFailButton,
R.string.fail_button_text,
testDetails.cloneAndChangeResultCode(SensorTestDetails.ResultCode.FAIL));
- } else {
+ } else if (resultCode != SensorTestDetails.ResultCode.INTERRUPTED) {
mTestLogger.logInstructions(R.string.snsr_test_complete);
enableTestResultButton(
mPassButton,
@@ -548,7 +564,8 @@
public void logTestDetails(SensorTestDetails testDetails) {
String name = testDetails.getName();
String summary = testDetails.getSummary();
- switch (testDetails.getResultCode()) {
+ SensorTestDetails.ResultCode resultCode = testDetails.getResultCode();
+ switch (resultCode) {
case SKIPPED:
logTestSkip(name, summary);
break;
@@ -558,9 +575,11 @@
case FAIL:
logTestFail(name, summary);
break;
+ case INTERRUPTED:
+ // do nothing, the test was interrupted so do we
+ break;
default:
- throw new InvalidParameterException(
- "Invalid SensorTestDetails.ResultCode: " + testDetails.getResultCode());
+ throw new IllegalStateException("Unknown ResultCode: " + resultCode);
}
}
@@ -589,6 +608,17 @@
return mOverallSummaryBuilder.toString();
}
+ void logExecutionTime(long startTimeNs) {
+ if (Thread.currentThread().isInterrupted()) {
+ return;
+ }
+ long executionTimeNs = SystemClock.elapsedRealtimeNanos() - startTimeNs;
+ long executionTimeSec = TimeUnit.NANOSECONDS.toSeconds(executionTimeNs);
+ // TODO: find a way to format times with nanosecond accuracy and longer than 24hrs
+ String formattedElapsedTime = DateUtils.formatElapsedTime(executionTimeSec);
+ logMessage(R.string.snsr_execution_time, formattedElapsedTime);
+ }
+
private void logTestEnd(int textViewResId, String testSummary) {
TextAppender textAppender = new TextAppender(textViewResId);
textAppender.setText(testSummary);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/ISensorTestStateContainer.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/ISensorTestStateContainer.java
index 3ef7e21..2ba74e3 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/ISensorTestStateContainer.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/ISensorTestStateContainer.java
@@ -33,7 +33,7 @@
/**
* Waits for the operator to acknowledge to continue execution.
*/
- void waitForUserToContinue();
+ void waitForUserToContinue() throws InterruptedException;
/**
* @param resId The resource Id to extract.
@@ -55,7 +55,7 @@
* @param action The action to start the Activity.
* @return The Activity's result code.
*/
- int executeActivity(String action);
+ int executeActivity(String action) throws InterruptedException;
/**
* Starts an Activity and blocks until it completes, then it returns its result back to the
@@ -64,7 +64,7 @@
* @param intent The intent to start the Activity.
* @return The Activity's result code.
*/
- int executeActivity(Intent intent);
+ int executeActivity(Intent intent) throws InterruptedException;
/**
* @return The {@link ContentResolver} associated with the test.
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsTestActivity.java
index 35bff24..16c5fcd 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsTestActivity.java
@@ -37,7 +37,6 @@
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.RunnerBuilder;
-import android.app.KeyguardManager;
import android.content.Context;
import android.hardware.cts.SensorTestCase;
import android.os.PowerManager;
@@ -67,11 +66,11 @@
}
@Override
- protected void activitySetUp() {
- mScreenManipulator = new SensorTestScreenManipulator(getApplicationContext());
- mScreenManipulator.initialize(this);
+ protected void activitySetUp() throws InterruptedException {
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SensorCtsTests");
+ mScreenManipulator = new SensorTestScreenManipulator(getApplicationContext());
+ mScreenManipulator.initialize(this);
SensorTestLogger logger = getTestLogger();
logger.logInstructions(R.string.snsr_no_interaction);
@@ -93,7 +92,9 @@
}
});
mScreenManipulator.turnScreenOn();
- mWakeLock.release();
+ if (mWakeLock.isHeld()) {
+ mWakeLock.release();
+ }
}
@Override
@@ -101,6 +102,7 @@
super.onDestroy();
if (mScreenManipulator != null) {
mScreenManipulator.releaseScreenOn();
+ mScreenManipulator.close();
}
}
@@ -154,7 +156,7 @@
return new JUnit38ClassRunner(sensorTestSuite);
}
- private boolean hasSuiteMethod(Class testClass) {
+ private boolean hasSuiteMethod(Class<?> testClass) {
try {
testClass.getMethod("suite");
return true;
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsTestResult.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsTestResult.java
index 851d405..5bbaaf7 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsTestResult.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsTestResult.java
@@ -39,6 +39,8 @@
private final Context mContext;
private final TestResult mWrappedTestResult;
+ private volatile boolean mInterrupted;
+
public SensorCtsTestResult(Context context, TestResult testResult) {
mContext = context;
mWrappedTestResult = testResult;
@@ -96,12 +98,23 @@
@Override
public void runProtected(Test test, Protectable protectable) {
- mWrappedTestResult.runProtected(test, protectable);
+ try {
+ protectable.protect();
+ } catch (AssertionFailedError e) {
+ addFailure(test, e);
+ } catch (ThreadDeath e) {
+ throw e;
+ } catch (InterruptedException e) {
+ mInterrupted = true;
+ addError(test, e);
+ } catch (Throwable e) {
+ addError(test, e);
+ }
}
@Override
public boolean shouldStop() {
- return mWrappedTestResult.shouldStop();
+ return mInterrupted || mWrappedTestResult.shouldStop();
}
@Override
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsVerifierTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsVerifierTestActivity.java
index 09753cc..a88abd0 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsVerifierTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/base/SensorCtsVerifierTestActivity.java
@@ -19,8 +19,6 @@
import com.android.cts.verifier.sensors.reporting.SensorTestDetails;
-import android.hardware.cts.helpers.SensorTestStateNotSupportedException;
-
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
@@ -47,29 +45,16 @@
}
/**
- * {@inheritDoc}
- */
- protected SensorCtsVerifierTestActivity(
- Class<? extends SensorCtsVerifierTestActivity> testClass,
- int layoutId) {
- super(testClass, layoutId);
- }
-
- /**
* Executes Semi-automated Sensor tests.
* Execution is driven by this class, and allows discovery of tests using reflection.
*/
@Override
- protected SensorTestDetails executeTests() {
+ protected SensorTestDetails executeTests() throws InterruptedException {
// TODO: use reporting to log individual test results
- StringBuilder overallTestResults = new StringBuilder();
for (Method testMethod : findTestMethods()) {
SensorTestDetails testDetails = executeTest(testMethod);
getTestLogger().logTestDetails(testDetails);
- overallTestResults.append(testDetails.toString());
- overallTestResults.append("\n");
}
-
return new SensorTestDetails(
getApplicationContext(),
getTestClassName(),
@@ -91,34 +76,40 @@
return testMethods;
}
- private SensorTestDetails executeTest(Method testMethod) {
+ private SensorTestDetails executeTest(Method testMethod) throws InterruptedException {
String testMethodName = testMethod.getName();
String testName = String.format("%s#%s", getTestClassName(), testMethodName);
- String testSummary;
- SensorTestDetails.ResultCode testResultCode;
+ SensorTestDetails testDetails;
try {
- getTestLogger().logTestStart(testMethod.getName());
- testSummary = (String) testMethod.invoke(this);
- testResultCode = SensorTestDetails.ResultCode.PASS;
- ++mTestPassedCounter;
+ getTestLogger().logTestStart(testMethodName);
+ String testSummary = (String) testMethod.invoke(this);
+ testDetails =
+ new SensorTestDetails(testName, SensorTestDetails.ResultCode.PASS, testSummary);
} catch (InvocationTargetException e) {
// get the inner exception, because we use reflection APIs to execute the test
- Throwable cause = e.getCause();
- testSummary = cause.getMessage();
- if (cause instanceof SensorTestStateNotSupportedException) {
- testResultCode = SensorTestDetails.ResultCode.SKIPPED;
- ++mTestSkippedCounter;
- } else {
- testResultCode = SensorTestDetails.ResultCode.FAIL;
- ++mTestFailedCounter;
- }
+ testDetails = new SensorTestDetails(testName, "TestExecution", e.getCause());
} catch (Throwable e) {
- testSummary = e.getMessage();
- testResultCode = SensorTestDetails.ResultCode.FAIL;
- ++mTestFailedCounter;
+ testDetails = new SensorTestDetails(testName, "TestInfrastructure", e);
}
- return new SensorTestDetails(testName, testResultCode, testSummary);
+ SensorTestDetails.ResultCode resultCode = testDetails.getResultCode();
+ switch(resultCode) {
+ case PASS:
+ ++mTestPassedCounter;
+ break;
+ case SKIPPED:
+ ++mTestSkippedCounter;
+ break;
+ case INTERRUPTED:
+ throw new InterruptedException();
+ case FAIL:
+ ++mTestFailedCounter;
+ break;
+ default:
+ throw new IllegalStateException("Unknown ResultCode: " + resultCode);
+ }
+
+ return testDetails;
}
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/PowerTestHostLink.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/PowerTestHostLink.java
index 0041aec..ed2fea3 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/PowerTestHostLink.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/PowerTestHostLink.java
@@ -53,7 +53,7 @@
public interface HostToDeviceInterface {
void logTestResult(SensorTestDetails testDetails);
void raiseError(String testName, String message) throws Exception;
- void waitForUserAcknowledgement(String message);
+ void waitForUserAcknowledgement(String message) throws InterruptedException;
void logText(String text);
void turnScreenOff();
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorFeaturesDeactivator.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorFeaturesDeactivator.java
index d69d343..82f8ae9 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorFeaturesDeactivator.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorFeaturesDeactivator.java
@@ -32,8 +32,6 @@
*/
public class SensorFeaturesDeactivator {
- private boolean mInitialStateCaptured;
-
private final ISensorTestStateContainer mStateContainer;
private final SensorSettingContainer mAirplaneMode = new AirplaneModeSettingContainer();
@@ -48,7 +46,7 @@
mStateContainer = stateContainer;
}
- public synchronized void requestDeactivationOfFeatures() {
+ public synchronized void requestDeactivationOfFeatures() throws InterruptedException {
captureInitialState();
mAirplaneMode.requestToSetMode(mStateContainer, true);
@@ -63,8 +61,10 @@
mStateContainer.waitForUserToContinue();
}
- public synchronized void requestToRestoreFeatures() {
- if (!isInitialStateCaptured()) {
+ public synchronized void requestToRestoreFeatures() throws InterruptedException {
+ if (Thread.currentThread().isInterrupted()) {
+ // TODO: in the future, if the thread is interrupted, we might need to serialize the
+ // intermediate state we acquired so we can restore when we have a chance
return;
}
@@ -76,21 +76,11 @@
}
private void captureInitialState() {
- if (mInitialStateCaptured) {
- return;
- }
-
mAirplaneMode.captureInitialState();
mScreenBrightnessMode.captureInitialState();
mAutoRotateScreenMode.captureInitialState();
mLocationMode.captureInitialState();
mKeepScreenOnMode.captureInitialState();
-
- mInitialStateCaptured = true;
- }
-
- private boolean isInitialStateCaptured() {
- return mInitialStateCaptured;
}
private class AirplaneModeSettingContainer extends SensorSettingContainer {
@@ -99,13 +89,15 @@
}
@Override
- protected int getSettingMode() {
+ protected int getSettingMode(int defaultValue) {
ContentResolver contentResolver = mStateContainer.getContentResolver();
// Settings.System.AIRPLANE_MODE_ON is deprecated in API 17
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
- return Settings.System.getInt(contentResolver, Settings.System.AIRPLANE_MODE_ON, 0);
+ return Settings.System
+ .getInt(contentResolver, Settings.System.AIRPLANE_MODE_ON, defaultValue);
} else {
- return Settings.Global.getInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0);
+ return Settings.Global
+ .getInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, defaultValue);
}
}
}
@@ -116,11 +108,11 @@
}
@Override
- public int getSettingMode() {
+ public int getSettingMode(int defaultValue) {
return Settings.System.getInt(
mStateContainer.getContentResolver(),
Settings.System.SCREEN_BRIGHTNESS_MODE,
- Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
+ defaultValue);
}
}
@@ -131,11 +123,11 @@
}
@Override
- protected int getSettingMode() {
+ protected int getSettingMode(int defaultValue) {
return Settings.System.getInt(
mStateContainer.getContentResolver(),
Settings.System.ACCELEROMETER_ROTATION,
- 0 /* default */);
+ defaultValue);
}
}
@@ -146,11 +138,11 @@
}
@Override
- protected int getSettingMode() {
+ protected int getSettingMode(int defaultValue) {
return Settings.Global.getInt(
mStateContainer.getContentResolver(),
Settings.Global.STAY_ON_WHILE_PLUGGED_IN,
- 0);
+ defaultValue);
}
}
@@ -160,11 +152,11 @@
}
@Override
- protected int getSettingMode() {
+ protected int getSettingMode(int defaultValue) {
return Settings.Secure.getInt(
mStateContainer.getContentResolver(),
Settings.Secure.LOCATION_MODE,
- Settings.Secure.LOCATION_MODE_OFF);
+ defaultValue);
}
}
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorSettingContainer.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorSettingContainer.java
index 9a0d7e5..2d44d8d 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorSettingContainer.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorSettingContainer.java
@@ -24,12 +24,18 @@
* A helper class for {@link SensorFeaturesDeactivator}. It abstracts the responsibility of handling
* device settings that affect sensors.
*
- * This class is not thread safe. It is meant to be used only by {@link SensorFeaturesDeactivator}.
+ * This class is meant to be used only by {@link SensorFeaturesDeactivator}.
+ * To keep things simple, this class synchronizes access to its internal state on public methods.
+ * This approach is fine, because there is no need for concurrent access.
*/
abstract class SensorSettingContainer {
+ private static final int DEFAULT_SETTING_VALUE = -1;
+
private final String mAction;
private final int mSettingNameResId;
+ private boolean mInitialized;
+ private boolean mSettingAvailable;
private boolean mCapturedModeOn;
public SensorSettingContainer(String action, int settingNameResId) {
@@ -37,13 +43,21 @@
mSettingNameResId = settingNameResId;
}
- public void captureInitialState() {
+ public synchronized void captureInitialState() {
+ if (mInitialized) {
+ return;
+ }
+ mSettingAvailable = getSettingMode(DEFAULT_SETTING_VALUE) != DEFAULT_SETTING_VALUE;
mCapturedModeOn = getCurrentSettingMode();
+ mInitialized = true;
}
public synchronized void requestToSetMode(
ISensorTestStateContainer stateContainer,
- boolean modeOn) {
+ boolean modeOn) throws InterruptedException {
+ if (!isSettingAvailable()) {
+ return;
+ }
trySetMode(stateContainer, modeOn);
if (getCurrentSettingMode() != modeOn) {
String message = stateContainer.getString(
@@ -54,11 +68,16 @@
}
}
- public synchronized void requestToResetMode(ISensorTestStateContainer stateContainer) {
+ public synchronized void requestToResetMode(ISensorTestStateContainer stateContainer)
+ throws InterruptedException {
+ if (!isSettingAvailable()) {
+ return;
+ }
trySetMode(stateContainer, mCapturedModeOn);
}
- private void trySetMode(ISensorTestStateContainer stateContainer, boolean modeOn) {
+ private void trySetMode(ISensorTestStateContainer stateContainer, boolean modeOn)
+ throws InterruptedException {
BaseSensorTestActivity.SensorTestLogger logger = stateContainer.getTestLogger();
String settingName = getSettingName(stateContainer);
if (getCurrentSettingMode() == modeOn) {
@@ -73,12 +92,20 @@
}
private boolean getCurrentSettingMode() {
- return getSettingMode() != 0;
+ return getSettingMode(DEFAULT_SETTING_VALUE) != 0;
}
private String getSettingName(ISensorTestStateContainer stateContainer) {
return stateContainer.getString(mSettingNameResId);
}
- protected abstract int getSettingMode();
+ private boolean isSettingAvailable() {
+ if (!mInitialized) {
+ throw new IllegalStateException(
+ "Object must be initialized first by invoking #captureInitialState.");
+ }
+ return mSettingAvailable;
+ }
+
+ protected abstract int getSettingMode(int defaultValue);
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorTestScreenManipulator.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorTestScreenManipulator.java
index 0263975..835ff56 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorTestScreenManipulator.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/helpers/SensorTestScreenManipulator.java
@@ -85,7 +85,8 @@
* NOTE: Initialization will bring up an Activity to let the user activate the Device Admin,
* this method will block until the user completes the operation.
*/
- public synchronized void initialize(ISensorTestStateContainer stateContainer) {
+ public synchronized void initialize(ISensorTestStateContainer stateContainer)
+ throws InterruptedException {
if (!isDeviceAdminInitialized()) {
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mComponentName);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/reporting/SensorTestDetails.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/reporting/SensorTestDetails.java
index dcf6c4a..c88187c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/reporting/SensorTestDetails.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/reporting/SensorTestDetails.java
@@ -22,6 +22,7 @@
import org.junit.runner.Result;
import android.content.Context;
+import android.hardware.cts.helpers.SensorTestStateNotSupportedException;
/**
* A class that holds the result of a Sensor test execution.
@@ -34,7 +35,12 @@
public enum ResultCode {
SKIPPED,
PASS,
- FAIL
+ FAIL,
+ INTERRUPTED
+ }
+
+ public SensorTestDetails(String name, ResultCode resultCode) {
+ this(name, resultCode, null /* summary */);
}
public SensorTestDetails(String name, ResultCode resultCode, String summary) {
@@ -69,6 +75,21 @@
result.getFailureCount());
}
+ public SensorTestDetails(String name, String tag, Throwable cause) {
+ ResultCode resultCode = ResultCode.FAIL;
+ if (cause instanceof InterruptedException) {
+ resultCode = ResultCode.INTERRUPTED;
+ // the interrupted status must be restored, so other routines can consume it
+ Thread.currentThread().interrupt();
+ } else if (cause instanceof SensorTestStateNotSupportedException) {
+ resultCode = ResultCode.SKIPPED;
+ }
+
+ mName = name;
+ mResultCode = resultCode;
+ mSummary = String.format("[%s] %s", tag, cause.getMessage());
+ }
+
public String getName() {
return mName;
}
diff --git a/build/config.mk b/build/config.mk
index e127e90..931220b 100644
--- a/build/config.mk
+++ b/build/config.mk
@@ -18,3 +18,4 @@
BUILD_CTS_HOST_JAVA_LIBRARY := cts/build/test_host_java_library.mk
BUILD_CTS_TARGET_JAVA_LIBRARY := cts/build/test_target_java_library.mk
BUILD_CTS_UI_JAVA_LIBRARY := cts/build/test_uiautomator.mk
+BUILD_CTS_DEQP_PACKAGE := cts/build/test_deqp_package.mk
diff --git a/build/deqp_dummy_test_list b/build/deqp_dummy_test_list
new file mode 100644
index 0000000..6bf22aa
--- /dev/null
+++ b/build/deqp_dummy_test_list
@@ -0,0 +1,3 @@
+suite:TestSuite
+case:TEST_CASE_NAME
+test:TEST_NAME
diff --git a/build/test_deqp_package.mk b/build/test_deqp_package.mk
new file mode 100644
index 0000000..b07876d
--- /dev/null
+++ b/build/test_deqp_package.mk
@@ -0,0 +1,44 @@
+# 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.
+
+#
+# Builds dEQP test description XMLs needed by CTS.
+#
+
+CTS_DEQP_CONFIG_PATH := $(call my-dir)
+
+cts_library_xml := $(CTS_TESTCASES_OUT)/com.drawelements.deqp.$(DEQP_API).xml
+
+$(cts_library_xml): MUSTPASS_XML_FILE := external/deqp/android/cts/com.drawelements.deqp.$(DEQP_API).xml
+$(cts_library_xml): PRIVATE_TEST_NAME := $(DEQP_TEST_NAME)
+$(cts_library_xml): PRIVATE_TEST_PACKAGE := com.drawelements.deqp.$(DEQP_API)
+$(cts_library_xml): PRIVATE_DUMMY_CASELIST := $(CTS_DEQP_CONFIG_PATH)/deqp_dummy_test_list
+$(cts_library_xml): $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME))/package.apk external/deqp/android/cts/com.drawelements.deqp.$(DEQP_API).xml $(CTS_EXPECTATIONS) $(CTS_UNSUPPORTED_ABIS) $(CTS_XML_GENERATOR)
+ $(hide) echo Generating test description for $(PRIVATE_TEST_NAME)
+ $(hide) mkdir -p $(CTS_TESTCASES_OUT)
+
+# Query build ABIs by routing a dummy test list through xml generator and parse result
+ $(hide) $(eval supported_abi_attr := $(shell $(CTS_XML_GENERATOR) -t dummyTest \
+ -n dummyName \
+ -p invalid.dummy \
+ -e $(CTS_EXPECTATIONS) \
+ -b $(CTS_UNSUPPORTED_ABIS) \
+ -a $(CTS_TARGET_ARCH) \
+ < $(PRIVATE_DUMMY_CASELIST) \
+ | grep --only-matching -e " abis=\"[^\"]*\""))
+
+# Patch xml caselist with supported abi
+ $(hide) $(SED_EXTENDED) -e 's:^<Test (.*)/>$$:<Test \1 $(supported_abi_attr) />:' \
+ < $(MUSTPASS_XML_FILE) \
+ > $@
diff --git a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java
index 83187c7..6720dff 100644
--- a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java
+++ b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTest.java
@@ -54,6 +54,7 @@
mDevice = UiDevice.getInstance(getInstrumentation());
mActivity = launchActivity(getInstrumentation().getTargetContext().getPackageName(),
MyActivity.class, null);
+ mDevice.waitForIdle();
}
@Override
@@ -78,6 +79,7 @@
mActivity.startActivityForResult(intent, 42);
// Ensure that we see both of our roots
+ mDevice.waitForIdle();
assertTrue("CtsLocal root", new UiObject(new UiSelector().text("CtsLocal")).exists());
assertTrue("CtsCreate root", new UiObject(new UiSelector().text("CtsCreate")).exists());
assertFalse("CtsGetContent", new UiObject(new UiSelector().text("CtsGetContent")).exists());
@@ -86,8 +88,6 @@
mDevice.waitForIdle();
new UiObject(new UiSelector().text("CtsLocal")).click();
- // make sure drawer is expanded?
-
mDevice.waitForIdle();
new UiObject(new UiSelector().text("FILE1")).click();
@@ -148,6 +148,7 @@
mDevice.waitForIdle();
new UiObject(new UiSelector().text("FILE1")).click();
+ mDevice.waitForIdle();
new UiObject(new UiSelector().resourceId("com.android.documentsui:id/container_save")
.childSelector(new UiSelector().resourceId("android:id/button1"))).click();
@@ -237,16 +238,15 @@
intent.setType("*/*");
mActivity.startActivityForResult(intent, 42);
- mDevice.waitForIdle();
-
// Look around, we should be able to see both DocumentsProviders and
// other GET_CONTENT sources.
+ mDevice.waitForIdle();
assertTrue("CtsLocal root", new UiObject(new UiSelector().text("CtsLocal")).exists());
assertTrue("CtsCreate root", new UiObject(new UiSelector().text("CtsCreate")).exists());
assertTrue("CtsGetContent", new UiObject(new UiSelector().text("CtsGetContent")).exists());
- new UiObject(new UiSelector().text("CtsGetContent")).click();
mDevice.waitForIdle();
+ new UiObject(new UiSelector().text("CtsGetContent")).click();
final Result result = mActivity.getResult();
assertEquals("ReSuLt", result.data.getAction());
diff --git a/hostsidetests/devicepolicy/app/IntentReceiver/src/com/android/cts/intent/receiver/IntentReceiverActivity.java b/hostsidetests/devicepolicy/app/IntentReceiver/src/com/android/cts/intent/receiver/IntentReceiverActivity.java
index 17dc3f1..59f0752 100644
--- a/hostsidetests/devicepolicy/app/IntentReceiver/src/com/android/cts/intent/receiver/IntentReceiverActivity.java
+++ b/hostsidetests/devicepolicy/app/IntentReceiver/src/com/android/cts/intent/receiver/IntentReceiverActivity.java
@@ -22,12 +22,11 @@
import android.util.Log;
import java.io.BufferedReader;
+import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.io.IOException;
import java.io.OutputStreamWriter;
-
/**
* Class to receive intents sent across profile boundaries, and read/write to content uri specified
* in these intents to test cross-profile content uris.
diff --git a/hostsidetests/devicepolicy/app/IntentSender/Android.mk b/hostsidetests/devicepolicy/app/IntentSender/Android.mk
new file mode 100644
index 0000000..e45ec31
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/IntentSender/Android.mk
@@ -0,0 +1,33 @@
+# Copyright (C) 2014 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_PACKAGE_NAME := CtsIntentSenderApp
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/IntentSender/AndroidManifest.xml b/hostsidetests/devicepolicy/app/IntentSender/AndroidManifest.xml
new file mode 100644
index 0000000..070ef40
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/IntentSender/AndroidManifest.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.cts.intent.sender">
+
+ <uses-sdk android:minSdkVersion="19" />
+
+ <permission
+ android:name="com.android.cts.intent.sender.permission.SAMPLE"
+ android:label="Sample Permission" />
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+
+ <activity android:name=".IntentSenderActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ </intent-filter>
+ </activity>
+
+ <provider
+ android:name="android.support.v4.content.FileProvider"
+ android:authorities="com.android.cts.intent.sender.fileprovider"
+ android:grantUriPermissions="true"
+ android:exported="false">
+ <meta-data
+ android:name="android.support.FILE_PROVIDER_PATHS"
+ android:resource="@xml/filepaths" />
+ </provider>
+
+ <provider
+ android:name=".BasicContentProvider"
+ android:authorities="com.android.cts.intent.sender.provider"
+ android:grantUriPermissions="true"
+ android:exported="true"
+ android:permission="com.android.cts.intent.sender.permission.SAMPLE" />
+
+ </application>
+
+ <instrumentation
+ android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.android.cts.intent.sender"
+ android:label="Intent Sender CTS Tests" />
+
+</manifest>
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/res/xml/filepaths.xml b/hostsidetests/devicepolicy/app/IntentSender/res/xml/filepaths.xml
similarity index 100%
rename from hostsidetests/devicepolicy/app/ManagedProfile/res/xml/filepaths.xml
rename to hostsidetests/devicepolicy/app/IntentSender/res/xml/filepaths.xml
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/BasicContentProvider.java b/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/BasicContentProvider.java
similarity index 96%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/BasicContentProvider.java
rename to hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/BasicContentProvider.java
index f91d404..183ab9f 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/BasicContentProvider.java
+++ b/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/BasicContentProvider.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.cts.managedprofile.crossprofilecontent;
+package com.android.cts.intent.sender;
import android.content.ContentProvider;
import android.content.ContentValues;
@@ -69,4 +69,3 @@
new File("/dev/null"), ParcelFileDescriptor.MODE_READ_ONLY);
}
}
-
diff --git a/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/IntentSenderActivity.java b/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/IntentSenderActivity.java
new file mode 100644
index 0000000..00fa6b7
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/IntentSenderActivity.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2014 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.cts.intent.sender;
+
+import android.app.Activity;
+import android.content.Intent;
+
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.TimeUnit;
+
+public class IntentSenderActivity extends Activity {
+
+ private final SynchronousQueue<Result> mResult = new SynchronousQueue<>();
+
+ public static class Result {
+ public final int resultCode;
+ public final Intent data;
+
+ public Result(int resultCode, Intent data) {
+ this.resultCode = resultCode;
+ this.data = data;
+ }
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (resultCode == Activity.RESULT_OK) {
+ try {
+ mResult.offer(new Result(resultCode, data), 5, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ public Intent getResult(Intent intent) throws Exception {
+ startActivityForResult(intent, 42);
+ final Result result = mResult.poll(30, TimeUnit.SECONDS);
+ return (result != null) ? result.data : null;
+ }
+}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/CrossProfileContentTest.java b/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/IntentSenderTest.java
similarity index 76%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/CrossProfileContentTest.java
rename to hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/IntentSenderTest.java
index 85e7d1b..47de0da 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/CrossProfileContentTest.java
+++ b/hostsidetests/devicepolicy/app/IntentSender/src/com/android/cts/intent/sender/IntentSenderTest.java
@@ -13,30 +13,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.cts.managedprofile.crossprofilecontent;
-import static com.android.cts.managedprofile.BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT;
+package com.android.cts.intent.sender;
-import android.app.admin.DevicePolicyManager;
import android.content.ClipData;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.net.Uri;
import android.support.v4.content.FileProvider;
-import android.test.ActivityInstrumentationTestCase2;
+import android.test.InstrumentationTestCase;
import android.util.Log;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
+import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.io.IOException;
-public class CrossProfileContentTest extends
- ActivityInstrumentationTestCase2<IntentSenderActivity> {
+public class IntentSenderTest extends InstrumentationTestCase {
private static final String MESSAGE = "Sample Message";
@@ -49,35 +45,20 @@
private static final String TAG = "CrossProfileContentTest";
- private static final String BASIC_CONTENT_PROVIDER_AUTHORITY =
- "com.android.cts.managedprofile.basiccontentProvider";
-
-
- private DevicePolicyManager mDpm;
-
private Context mContext;
-
- public CrossProfileContentTest() {
- super(IntentSenderActivity.class);
- }
+ private IntentSenderActivity mActivity;
@Override
protected void setUp() throws Exception {
super.setUp();
mContext = getInstrumentation().getTargetContext();
- mDpm = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(ACTION_READ_FROM_URI);
- intentFilter.addAction(ACTION_WRITE_TO_URI);
- intentFilter.addAction(ACTION_TAKE_PERSISTABLE_URI_PERMISSION);
- mDpm.addCrossProfileIntentFilter(ADMIN_RECEIVER_COMPONENT, intentFilter,
- DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED);
+ mActivity = launchActivity(mContext.getPackageName(), IntentSenderActivity.class, null);
}
@Override
- protected void tearDown() throws Exception {
- mDpm.clearCrossProfileIntentFilters(ADMIN_RECEIVER_COMPONENT);
+ public void tearDown() throws Exception {
super.tearDown();
+ mActivity.finish();
}
/**
@@ -85,14 +66,15 @@
* This intent will have, in the ClipData, a uri whose associated file stores a message.
* The receiver will read the message from the uri, and put it inside the result intent.
*/
- public void testReceiverCanRead() {
+ public void testReceiverCanRead() throws Exception {
Uri uri = getUriWithTextInFile("reading_test", MESSAGE);
assertTrue(uri != null);
Intent intent = new Intent(ACTION_READ_FROM_URI);
intent.setClipData(ClipData.newRawUri("", uri));
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- Intent result = getActivity().getResultForIntent(intent);
- assertTrue(result != null);
+
+ final Intent result = mActivity.getResult(intent);
+ assertNotNull(result);
assertEquals(MESSAGE, result.getStringExtra("extra_response"));
}
@@ -102,7 +84,7 @@
* The receiver will read the message from the extra, and write it to the uri in
* the ClipData.
*/
- public void testReceiverCanWrite() {
+ public void testReceiverCanWrite() throws Exception {
// It's the receiver of the intent that should write to the uri, not us. So, for now, we
// write an empty string.
Uri uri = getUriWithTextInFile("writing_test", "");
@@ -112,19 +94,21 @@
intent.putExtra("extra_message", MESSAGE);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION
| Intent.FLAG_GRANT_READ_URI_PERMISSION);
- getActivity().getResultForIntent(intent);
+
+ mActivity.getResult(intent);
assertEquals(MESSAGE, getFirstLineFromUri(uri));
}
- public void testPersistablePermission() {
+ public void testPersistablePermission() throws Exception {
Uri uri = getUriWithTextInFile("persistable_test", MESSAGE);
grantPersistableReadPermission(uri);
// Now checking if the receiver can read this uri, without re-granting the read permission.
Intent intent = new Intent(ACTION_READ_FROM_URI);
intent.setClipData(ClipData.newRawUri("", uri));
- Intent result = getActivity().getResultForIntent(intent);
- assertTrue(result != null);
+
+ final Intent result = mActivity.getResult(intent);
+ assertNotNull(result);
assertEquals(MESSAGE, result.getStringExtra("extra_response"));
}
@@ -138,7 +122,7 @@
* uriNotGranted), to enforce that even if an app has permission to one uri of a
* ContentProvider, it still cannot access a uri it does not have access to.
*/
- public void testAppPermissionsDontWorkAcrossProfiles() {
+ public void testAppPermissionsDontWorkAcrossProfiles() throws Exception {
// The FileProvider does not allow to use app permissions. So we need to use another
// ContentProvider.
Uri uriGranted = getBasicContentProviderUri("uri_granted");
@@ -152,19 +136,41 @@
Intent notGrant = new Intent(ACTION_READ_FROM_URI);
notGrant.setClipData(ClipData.newRawUri("", uriNotGranted));
- Intent result = getActivity().getResultForIntent(notGrant);
- assertTrue(result != null);
+ final Intent result = mActivity.getResult(notGrant);
+ assertNotNull(result);
// The receiver did not have permission to read the uri. So it should have caught a security
// exception.
assertTrue(result.getBooleanExtra("extra_caught_security_exception", false));
}
- private void grantPersistableReadPermission(Uri uri) {
+ /**
+ * Ensure that sender is only able to send data that it has access to.
+ */
+ public void testSecurity() throws Exception {
+ // Pick a URI that neither of us have access to; it doens't matter if
+ // its missing, since we expect a SE before a FNFE.
+ final Uri uri = Uri.parse("content://media/external/images/media/10240");
+ final Intent intent = new Intent(ACTION_READ_FROM_URI);
+ intent.setClipData(ClipData.newRawUri("", uri));
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+ // We're expecting to run into a security exception
+ final Intent result = mActivity.getResult(intent);
+ if (result == null) {
+ // This is fine; probably of a SecurityException when off in the
+ // system somewhere.
+ } else {
+ // But if we somehow came through, make sure they threw.
+ assertTrue(result.getBooleanExtra("extra_caught_security_exception", false));
+ }
+ }
+
+ private void grantPersistableReadPermission(Uri uri) throws Exception {
Intent grantPersistable = new Intent(ACTION_TAKE_PERSISTABLE_URI_PERMISSION);
grantPersistable.setClipData(ClipData.newRawUri("", uri));
grantPersistable.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
- getActivity().getResultForIntent(grantPersistable);
+ mActivity.getResult(grantPersistable);
}
private Uri getBasicContentProviderUri(String path) {
@@ -172,7 +178,7 @@
// granting these uris to other apps, or these apps from trying to access these uris.
return new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
- .authority(BASIC_CONTENT_PROVIDER_AUTHORITY)
+ .authority("com.android.cts.intent.sender.provider")
.path(path)
.build();
}
@@ -191,7 +197,7 @@
Log.e(TAG, "Could not create file " + filename + " with text " + text);
return null;
}
- return FileProvider.getUriForFile(mContext, "com.android.cts.managedprofile.fileprovider",
+ return FileProvider.getUriForFile(mContext, "com.android.cts.intent.sender.fileprovider",
file);
}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml b/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
index 56b3671..008ed38 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
@@ -19,9 +19,6 @@
<uses-sdk android:minSdkVersion="20"/>
- <permission android:name="com.android.cts.managedprofile.permission.SAMPLE"
- android:label="Sample Permission"/>
-
<application>
<uses-library android:name="android.test.runner" />
<receiver
@@ -65,11 +62,6 @@
<action android:name="com.android.cts.managedprofile.ACTION_TEST_ALL_ACTIVITY" />
</intent-filter>
</activity>
- <activity android:name=".crossprofilecontent.IntentSenderActivity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- </intent-filter>
- </activity>
<activity android:name=".UserRestrictionActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -77,22 +69,6 @@
</intent-filter>
</activity>
<activity android:name=".TestActivity" />
- <provider
- android:name="android.support.v4.content.FileProvider"
- android:authorities="com.android.cts.managedprofile.fileprovider"
- android:grantUriPermissions="true"
- android:exported="false">
- <meta-data
- android:name="android.support.FILE_PROVIDER_PATHS"
- android:resource="@xml/filepaths" />
- </provider>
- <provider
- android:name="com.android.cts.managedprofile.crossprofilecontent.BasicContentProvider"
- android:authorities="com.android.cts.managedprofile.basiccontentProvider"
- android:grantUriPermissions="true"
- android:exported="true"
- android:permission="com.android.cts.managedprofile.permission.SAMPLE"
- />
</application>
<instrumentation android:name="android.test.InstrumentationTestRunner"
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/AllUsersActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/AllUsersActivity.java
similarity index 100%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/AllUsersActivity.java
rename to hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/AllUsersActivity.java
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/ComponentDisablingActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ComponentDisablingActivity.java
similarity index 100%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/ComponentDisablingActivity.java
rename to hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ComponentDisablingActivity.java
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/CrossProfileUtils.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/CrossProfileUtils.java
new file mode 100644
index 0000000..9615991
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/CrossProfileUtils.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2014 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.cts.managedprofile;
+
+import static com.android.cts.managedprofile.BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.IntentFilter;
+import android.test.AndroidTestCase;
+
+public class CrossProfileUtils extends AndroidTestCase {
+ private static final String ACTION_READ_FROM_URI = "com.android.cts.action.READ_FROM_URI";
+
+ private static final String ACTION_WRITE_TO_URI = "com.android.cts.action.WRITE_TO_URI";
+
+ private static final String ACTION_TAKE_PERSISTABLE_URI_PERMISSION =
+ "com.android.cts.action.TAKE_PERSISTABLE_URI_PERMISSION";
+
+ public void addParentCanAccessManagedFilters() {
+ removeAllFilters();
+
+ final DevicePolicyManager dpm = (DevicePolicyManager) getContext().getSystemService(
+ Context.DEVICE_POLICY_SERVICE);
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(ACTION_READ_FROM_URI);
+ intentFilter.addAction(ACTION_WRITE_TO_URI);
+ intentFilter.addAction(ACTION_TAKE_PERSISTABLE_URI_PERMISSION);
+ dpm.addCrossProfileIntentFilter(ADMIN_RECEIVER_COMPONENT, intentFilter,
+ DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED);
+ }
+
+ public void addManagedCanAccessParentFilters() {
+ removeAllFilters();
+
+ final DevicePolicyManager dpm = (DevicePolicyManager) getContext().getSystemService(
+ Context.DEVICE_POLICY_SERVICE);
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(ACTION_READ_FROM_URI);
+ intentFilter.addAction(ACTION_WRITE_TO_URI);
+ intentFilter.addAction(ACTION_TAKE_PERSISTABLE_URI_PERMISSION);
+ dpm.addCrossProfileIntentFilter(ADMIN_RECEIVER_COMPONENT, intentFilter,
+ DevicePolicyManager.FLAG_MANAGED_CAN_ACCESS_PARENT);
+ }
+
+ public void removeAllFilters() {
+ final DevicePolicyManager dpm = (DevicePolicyManager) getContext().getSystemService(
+ Context.DEVICE_POLICY_SERVICE);
+ dpm.clearCrossProfileIntentFilters(ADMIN_RECEIVER_COMPONENT);
+ }
+}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/ManagedProfileActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ManagedProfileActivity.java
similarity index 100%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/ManagedProfileActivity.java
rename to hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ManagedProfileActivity.java
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/ManagedProfileTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ManagedProfileTest.java
similarity index 100%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/ManagedProfileTest.java
rename to hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ManagedProfileTest.java
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserActivity.java
similarity index 99%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserActivity.java
rename to hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserActivity.java
index 35f70be..b0e84ae 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserActivity.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserActivity.java
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package com.android.cts.managedprofile;
import android.app.Activity;
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserFilterSetterActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserFilterSetterActivity.java
similarity index 100%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserFilterSetterActivity.java
rename to hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserFilterSetterActivity.java
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserTest.java
similarity index 99%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserTest.java
rename to hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserTest.java
index 7098d9e..40ff6c5 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/PrimaryUserTest.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserTest.java
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package com.android.cts.managedprofile;
import android.app.admin.DevicePolicyManager;
@@ -55,7 +56,7 @@
public void testAddCrossProfileIntentFilter_all() {
assertEquals(2, mPackageManager.queryIntentActivities(
new Intent(AllUsersActivity.ACTION), /* flags = */ 0).size());
-
+
// If we used startActivity(), the user would have a disambiguation dialog presented which
// requires human intervention, so we won't be testing like that
}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/TestActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/TestActivity.java
similarity index 100%
rename from hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofileintentfilters/TestActivity.java
rename to hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/TestActivity.java
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/IntentSenderActivity.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/IntentSenderActivity.java
deleted file mode 100644
index e4c8ddf..0000000
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/crossprofilecontent/IntentSenderActivity.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2014 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.cts.managedprofile.crossprofilecontent;
-
-import static com.android.cts.managedprofile.BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.util.Log;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-public class IntentSenderActivity extends Activity {
-
- private CountDownLatch mLatch;
-
- private static final int WAIT_FOR_RESPONSE_TIMEOUT_SECONDS = 5;
-
- private Intent mResult;
-
- Intent getResultForIntent(Intent intent) {
- mLatch = new CountDownLatch(1);
- mResult = null;
- startActivityForResult(intent, 0);
- try {
- mLatch.await(WAIT_FOR_RESPONSE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
- } catch (InterruptedException e) {
- }
- return mResult;
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent result) {
- if (resultCode == Activity.RESULT_OK) {
- mResult = result;
- }
- mLatch.countDown();
- }
-}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
index 15c7725..544ddff 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -17,6 +17,7 @@
package com.android.cts.devicepolicy;
import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.cts.util.AbiUtils;
import com.android.ddmlib.Log.LogLevel;
import com.android.ddmlib.testrunner.InstrumentationResultParser;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
@@ -26,11 +27,13 @@
import com.android.ddmlib.testrunner.TestRunResult;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.CollectingTestListener;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IBuildReceiver;
+import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashSet;
@@ -74,6 +77,21 @@
installResult);
}
+ protected void installAppAsUser(String appFileName, int userId) throws FileNotFoundException,
+ DeviceNotAvailableException {
+ final ITestDevice device = getDevice();
+
+ final File apk = mCtsBuild.getTestApp(appFileName);
+ final String remotePath = "/data/local/tmp/" + apk.getName();
+ if (!device.pushFile(apk, remotePath)) {
+ throw new IllegalStateException("Failed to push " + apk);
+ }
+
+ final String result = device.executeShellCommand(
+ "pm install --user " + userId + " " + remotePath);
+ assertTrue(result, result.contains("\nSuccess"));
+ }
+
/** Initializes the user with the given id. This is required so that apps can run on it. */
protected void startUser(int userId) throws DeviceNotAvailableException {
String command = "am start-user " + userId;
@@ -135,7 +153,17 @@
protected boolean runDeviceTestsAsUser(
String pkgName, @Nullable String testClassName, int userId)
throws DeviceNotAvailableException {
- return runDeviceTests(pkgName, testClassName, null /*testMethodName*/, userId);
+ return runDeviceTestsAsUser(pkgName, testClassName, null, userId);
+ }
+
+ /** Returns true if the specified tests passed. Tests are run as given user. */
+ protected boolean runDeviceTestsAsUser(
+ String pkgName, @Nullable String testClassName, String testMethodName, int userId)
+ throws DeviceNotAvailableException {
+ if (testClassName.startsWith(".")) {
+ testClassName = pkgName + testClassName;
+ }
+ return runDeviceTests(pkgName, testClassName, testMethodName, userId);
}
private boolean runDeviceTests(String pkgName, @Nullable String testClassName,
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
index 88a3b70..6ece85c 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
@@ -28,6 +28,9 @@
private static final String MANAGED_PROFILE_PKG = "com.android.cts.managedprofile";
private static final String MANAGED_PROFILE_APK = "CtsManagedProfileApp.apk";
+ private static final String INTENT_SENDER_PKG = "com.android.cts.intent.sender";
+ private static final String INTENT_SENDER_APK = "CtsIntentSenderApp.apk";
+
private static final String INTENT_RECEIVER_PKG = "com.android.cts.intent.receiver";
private static final String INTENT_RECEIVER_APK = "CtsIntentReceiverApp.apk";
@@ -110,16 +113,30 @@
if (!mHasFeature) {
return;
}
+
try {
- installApp(INTENT_RECEIVER_APK);
+ getDevice().uninstallPackage(INTENT_SENDER_PKG);
+ getDevice().uninstallPackage(INTENT_RECEIVER_PKG);
+ installAppAsUser(INTENT_SENDER_APK, 0);
+ installAppAsUser(INTENT_RECEIVER_APK, mUserId);
- String command = "pm uninstall --user " + mUserId + " " + INTENT_RECEIVER_PKG;
- CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": "
- + getDevice().executeShellCommand(command));
+ // Test from parent to managed
+ assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".CrossProfileUtils",
+ "addManagedCanAccessParentFilters", mUserId));
+ assertTrue(runDeviceTestsAsUser(INTENT_SENDER_PKG, ".IntentSenderTest", 0));
- assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG,
- MANAGED_PROFILE_PKG + ".crossprofilecontent.CrossProfileContentTest", mUserId));
+ getDevice().uninstallPackage(INTENT_SENDER_PKG);
+ getDevice().uninstallPackage(INTENT_RECEIVER_PKG);
+ installAppAsUser(INTENT_SENDER_APK, mUserId);
+ installAppAsUser(INTENT_RECEIVER_APK, 0);
+
+ // Test from managed to parent
+ assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".CrossProfileUtils",
+ "addParentCanAccessManagedFilters", mUserId));
+ assertTrue(runDeviceTestsAsUser(INTENT_SENDER_PKG, ".IntentSenderTest", mUserId));
+
} finally {
+ getDevice().uninstallPackage(INTENT_SENDER_PKG);
getDevice().uninstallPackage(INTENT_RECEIVER_PKG);
}
}
diff --git a/libs/commonutil/Android.mk b/libs/commonutil/Android.mk
new file mode 100644
index 0000000..9c131b0
--- /dev/null
+++ b/libs/commonutil/Android.mk
@@ -0,0 +1,27 @@
+#
+# Copyright (C) 2014 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 $(call all-subdir-makefiles)
+
+# ======================================================
+# Build a static host library for the AbiUtils
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := src/com/android/cts/util/AbiUtils.java
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE := ctsabiutilslib
+include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/libs/commonutil/src/com/android/cts/util/AbiUtils.java b/libs/commonutil/src/com/android/cts/util/AbiUtils.java
index 4a34c6f..6f47d52 100644
--- a/libs/commonutil/src/com/android/cts/util/AbiUtils.java
+++ b/libs/commonutil/src/com/android/cts/util/AbiUtils.java
@@ -163,4 +163,22 @@
public static String getBitness(String name) {
return ABIS_32BIT.contains(name) ? "32" : "64";
}
+
+ /**
+ * @param abilistString A comma separated string containing abis.
+ * @return A List of Strings containing valid ABIs.
+ */
+ public static Set<String> parseAbiList(String unsupportedAbiDescription) {
+ Set<String> abiSet = new HashSet<>();
+ String[] descSegments = unsupportedAbiDescription.split(":");
+ if (descSegments.length == 2) {
+ for (String abi : descSegments[1].split(",")) {
+ String trimmedAbi = abi.trim();
+ if (isAbiSupportedByCts(trimmedAbi)) {
+ abiSet.add(trimmedAbi);
+ }
+ }
+ }
+ return abiSet;
+ }
}
diff --git a/suite/cts/deviceTests/browserbench/src/com/android/cts/browser/BrowserBenchTest.java b/suite/cts/deviceTests/browserbench/src/com/android/cts/browser/BrowserBenchTest.java
index 997f730..d74ddb2 100644
--- a/suite/cts/deviceTests/browserbench/src/com/android/cts/browser/BrowserBenchTest.java
+++ b/suite/cts/deviceTests/browserbench/src/com/android/cts/browser/BrowserBenchTest.java
@@ -17,6 +17,7 @@
package com.android.cts.browser;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.cts.util.WatchDog;
import android.net.Uri;
import android.provider.Browser;
@@ -70,10 +71,12 @@
private volatile int mRunIndex;
/** stores results for each runs. last entry will be the final score. */
private LinkedHashMap<String, double[]> mResultsMap;
+ private PackageManager mPackageManager;
@Override
protected void setUp() throws Exception {
super.setUp();
+ mPackageManager = getInstrumentation().getContext().getPackageManager();
mWebServer = new CtsTestServer(getContext()) {
@Override
protected HttpResponse onPost(HttpRequest request) throws Exception {
@@ -124,6 +127,10 @@
@TimeoutReq(minutes = 60)
public void testOctane() throws InterruptedException {
+ if (!isBrowserSupported()) {
+ Log.i(TAG, "Skipping test for device with no supported browser");
+ return;
+ }
String url = mWebServer.getAssetUrl(OCTANE_START_FILE) + "?auto=1";
final int kRepeat = 5;
doTest(url, ResultType.LOWER_BETTER, ResultUnit.MS,
@@ -167,4 +174,13 @@
numberToProcess++;
}
}
+
+ /**
+ * @return true iff this device is has a working browser.
+ */
+ private boolean isBrowserSupported() {
+ return !(mPackageManager.hasSystemFeature("android.hardware.type.television")
+ || mPackageManager.hasSystemFeature("android.software.leanback")
+ || mPackageManager.hasSystemFeature("android.hardware.type.watch"));
+ }
}
diff --git a/tests/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index 8adf345..9ae041c 100644
--- a/tests/expectations/knownfailures.txt
+++ b/tests/expectations/knownfailures.txt
@@ -1,5 +1,13 @@
[
{
+ description: "tests a fragile by nature as they rely on hardcoded behavior",
+ names: [
+ "android.accessibilityservice.cts.AccessibilityTextTraversalTest#testActionNextAndPreviousAtGranularityPageOverText",
+ "android.accessibilityservice.cts.AccessibilityTextTraversalTest#testActionNextAndPreviousAtGranularityPageOverTextExtend"
+ ],
+ bug: 17595050
+},
+{
description: "signature test stil needs more work",
names: [
"android.signature.cts.SignatureTest#testSignature"
@@ -37,6 +45,26 @@
bug: 16720689
},
{
+ description: "test can only run properly on a user build device when the bug is resolved",
+ names: [
+ "android.appwidget.cts.AppWidgetTest#testAppWidgetProviderCallbacks",
+ "android.appwidget.cts.AppWidgetTest#testBindAppWidget",
+ "android.appwidget.cts.AppWidgetTest#testCollectionWidgets",
+ "android.appwidget.cts.AppWidgetTest#testDeleteHost",
+ "android.appwidget.cts.AppWidgetTest#testDeleteHosts",
+ "android.appwidget.cts.AppWidgetTest#testGetAppWidgetIds",
+ "android.appwidget.cts.AppWidgetTest#testGetAppWidgetInfo",
+ "android.appwidget.cts.AppWidgetTest#testGetAppWidgetOptions",
+ "android.appwidget.cts.AppWidgetTest#testPartiallyUpdateAppWidgetViaWidgetId",
+ "android.appwidget.cts.AppWidgetTest#testPartiallyUpdateAppWidgetViaWidgetIds",
+ "android.appwidget.cts.AppWidgetTest#testTwoAppWidgetProviderCallbacks",
+ "android.appwidget.cts.AppWidgetTest#testUpdateAppWidgetViaComponentName",
+ "android.appwidget.cts.AppWidgetTest#testUpdateAppWidgetViaWidgetId",
+ "android.appwidget.cts.AppWidgetTest#testUpdateAppWidgetViaWidgetIds"
+ ],
+ bug: 17993121
+},
+{
description: "A few WebGL tests are known to fail in WebView",
names: [
"android.webgl.cts.WebGLTest#test_conformance_extensions_oes_texture_float_with_video_html",
@@ -74,6 +102,13 @@
bug: 17530117
},
{
+ description: "this test removes the stay-awake option, causing the screen to turn off during the execution of subsequent tests",
+ names: [
+ "android.admin.cts.DevicePolicyManagerTest#testMaximumTimeToLock"
+ ],
+ bug: 18002490
+},
+{
description: "these tests locks the screen with an emtpy password or swipe-to-unlock, blocking subsequent test to dismiss keyguard",
names: [
"android.admin.cts.DevicePolicyManagerTest#testPasswordQuality_something",
diff --git a/tests/expectations/unsupportedabis.txt b/tests/expectations/unsupportedabis.txt
index 520d750..817179b 100644
--- a/tests/expectations/unsupportedabis.txt
+++ b/tests/expectations/unsupportedabis.txt
@@ -2,6 +2,14 @@
{
description: "Tests not supporting: arm64-v8a, x86_64, mips64",
names: [
+ "android.bionic.malloc#pvalloc_overflow",
+ "android.bionic.malloc#pvalloc_std",
+ "android.bionic.malloc#valloc_overflow",
+ "android.bionic.malloc#valloc_std",
+ "android.renderscriptlegacy.cts.LeakTest",
+ "android.renderscriptlegacy.cts.RSBase",
+ "android.renderscriptlegacy.cts.RSBaseCompute",
+ "android.renderscriptlegacy.cts.VersionTest",
"android.sample.cts.SampleDeviceResultTest",
"android.sample.cts.SampleDeviceTest",
"android.sample.cts.SampleHostResultTest",
diff --git a/tests/tests/bionic/Android.mk b/tests/tests/bionic/Android.mk
index 1a048c6..e1afd50 100644
--- a/tests/tests/bionic/Android.mk
+++ b/tests/tests/bionic/Android.mk
@@ -8,6 +8,9 @@
LOCAL_MODULE := $(test_executable)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativetest
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
LOCAL_ADDITION_DEPENDENCIES := \
$(LOCAL_PATH)/Android.mk \
@@ -31,6 +34,10 @@
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := $(list_executable)
+LOCAL_MULTILIB := both
+# Use the 32 bit list executable since it will include some 32 bit only tests.
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
LOCAL_ADDITION_DEPENDENCIES := \
$(LOCAL_PATH)/Android.mk \
diff --git a/tests/tests/deqp/Android.mk b/tests/tests/deqp/Android.mk
new file mode 100644
index 0000000..d8a4dda
--- /dev/null
+++ b/tests/tests/deqp/Android.mk
@@ -0,0 +1,26 @@
+# Copyright (C) 2014 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.
+
+# Dummy target to make dEQP test list generation consistent with other tests.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# All APIs share the same package
+LOCAL_PACKAGE_NAME := com.drawelements.deqp
+
+include $(LOCAL_PATH)/deqp_gles2.mk
+include $(LOCAL_PATH)/deqp_gles3.mk
+include $(LOCAL_PATH)/deqp_gles31.mk
diff --git a/tests/tests/deqp/deqp_gles2.mk b/tests/tests/deqp/deqp_gles2.mk
new file mode 100644
index 0000000..3cd60da
--- /dev/null
+++ b/tests/tests/deqp/deqp_gles2.mk
@@ -0,0 +1,21 @@
+# Copyright (C) 2014 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.
+
+# Dummy target to make dEQP GLES2 test list generation consistent with other
+# tests.
+
+DEQP_API := gles2
+DEQP_TEST_NAME := dEQP-GLES2
+
+include $(BUILD_CTS_DEQP_PACKAGE)
diff --git a/tests/tests/deqp/deqp_gles3.mk b/tests/tests/deqp/deqp_gles3.mk
new file mode 100644
index 0000000..07dfdae
--- /dev/null
+++ b/tests/tests/deqp/deqp_gles3.mk
@@ -0,0 +1,21 @@
+# Copyright (C) 2014 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.
+
+# Dummy target to make dEQP GLES3 test list generation consistent with other
+# tests.
+
+DEQP_API := gles3
+DEQP_TEST_NAME := dEQP-GLES3
+
+include $(BUILD_CTS_DEQP_PACKAGE)
diff --git a/tests/tests/deqp/deqp_gles31.mk b/tests/tests/deqp/deqp_gles31.mk
new file mode 100644
index 0000000..7e45413
--- /dev/null
+++ b/tests/tests/deqp/deqp_gles31.mk
@@ -0,0 +1,21 @@
+# Copyright (C) 2014 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.
+
+# Dummy target to make dEQP GLES31 test list generation consistent with other
+# tests.
+
+DEQP_API := gles31
+DEQP_TEST_NAME := dEQP-GLES31
+
+include $(BUILD_CTS_DEQP_PACKAGE)
diff --git a/tests/tests/graphics/res/drawable/vector_icon_delete.xml b/tests/tests/graphics/res/drawable/vector_icon_delete.xml
index 7b8f2aa..8d9c21c 100644
--- a/tests/tests/graphics/res/drawable/vector_icon_delete.xml
+++ b/tests/tests/graphics/res/drawable/vector_icon_delete.xml
@@ -24,6 +24,6 @@
<path
android:fillColor="#FF000000"
- android:pathData="M6.0,19.0c0.0,1.104 896e-3,2.0 2.0,2.0l8.0,0.0c1.104,0.0 2.0-896e-3 2.0-2.0l0.0-12.0L6.0,7.0L6.0,19.0zM18.0,4.0l-2.5,0.0l-1.0-1.0l-5.0,0.0l-1.0,1.0L6.0,4.0C5.4469986,4.0 5.0,4.4469986 5.0,5.0l0.0,1.0l14.0,0.0l0.0-1.0C19.0,4.4469986 18.552002,4.0 18.0,4.0z" />
+ android:pathData="M6.0,19.0c0.0,1.104 0.896,2.0 2.0,2.0l8.0,0.0c1.104,0.0 2.0-0.896 2.0-2.0l0.0-12.0L6.0,7.0L6.0,19.0zM18.0,4.0l-2.5,0.0l-1.0-1.0l-5.0,0.0l-1.0,1.0L6.0,4.0C5.4469986,4.0 5.0,4.4469986 5.0,5.0l0.0,1.0l14.0,0.0l0.0-1.0C19.0,4.4469986 18.552002,4.0 18.0,4.0z" />
</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_heart.xml b/tests/tests/graphics/res/drawable/vector_icon_heart.xml
index ad991c9..ff55fe5 100644
--- a/tests/tests/graphics/res/drawable/vector_icon_heart.xml
+++ b/tests/tests/graphics/res/drawable/vector_icon_heart.xml
@@ -24,6 +24,6 @@
<path
android:fillColor="#FF000000"
- android:pathData="M16.0,5.0c-1.955.0 -3.83,1.268 -4.5,3.0c-0.67-1.732 -2.547-3.0 -4.5-3.0C4.4570007,5.0 2.5,6.931999 2.5,9.5c0.0,3.529 3.793,6.258 9.0,11.5c5.207-5.242 9.0-7.971 9.0-11.5C20.5,6.931999 18.543,5.0 16.0,5.0z" />
+ android:pathData="M16.0,5.0c-1.955,0.0 -3.83,1.268 -4.5,3.0c-0.67-1.732 -2.547-3.0 -4.5-3.0C4.4570007,5.0 2.5,6.931999 2.5,9.5c0.0,3.529 3.793,6.258 9.0,11.5c5.207-5.242 9.0-7.971 9.0-11.5C20.5,6.931999 18.543,5.0 16.0,5.0z" />
</vector>
\ No newline at end of file
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/ActivityResultMultiplexedLatch.java b/tests/tests/hardware/src/android/hardware/cts/helpers/ActivityResultMultiplexedLatch.java
index bfc59c4..093a659 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/ActivityResultMultiplexedLatch.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/ActivityResultMultiplexedLatch.java
@@ -16,9 +16,6 @@
package android.hardware.cts.helpers;
-import android.app.Activity;
-import android.util.Log;
-
import java.util.HashMap;
import java.util.concurrent.CountDownLatch;
@@ -53,13 +50,8 @@
*
* @return The result code of the Activity executed.
*/
- public int await() {
- try {
- mEntry.latch.await();
- } catch (InterruptedException e) {
- Log.e(TAG, "Error waiting for Activity result.", e);
- return Activity.RESULT_CANCELED;
- }
+ public int await() throws InterruptedException {
+ mEntry.latch.await();
return mEntry.resultCode;
}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/CollectingSensorEventListener.java b/tests/tests/hardware/src/android/hardware/cts/helpers/CollectingSensorEventListener.java
index c11b29f..ca7d133 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/CollectingSensorEventListener.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/CollectingSensorEventListener.java
@@ -64,7 +64,7 @@
* </p>
*/
@Override
- public void waitForEvents(int eventCount) {
+ public void waitForEvents(int eventCount) throws InterruptedException {
clearEvents();
super.waitForEvents(eventCount);
}
@@ -76,7 +76,7 @@
* </p>
*/
@Override
- public void waitForEvents(long duration, TimeUnit timeUnit) {
+ public void waitForEvents(long duration, TimeUnit timeUnit) throws InterruptedException {
clearEvents();
super.waitForEvents(duration, timeUnit);
}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelper.java b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelper.java
index 1f1b290..a79e5b1 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelper.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/SensorCtsHelper.java
@@ -26,7 +26,7 @@
/**
* Set of static helper methods for CTS tests.
*/
-//TODO: Refactor this class into several more well defined helper classes
+//TODO: Refactor this class into several more well defined helper classes, look at StatisticsUtils
public class SensorCtsHelper {
private static final long NANOS_PER_MILLI = 1000000;
@@ -143,13 +143,9 @@
/**
* Helper method to sleep for a given duration.
*/
- public static void sleep(long duration, TimeUnit timeUnit) {
+ public static void sleep(long duration, TimeUnit timeUnit) throws InterruptedException {
long durationNs = TimeUnit.NANOSECONDS.convert(duration, timeUnit);
- try {
- Thread.sleep(durationNs / NANOS_PER_MILLI, (int) (durationNs % NANOS_PER_MILLI));
- } catch (InterruptedException e) {
- // Ignore
- }
+ Thread.sleep(durationNs / NANOS_PER_MILLI, (int) (durationNs % NANOS_PER_MILLI));
}
/**
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEventListener.java b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEventListener.java
index 4505633..9b3a5e4 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEventListener.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEventListener.java
@@ -21,6 +21,7 @@
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener2;
+import android.os.SystemClock;
import android.util.Log;
import java.util.Arrays;
@@ -87,30 +88,20 @@
*/
@Override
public void onSensorChanged(SensorEvent event) {
+ mListener.onSensorChanged(event);
+ if (mLogEvents) {
+ Log.v(LOG_TAG, String.format(
+ "Sensor %d: sensor_timestamp=%dns, received_timestamp=%dns, values=%s",
+ mEnvironment.getSensor().getType(),
+ event.timestamp,
+ SystemClock.elapsedRealtimeNanos(),
+ Arrays.toString(event.values)));
+ }
+
CountDownLatch eventLatch = mEventLatch;
if(eventLatch != null) {
eventLatch.countDown();
}
- mListener.onSensorChanged(event);
- if (mLogEvents) {
- StringBuilder valuesSb = new StringBuilder();
- if (event.values.length == 1) {
- valuesSb.append(String.format("%.2f", event.values[0]));
- } else {
- valuesSb.append("[").append(String.format("%.2f", event.values[0]));
- for (int i = 1; i < event.values.length; i++) {
- valuesSb.append(String.format(", %.2f", event.values[i]));
- }
- valuesSb.append("]");
- }
-
- Log.v(LOG_TAG, String.format(
- "Sensor %d: sensor_timestamp=%d, received_timestamp=%d, values=%s",
- mEnvironment.getSensor().getType(),
- event.timestamp,
- System.nanoTime(),
- Arrays.toString(event.values)));
- }
}
/**
@@ -139,17 +130,14 @@
*
* @throws AssertionError if there was a timeout after {@link #FLUSH_TIMEOUT_US} µs
*/
- public void waitForFlushComplete() {
+ public void waitForFlushComplete() throws InterruptedException {
CountDownLatch latch = mFlushLatch;
- try {
- if(latch != null) {
- Assert.assertTrue(
- SensorCtsHelper.formatAssertionMessage("WaitForFlush", mEnvironment),
- latch.await(FLUSH_TIMEOUT_US, TimeUnit.MICROSECONDS));
- }
- } catch(InterruptedException e) {
- // Ignore
+ if(latch == null) {
+ return;
}
+ Assert.assertTrue(
+ SensorCtsHelper.formatAssertionMessage("WaitForFlush", mEnvironment),
+ latch.await(FLUSH_TIMEOUT_US, TimeUnit.MICROSECONDS));
}
/**
@@ -157,15 +145,14 @@
*
* @throws AssertionError if there was a timeout after {@link #FLUSH_TIMEOUT_US} µs
*/
- public void waitForEvents(int eventCount) {
+ public void waitForEvents(int eventCount) throws InterruptedException {
mEventLatch = new CountDownLatch(eventCount);
try {
int rateUs = mEnvironment.getExpectedSamplingPeriodUs();
// Timeout is 2 * event count * expected period + batch timeout + default wait
- long timeoutUs = ((2 * eventCount * rateUs)
+ long timeoutUs = (2 * eventCount * rateUs)
+ mEnvironment.getMaxReportLatencyUs()
- + EVENT_TIMEOUT_US);
-
+ + EVENT_TIMEOUT_US;
String message = SensorCtsHelper.formatAssertionMessage(
"WaitForEvents",
mEnvironment,
@@ -173,8 +160,6 @@
eventCount,
eventCount - mEventLatch.getCount());
Assert.assertTrue(message, mEventLatch.await(timeoutUs, TimeUnit.MICROSECONDS));
- } catch(InterruptedException e) {
- // Ignore
} finally {
mEventLatch = null;
}
@@ -183,7 +168,7 @@
/**
* Collect {@link TestSensorEvent} for a specific duration.
*/
- public void waitForEvents(long duration, TimeUnit timeUnit) {
+ public void waitForEvents(long duration, TimeUnit timeUnit) throws InterruptedException {
SensorCtsHelper.sleep(duration, timeUnit);
}
}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorManager.java b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorManager.java
index d72a2ce..dc40ff4 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorManager.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorManager.java
@@ -120,24 +120,22 @@
/**
* Wait for a specific number of events.
*/
- public void waitForEvents(int eventCount) {
+ public void waitForEvents(int eventCount) throws InterruptedException {
if (mTestSensorEventListener == null) {
Log.w(LOG_TAG, "No listener registered, returning.");
return;
}
-
mTestSensorEventListener.waitForEvents(eventCount);
}
/**
* Wait for a specific duration.
*/
- public void waitForEvents(long duration, TimeUnit timeUnit) {
+ public void waitForEvents(long duration, TimeUnit timeUnit) throws InterruptedException {
if (mTestSensorEventListener == null) {
Log.w(LOG_TAG, "No listener registered, returning.");
return;
}
-
mTestSensorEventListener.waitForEvents(duration, timeUnit);
}
@@ -168,7 +166,6 @@
if (mTestSensorEventListener == null) {
return;
}
-
mTestSensorEventListener.waitForFlushComplete();
}
@@ -185,7 +182,6 @@
if (mTestSensorEventListener == null) {
return;
}
-
startFlush();
waitForFlushCompleted();
}
@@ -193,12 +189,12 @@
/**
* Register a listener, wait for a specific number of events, and then unregister the listener.
*/
- public void runSensor(TestSensorEventListener listener, int eventCount) {
+ public void runSensor(TestSensorEventListener listener, int eventCount)
+ throws InterruptedException {
if (mTestSensorEventListener != null) {
Log.w(LOG_TAG, "Listener already registered, returning.");
return;
}
-
try {
registerListener(listener);
waitForEvents(eventCount);
@@ -210,12 +206,12 @@
/**
* Register a listener, wait for a specific duration, and then unregister the listener.
*/
- public void runSensor(TestSensorEventListener listener, long duration, TimeUnit timeUnit) {
+ public void runSensor(TestSensorEventListener listener, long duration, TimeUnit timeUnit)
+ throws InterruptedException {
if (mTestSensorEventListener != null) {
Log.w(LOG_TAG, "Listener already registered, returning.");
return;
}
-
try {
registerListener(listener);
waitForEvents(duration, timeUnit);
@@ -231,7 +227,7 @@
public void runSensorAndFlush(
TestSensorEventListener listener,
long duration,
- TimeUnit timeUnit) {
+ TimeUnit timeUnit) throws InterruptedException {
if (mTestSensorEventListener != null) {
Log.w(LOG_TAG, "Listener already registered, returning.");
return;
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/AlarmOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/AlarmOperation.java
index 95f1248..88e4954 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/AlarmOperation.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/AlarmOperation.java
@@ -72,7 +72,7 @@
* {@inheritDoc}
*/
@Override
- public void execute() {
+ public void execute() throws InterruptedException {
// Start alarm
IntentFilter intentFilter = new IntentFilter(ACTION);
BroadcastReceiver receiver = new BroadcastReceiver() {
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/DelaySensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/DelaySensorOperation.java
index bf43189..b4d1f23 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/DelaySensorOperation.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/DelaySensorOperation.java
@@ -50,8 +50,8 @@
* {@inheritDoc}
*/
@Override
- public void execute() {
- sleep(mDelay, mTimeUnit);
+ public void execute() throws InterruptedException {
+ SensorCtsHelper.sleep(mDelay, mTimeUnit);
mOperation.execute();
}
@@ -70,11 +70,4 @@
public DelaySensorOperation clone() {
return new DelaySensorOperation(mOperation.clone(), mDelay, mTimeUnit);
}
-
- /**
- * Helper method to sleep for a given number of ns. Exposed for unit testing.
- */
- void sleep(long delay, TimeUnit timeUnit) {
- SensorCtsHelper.sleep(delay, timeUnit);
- }
}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/ISensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/ISensorOperation.java
index 4ae56ea..62a4e9e 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/ISensorOperation.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/ISensorOperation.java
@@ -38,8 +38,12 @@
/**
* Executes the sensor operation. This may throw {@link RuntimeException}s such as
* {@link AssertionError}s.
+ *
+ * NOTE: the operation is expected to handle interruption by:
+ * - cleaning up on {@link InterruptedException}
+ * - propagating the exception down the stack
*/
- public void execute();
+ public void execute() throws InterruptedException;
/**
* Get the stats for the operation.
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/ParallelSensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/ParallelSensorOperation.java
index 4cca428..5a4466c 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/ParallelSensorOperation.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/ParallelSensorOperation.java
@@ -16,15 +16,21 @@
package android.hardware.cts.helpers.sensoroperations;
-import android.hardware.cts.helpers.SensorStats;
-import android.util.Log;
-
import junit.framework.Assert;
+import android.hardware.cts.helpers.SensorStats;
+import android.os.SystemClock;
+
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
/**
* A {@link ISensorOperation} that executes a set of children {@link ISensorOperation}s in parallel.
@@ -34,9 +40,6 @@
public class ParallelSensorOperation extends AbstractSensorOperation {
public static final String STATS_TAG = "parallel";
- private static final String TAG = "ParallelSensorOperation";
- private static final int NANOS_PER_MILLI = 1000000;
-
private final List<ISensorOperation> mOperations = new LinkedList<ISensorOperation>();
private final Long mTimeout;
private final TimeUnit mTimeUnit;
@@ -44,6 +47,7 @@
/**
* Constructor for the {@link ParallelSensorOperation} without a timeout.
*/
+ // TODO: sensor tests must always provide a timeout to prevent tests from running forever
public ParallelSensorOperation() {
mTimeout = null;
mTimeUnit = null;
@@ -77,57 +81,67 @@
* operations, the first exception will be thrown once all operations are completed.
*/
@Override
- public void execute() {
- Long timeoutTimeNs = null;
- if (mTimeout != null && mTimeUnit != null) {
- timeoutTimeNs = System.nanoTime() + TimeUnit.NANOSECONDS.convert(mTimeout, mTimeUnit);
- }
+ public void execute() throws InterruptedException {
+ int operationsCount = mOperations.size();
+ ThreadPoolExecutor executor = new ThreadPoolExecutor(
+ operationsCount,
+ operationsCount,
+ 1 /* keepAliveTime */,
+ TimeUnit.SECONDS,
+ new LinkedBlockingQueue<Runnable>());
+ executor.allowCoreThreadTimeOut(true);
+ executor.prestartAllCoreThreads();
- List<OperationThread> threadPool = new ArrayList<OperationThread>(mOperations.size());
+ ArrayList<Future<ISensorOperation>> futures = new ArrayList<Future<ISensorOperation>>();
for (final ISensorOperation operation : mOperations) {
- OperationThread thread = new OperationThread(operation);
- thread.start();
- threadPool.add(thread);
+ Future<ISensorOperation> future = executor.submit(new Callable<ISensorOperation>() {
+ @Override
+ public ISensorOperation call() throws Exception {
+ operation.execute();
+ return operation;
+ }
+ });
+ futures.add(future);
}
- List<Integer> timeoutIndices = new ArrayList<Integer>();
- List<OperationExceptionInfo> exceptions = new ArrayList<OperationExceptionInfo>();
- Throwable earliestException = null;
- Long earliestExceptionTime = null;
+ Long executionTimeNs = null;
+ if (mTimeout != null) {
+ executionTimeNs = SystemClock.elapsedRealtimeNanos()
+ + TimeUnit.NANOSECONDS.convert(mTimeout, mTimeUnit);
+ }
- for (int i = 0; i < threadPool.size(); i++) {
- OperationThread thread = threadPool.get(i);
- join(thread, timeoutTimeNs);
- if (thread.isAlive()) {
+ boolean hasAssertionErrors = false;
+ ArrayList<Integer> timeoutIndices = new ArrayList<Integer>();
+ ArrayList<Throwable> exceptions = new ArrayList<Throwable>();
+ for (int i = 0; i < operationsCount; ++i) {
+ Future<ISensorOperation> future = futures.get(i);
+ try {
+ ISensorOperation operation = getFutureResult(future, executionTimeNs);
+ addSensorStats(STATS_TAG, i, operation.getStats());
+ } catch (ExecutionException e) {
+ // extract the exception thrown by the worker thread
+ Throwable cause = e.getCause();
+ hasAssertionErrors |= (cause instanceof AssertionError);
+ exceptions.add(e.getCause());
+ addSensorStats(STATS_TAG, i, mOperations.get(i).getStats());
+ } catch (TimeoutException e) {
+ // we log, but we also need to interrupt the operation to terminate cleanly
timeoutIndices.add(i);
- thread.interrupt();
+ future.cancel(true /* mayInterruptIfRunning */);
+ } catch (InterruptedException e) {
+ // clean-up after ourselves by interrupting all the worker threads, and propagate
+ // the interruption status, so we stop the outer loop as well
+ executor.shutdownNow();
+ throw e;
}
-
- Throwable exception = thread.getException();
- Long exceptionTime = thread.getExceptionTime();
- if (exception != null && exceptionTime != null) {
- if (exception instanceof AssertionError) {
- exceptions.add(new OperationExceptionInfo(i, (AssertionError) exception));
- }
- if (earliestExceptionTime == null || exceptionTime < earliestExceptionTime) {
- earliestException = exception;
- earliestExceptionTime = exceptionTime;
- }
- }
-
- addSensorStats(STATS_TAG, i, thread.getSensorOperation().getStats());
}
- if (earliestException == null) {
- if (timeoutIndices.size() > 0) {
- Assert.fail(getTimeoutMessage(timeoutIndices));
- }
- } else if (earliestException instanceof AssertionError) {
- String msg = getExceptionMessage(exceptions, timeoutIndices);
- getStats().addValue(SensorStats.ERROR, msg);
- throw new AssertionError(msg, earliestException);
- } else if (earliestException instanceof RuntimeException) {
- throw (RuntimeException) earliestException;
+ String summary = getSummaryMessage(exceptions, timeoutIndices);
+ if (hasAssertionErrors) {
+ getStats().addValue(SensorStats.ERROR, summary);
+ }
+ if (!exceptions.isEmpty() || !timeoutIndices.isEmpty()) {
+ Assert.fail(summary);
}
}
@@ -144,114 +158,39 @@
}
/**
- * Helper method that joins a thread at a given time in the future.
+ * Helper method that waits for a {@link Future} to complete, and returns its result.
*/
- private void join(Thread thread, Long timeoutTimeNs) {
- try {
- if (timeoutTimeNs == null) {
- thread.join();
- } else {
- // Cap wait time to 1ns so that join doesn't block indefinitely.
- long waitTimeNs = Math.max(timeoutTimeNs - System.nanoTime(), 1);
- thread.join(waitTimeNs / NANOS_PER_MILLI, (int) waitTimeNs % NANOS_PER_MILLI);
- }
- } catch (InterruptedException e) {
- // Log and ignore
- Log.w(TAG, "Thread interrupted during join, operations may timeout before expected"
- + " time");
+ private ISensorOperation getFutureResult(Future<ISensorOperation> future, Long timeoutNs)
+ throws ExecutionException, TimeoutException, InterruptedException {
+ if (timeoutNs == null) {
+ return future.get();
}
+ // cap timeout to 1ns so that join doesn't block indefinitely
+ long waitTimeNs = Math.max(timeoutNs - SystemClock.elapsedRealtimeNanos(), 1);
+ return future.get(waitTimeNs, TimeUnit.NANOSECONDS);
}
/**
- * Helper method for joining the exception messages used in assertions.
+ * Helper method for joining the exception and timeout messages used in assertions.
*/
- private String getExceptionMessage(List<OperationExceptionInfo> exceptions,
- List<Integer> timeoutIndices) {
+ private String getSummaryMessage(List<Throwable> exceptions, List<Integer> timeoutIndices) {
StringBuilder sb = new StringBuilder();
- sb.append(exceptions.get(0).toString());
- for (int i = 1; i < exceptions.size(); i++) {
- sb.append(", ").append(exceptions.get(i).toString());
- }
- if (timeoutIndices.size() > 0) {
- sb.append(", ").append(getTimeoutMessage(timeoutIndices));
- }
- return sb.toString();
- }
-
- /**
- * Helper method for formatting the operation timed out message used in assertions
- */
- private String getTimeoutMessage(List<Integer> indices) {
- StringBuilder sb = new StringBuilder();
- sb.append("Operation");
- if (indices.size() != 1) {
- sb.append("s");
- }
- sb.append(" ").append(indices.get(0));
- for (int i = 1; i < indices.size(); i++) {
- sb.append(", ").append(indices.get(i));
- }
- sb.append(" timed out");
- return sb.toString();
- }
-
- /**
- * Helper class for holding operation index and exception
- */
- private class OperationExceptionInfo {
- private final int mIndex;
- private final AssertionError mException;
-
- public OperationExceptionInfo(int index, AssertionError exception) {
- mIndex = index;
- mException = exception;
+ for (Throwable exception : exceptions) {
+ sb.append(exception.toString()).append(", ");
}
- @Override
- public String toString() {
- return String.format("Operation %d failed: \"%s\"", mIndex, mException.getMessage());
- }
- }
-
- /**
- * Helper class to run the {@link ISensorOperation} in its own thread.
- */
- private class OperationThread extends Thread {
- final private ISensorOperation mOperation;
- private Throwable mException = null;
- private Long mExceptionTime = null;
-
- public OperationThread(ISensorOperation operation) {
- mOperation = operation;
- }
-
- /**
- * Run the thread catching {@link RuntimeException}s and {@link AssertionError}s and
- * the time it happened.
- */
- @Override
- public void run() {
- try {
- mOperation.execute();
- } catch (AssertionError e) {
- mExceptionTime = System.nanoTime();
- mException = e;
- } catch (RuntimeException e) {
- mExceptionTime = System.nanoTime();
- mException = e;
+ if (!timeoutIndices.isEmpty()) {
+ sb.append("Operation");
+ if (timeoutIndices.size() != 1) {
+ sb.append("s");
}
+ sb.append(" [");
+ for (Integer index : timeoutIndices) {
+ sb.append(index).append(", ");
+ }
+ sb.append("] timed out");
}
- public ISensorOperation getSensorOperation() {
- return mOperation;
- }
-
- public Throwable getException() {
- return mException;
- }
-
- public Long getExceptionTime() {
- return mExceptionTime;
- }
+ return sb.toString();
}
}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/RepeatingSensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/RepeatingSensorOperation.java
index 5e023e5..3d682fe 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/RepeatingSensorOperation.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/RepeatingSensorOperation.java
@@ -48,7 +48,7 @@
* in one iterations, it is thrown and all subsequent iterations will not run.
*/
@Override
- public void execute() {
+ public void execute() throws InterruptedException {
for(int i = 0; i < mIterations; ++i) {
ISensorOperation operation = mOperation.clone();
try {
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/SensorOperationTest.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/SensorOperationTest.java
index 15b6978..bc48725 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/SensorOperationTest.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/SensorOperationTest.java
@@ -35,7 +35,7 @@
* Test that the {@link FakeSensorOperation} functions correctly. Other tests in this class
* rely on this operation.
*/
- public void testFakeSensorOperation() {
+ public void testFakeSensorOperation() throws InterruptedException {
final int opDurationMs = 100;
ISensorOperation op = new FakeSensorOperation(opDurationMs, TimeUnit.MILLISECONDS);
@@ -60,7 +60,7 @@
/**
* Test that the {@link DelaySensorOperation} functions correctly.
*/
- public void testDelaySensorOperation() {
+ public void testDelaySensorOperation() throws InterruptedException {
final int opDurationMs = 500;
final int subOpDurationMs = 100;
@@ -77,7 +77,7 @@
/**
* Test that the {@link ParallelSensorOperation} functions correctly.
*/
- public void testParallelSensorOperation() {
+ public void testParallelSensorOperation() throws InterruptedException {
final int subOpCount = 100;
final int subOpDurationMs = 500;
@@ -118,7 +118,7 @@
* Test that the {@link ParallelSensorOperation} functions correctly if there is a failure in
* a child operation.
*/
- public void testParallelSensorOperation_fail() {
+ public void testParallelSensorOperation_fail() throws InterruptedException {
final int subOpCount = 100;
ParallelSensorOperation op = new ParallelSensorOperation();
@@ -158,7 +158,7 @@
* Test that the {@link ParallelSensorOperation} functions correctly if a child exceeds the
* timeout.
*/
- public void testParallelSensorOperation_timeout() {
+ public void testParallelSensorOperation_timeout() throws InterruptedException {
final int subOpCount = 100;
ParallelSensorOperation op = new ParallelSensorOperation(1, TimeUnit.SECONDS);
@@ -192,7 +192,7 @@
/**
* Test that the {@link RepeatingSensorOperation} functions correctly.
*/
- public void testRepeatingSensorOperation() {
+ public void testRepeatingSensorOperation() throws InterruptedException {
final int iterations = 10;
final int subOpDurationMs = 100;
@@ -219,7 +219,7 @@
* Test that the {@link RepeatingSensorOperation} functions correctly if there is a failure in
* a child operation.
*/
- public void testRepeatingSensorOperation_fail() {
+ public void testRepeatingSensorOperation_fail() throws InterruptedException {
final int iterations = 100;
final int failCount = 75;
@@ -277,7 +277,7 @@
/**
* Test that the {@link SequentialSensorOperation} functions correctly.
*/
- public void testSequentialSensorOperation() {
+ public void testSequentialSensorOperation() throws InterruptedException {
final int subOpCount = 10;
final int subOpDurationMs = 100;
@@ -308,7 +308,7 @@
* Test that the {@link SequentialSensorOperation} functions correctly if there is a failure in
* a child operation.
*/
- public void testSequentialSensorOperation_fail() {
+ public void testSequentialSensorOperation_fail() throws InterruptedException {
final int subOpCount = 100;
final int failCount = 75;
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/SequentialSensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/SequentialSensorOperation.java
index 050a8f6..2ed0ca6 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/SequentialSensorOperation.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/SequentialSensorOperation.java
@@ -48,7 +48,7 @@
* in one operation, it is thrown and all subsequent operations will not run.
*/
@Override
- public void execute() {
+ public void execute() throws InterruptedException {
for (int i = 0; i < mOperations.size(); i++) {
ISensorOperation operation = mOperations.get(i);
try {
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/TestSensorFlushOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/TestSensorFlushOperation.java
index 1fb6bef..d5aa4b9 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/TestSensorFlushOperation.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/TestSensorFlushOperation.java
@@ -53,7 +53,7 @@
* {@inheritDoc}
*/
@Override
- protected void doExecute(TestSensorEventListener listener) {
+ protected void doExecute(TestSensorEventListener listener) throws InterruptedException {
mSensorManager.runSensorAndFlush(listener, mDuration, mTimeUnit);
}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/TestSensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/TestSensorOperation.java
index 6c3851e..695e1a7 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/TestSensorOperation.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/TestSensorOperation.java
@@ -76,7 +76,7 @@
* {@inheritDoc}
*/
@Override
- protected void doExecute(TestSensorEventListener listener) {
+ protected void doExecute(TestSensorEventListener listener) throws InterruptedException {
if (mEventCount != null) {
mSensorManager.runSensor(listener, mEventCount);
} else {
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/VerifiableSensorOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/VerifiableSensorOperation.java
index c635a75..57018eb 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/VerifiableSensorOperation.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/VerifiableSensorOperation.java
@@ -94,7 +94,7 @@
* Collect the specified number of events from the sensor and run all enabled verifications.
*/
@Override
- public void execute() {
+ public void execute() throws InterruptedException {
getStats().addValue("sensor_name", mEnvironment.getSensor().getName());
ValidatingSensorEventListener listener = new ValidatingSensorEventListener(mVerifications);
@@ -131,7 +131,7 @@
/**
* Execute operations in a {@link TestSensorManager}.
*/
- protected abstract void doExecute(TestSensorEventListener listener);
+ protected abstract void doExecute(TestSensorEventListener listener) throws InterruptedException;
/**
* Clone the subclass operation.
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/WakeLockOperation.java b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/WakeLockOperation.java
index 73da9c9..b500ea7 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/WakeLockOperation.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/sensoroperations/WakeLockOperation.java
@@ -59,7 +59,7 @@
* {@inheritDoc}
*/
@Override
- public void execute() {
+ public void execute() throws InterruptedException {
PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
WakeLock wakeLock = pm.newWakeLock(mWakelockFlags, TAG);
diff --git a/tests/tests/media/src/android/media/cts/Vp8CodecTestBase.java b/tests/tests/media/src/android/media/cts/Vp8CodecTestBase.java
index 5e38842..586b9ef 100644
--- a/tests/tests/media/src/android/media/cts/Vp8CodecTestBase.java
+++ b/tests/tests/media/src/android/media/cts/Vp8CodecTestBase.java
@@ -335,11 +335,11 @@
}
/**
- * Converts (interleaves) YUV420 planar to NV12 (if hw) or NV21 (if sw).
+ * Converts (interleaves) YUV420 planar to NV12.
* Assumes packed, macroblock-aligned frame with no cropping
- * (visible/coded row length == stride). Swap U/V if |sw|.
+ * (visible/coded row length == stride).
*/
- private static byte[] YUV420ToNV(int width, int height, byte[] yuv, boolean sw) {
+ private static byte[] YUV420ToNV(int width, int height, byte[] yuv) {
byte[] nv = new byte[yuv.length];
// Y plane we just copy.
System.arraycopy(yuv, 0, nv, 0, width * height);
@@ -348,17 +348,9 @@
int u_offset = width * height;
int v_offset = u_offset + u_offset / 4;
int nv_offset = width * height;
- if (sw) {
- for (int i = 0; i < width * height / 4; i++) {
- nv[nv_offset++] = yuv[v_offset++];
- nv[nv_offset++] = yuv[u_offset++];
- }
- }
- else {
- for (int i = 0; i < width * height / 4; i++) {
- nv[nv_offset++] = yuv[u_offset++];
- nv[nv_offset++] = yuv[v_offset++];
- }
+ for (int i = 0; i < width * height / 4; i++) {
+ nv[nv_offset++] = yuv[u_offset++];
+ nv[nv_offset++] = yuv[v_offset++];
}
return nv;
}
@@ -788,7 +780,7 @@
// Convert YUV420 to NV12 if necessary
if (mProperties.colorFormat != CodecCapabilities.COLOR_FormatYUV420Planar) {
return YUV420ToNV(mStreamParams.frameWidth, mStreamParams.frameHeight,
- mSrcFrame, mProperties.isGoogleSwCodec());
+ mSrcFrame);
} else {
return mSrcFrame;
}
@@ -1390,7 +1382,7 @@
// Convert YUV420 to NV12 if necessary
if (properties.colorFormat != CodecCapabilities.COLOR_FormatYUV420Planar) {
srcFrame = YUV420ToNV(streamParams.frameWidth, streamParams.frameHeight,
- srcFrame, properties.isGoogleSwCodec());
+ srcFrame);
}
}
@@ -1652,8 +1644,7 @@
// Convert YUV420 to NV12 if necessary
if (codecProperties[i].colorFormat !=
CodecCapabilities.COLOR_FormatYUV420Planar) {
- srcFrame[i] = YUV420ToNV(params.frameWidth, params.frameHeight, srcFrame[i],
- codecProperties[i].isGoogleSwCodec());
+ srcFrame[i] = YUV420ToNV(params.frameWidth, params.frameHeight, srcFrame[i]);
}
}
diff --git a/tests/tests/nativemedia/sl/Android.mk b/tests/tests/nativemedia/sl/Android.mk
index 5b34b3d..48b816c 100644
--- a/tests/tests/nativemedia/sl/Android.mk
+++ b/tests/tests/nativemedia/sl/Android.mk
@@ -10,6 +10,9 @@
LOCAL_MODULE := $(test_executable)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativetest
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
LOCAL_C_INCLUDES := \
bionic \
diff --git a/tests/tests/nativemedia/xa/Android.mk b/tests/tests/nativemedia/xa/Android.mk
index 6995bc0..ace315a 100644
--- a/tests/tests/nativemedia/xa/Android.mk
+++ b/tests/tests/nativemedia/xa/Android.mk
@@ -10,6 +10,9 @@
LOCAL_MODULE:= $(test_executable)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativetest
+LOCAL_MULTILIB := both
+LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32
+LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
LOCAL_C_INCLUDES := \
bionic \
diff --git a/tests/tests/widget/res/layout/popupwindow.xml b/tests/tests/widget/res/layout/popupwindow.xml
index 2508115..f93f965 100644
--- a/tests/tests/widget/res/layout/popupwindow.xml
+++ b/tests/tests/widget/res/layout/popupwindow.xml
@@ -14,37 +14,36 @@
limitations under the License.
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
- <TextView android:id="@+id/anchor_upper"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/text_view_hint" />
+ <View android:id="@+id/anchor_upper"
+ android:layout_width="10dp"
+ android:layout_height="10dp"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"
+ android:background="#f00" />
- <LinearLayout android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1">
+ <View android:id="@+id/anchor_lower"
+ android:layout_width="10dp"
+ android:layout_height="10dp"
+ android:layout_alignParentBottom="true"
+ android:layout_centerHorizontal="true"
+ android:background="#0f0" />
- <TextView android:id="@+id/anchor_middle_left"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:text="@string/text_view_hint"
- android:layout_weight="1"/>
+ <View android:id="@+id/anchor_middle_left"
+ android:layout_width="10dp"
+ android:layout_height="10dp"
+ android:layout_alignParentLeft="true"
+ android:layout_centerVertical="true"
+ android:background="#00f" />
- <TextView android:id="@+id/anchor_middle_right"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:text="@string/text_view_hint"
- android:layout_weight="1"/>
+ <View android:id="@+id/anchor_middle_right"
+ android:layout_width="10dp"
+ android:layout_height="10dp"
+ android:layout_alignParentRight="true"
+ android:layout_centerVertical="true"
+ android:background="#ff0" />
- </LinearLayout>
-
- <TextView android:id="@+id/anchor_lower"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/text_view_hint" />
-
-</LinearLayout>
+</RelativeLayout>
diff --git a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
index 4a14d2b..e1742c8 100644
--- a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
+++ b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
@@ -25,6 +25,7 @@
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import android.os.Debug;
import android.os.SystemClock;
import android.test.ActivityInstrumentationTestCase2;
import android.test.UiThreadTest;
@@ -580,7 +581,8 @@
assertEquals(50, mPopupWindow.getHeight());
mPopupWindow.getContentView().getLocationOnScreen(viewXY);
- // the position should be changed
+
+ // The popup should appear below and to right with an offset.
assertEquals(anchorXY[0] + 20 + viewInWindowOff[0], viewXY[0]);
assertEquals(anchorXY[1] + anchorView.getHeight() + 50 + viewInWindowOff[1], viewXY[1]);
@@ -597,14 +599,15 @@
assertEquals(50, mPopupWindow.getHeight());
mPopupWindow.getContentView().getLocationOnScreen(viewXY);
- // the position should be changed
+
+ // The popup should appear below and to right with an offset.
assertEquals(anchorXY[0] + 10 + viewInWindowOff[0], viewXY[0]);
assertEquals(anchorXY[1] + anchorView.getHeight() + 50 + viewInWindowOff[1], viewXY[1]);
- final View anthoterView = mActivity.findViewById(R.id.anchor_middle_right);
+ final View anotherView = mActivity.findViewById(R.id.anchor_middle_left);
mInstrumentation.runOnMainSync(new Runnable() {
public void run() {
- mPopupWindow.update(anthoterView, 0, 0, 60, 60);
+ mPopupWindow.update(anotherView, 0, 0, 60, 60);
}
});
mInstrumentation.waitForIdleSync();
@@ -614,11 +617,12 @@
assertEquals(60, mPopupWindow.getHeight());
int[] newXY = new int[2];
- anthoterView.getLocationOnScreen(newXY);
+ anotherView.getLocationOnScreen(newXY);
mPopupWindow.getContentView().getLocationOnScreen(viewXY);
- // the position should be changed
+
+ // The popup should appear below and to the right.
assertEquals(newXY[0] + viewInWindowOff[0], viewXY[0]);
- assertEquals(newXY[1] + anthoterView.getHeight() + viewInWindowOff[1], viewXY[1]);
+ assertEquals(newXY[1] + anotherView.getHeight() + viewInWindowOff[1], viewXY[1]);
dismissPopup();
}
@@ -815,8 +819,7 @@
}
private View createPopupContent() {
- TextView popupView = new TextView(mActivity);
- popupView.setText("Popup");
+ View popupView = new View(mActivity);
popupView.setLayoutParams(new ViewGroup.LayoutParams(50, 50));
popupView.setBackgroundColor(Color.WHITE);
diff --git a/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/XmlGenerator.java b/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/XmlGenerator.java
index 1680cae..833bf69 100644
--- a/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/XmlGenerator.java
+++ b/tools/cts-xml-generator/src/com/android/cts/xmlgenerator/XmlGenerator.java
@@ -205,7 +205,8 @@
String className = nameCollector.toString();
nameCollector.append('#').append(test.getName());
writer.append("<Test name=\"").append(test.getName()).append("\"");
- String abis = getSupportedAbis(mUnsupportedAbis, mArchitecture, className).toString();
+ String abis = getSupportedAbis(mUnsupportedAbis, mArchitecture,
+ className, nameCollector.toString()).toString();
writer.append(" abis=\"" + abis.substring(1, abis.length() - 1) + "\"");
if (isKnownFailure(mKnownFailures, nameCollector.toString())) {
writer.append(" expectation=\"failure\"");
@@ -232,23 +233,36 @@
// Returns the list of ABIs supported by this TestCase on this architecture.
public static Set<String> getSupportedAbis(ExpectationStore expectationStore,
- String architecture, String className) {
+ String architecture, String className, String testName) {
Set<String> supportedAbis = AbiUtils.getAbisForArch(architecture);
- Expectation e = (expectationStore == null) ? null : expectationStore.get(className);
- if (e != null && !e.getDescription().isEmpty()) {
- // Description should be written in the form "blah blah: abi1, abi2..."
- String description = e.getDescription().split(":")[1];
- String[] unsupportedAbis = description.split(",");
- for (String a : unsupportedAbis) {
- String abi = a.trim();
- if (!AbiUtils.isAbiSupportedByCts(abi)) {
- throw new RuntimeException(
- String.format("Unrecognised ABI %s in %s", abi, e.getDescription()));
- }
- supportedAbis.remove(abi);
- }
+ if (expectationStore == null) {
+ return supportedAbis;
}
+
+ removeUnsupportedAbis(expectationStore.get(className), supportedAbis);
+ removeUnsupportedAbis(expectationStore.get(testName), supportedAbis);
return supportedAbis;
}
+ public static void removeUnsupportedAbis(Expectation expectation, Set<String> supportedAbis) {
+ if (expectation == null) {
+ return;
+ }
+
+ String description = expectation.getDescription();
+ if (description.isEmpty()) {
+ return;
+ }
+
+ String[] unsupportedAbis = description.split(":")[1].split(",");
+ for (String a : unsupportedAbis) {
+ String abi = a.trim();
+ if (!AbiUtils.isAbiSupportedByCts(abi)) {
+ throw new RuntimeException(
+ String.format("Unrecognised ABI %s in %s", abi, description));
+ }
+ supportedAbis.remove(abi);
+ }
+ }
+
}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsXmlResultReporter.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsXmlResultReporter.java
index e8d6e71..8224481 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsXmlResultReporter.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsXmlResultReporter.java
@@ -223,8 +223,10 @@
@Override
public void testRunStarted(String id, int numTests) {
- mCurrentPkgResult = mResults.getOrCreatePackage(id);
mIsDeviceInfoRun = DeviceInfoCollector.IDS.contains(id);
+ if (!mIsDeviceInfoRun) {
+ mCurrentPkgResult = mResults.getOrCreatePackage(id);
+ }
}
/**
@@ -232,7 +234,9 @@
*/
@Override
public void testStarted(TestIdentifier test) {
- mCurrentPkgResult.insertTest(test);
+ if (!mIsDeviceInfoRun) {
+ mCurrentPkgResult.insertTest(test);
+ }
}
/**
@@ -240,7 +244,9 @@
*/
@Override
public void testFailed(TestIdentifier test, String trace) {
- mCurrentPkgResult.reportTestFailure(test, CtsTestStatus.FAIL, trace);
+ if (!mIsDeviceInfoRun) {
+ mCurrentPkgResult.reportTestFailure(test, CtsTestStatus.FAIL, trace);
+ }
}
/**
@@ -249,7 +255,9 @@
@Override
public void testAssumptionFailure(TestIdentifier test, String trace) {
// TODO: do something different here?
- mCurrentPkgResult.reportTestFailure(test, CtsTestStatus.FAIL, trace);
+ if (!mIsDeviceInfoRun) {
+ mCurrentPkgResult.reportTestFailure(test, CtsTestStatus.FAIL, trace);
+ }
}
/**
@@ -265,7 +273,9 @@
*/
@Override
public void testEnded(TestIdentifier test, Map<String, String> testMetrics) {
- mCurrentPkgResult.reportTestEnded(test, testMetrics);
+ if (!mIsDeviceInfoRun) {
+ mCurrentPkgResult.reportTestEnded(test, testMetrics);
+ }
}
/**
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsTest.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsTest.java
index 6d617ea..7aed84d 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsTest.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/CtsTest.java
@@ -762,15 +762,26 @@
*/
private void installPrerequisiteApks(Collection<String> prerequisiteApks)
throws DeviceNotAvailableException {
+ Log.logAndDisplay(LogLevel.INFO, LOG_TAG, "Installing prerequisites");
+ Set<String> supportedAbiSet = getAbis();
for (String apkName : prerequisiteApks) {
try {
File apkFile = mCtsBuild.getTestApp(apkName);
- String errorCode = null;
- String abi = AbiFormatter.getDefaultAbi(getDevice(), mForceAbi);
- String[] options = {AbiUtils.createAbiFlag(abi)};
- errorCode = getDevice().installPackage(apkFile, true, options);
- if (errorCode != null) {
- CLog.e("Failed to install %s. Reason: %s", apkName, errorCode);
+ // As a workaround for multi arch support, try to install the APK
+ // for all device supported ABIs. This will generate warning messages
+ // until the above FIXME is resolved.
+ int installFailCount = 0;
+ for (String abi : supportedAbiSet) {
+ String[] options = {AbiUtils.createAbiFlag(abi)};
+ String errorCode = getDevice().installPackage(apkFile, true, options);
+ if (errorCode != null) {
+ installFailCount++;
+ CLog.w("Failed to install %s. Reason: %s", apkName, errorCode);
+ }
+
+ }
+ if (installFailCount >= supportedAbiSet.size()) {
+ CLog.e("Failed to install %s. See warning messages.", apkName);
}
} catch (FileNotFoundException e) {
CLog.e("Could not find test apk %s", apkName);
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/GeeTest.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/GeeTest.java
index 9bfe151..6c2ed65 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/GeeTest.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/GeeTest.java
@@ -49,9 +49,9 @@
private CtsBuildHelper mCtsBuild;
private ITestDevice mDevice;
private IAbi mAbi;
+ private String mExeName;
private final String mPackageName;
- private final String mExeName;
public GeeTest(String packageName, String exeName) {
mPackageName = packageName;
@@ -63,6 +63,7 @@
*/
public void setAbi(IAbi abi) {
mAbi = abi;
+ mExeName += mAbi.getBitness();
}
@Override
diff --git a/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/CtsXmlResultReporterTest.java b/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/CtsXmlResultReporterTest.java
index 48f1ba5..b74e26c 100644
--- a/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/CtsXmlResultReporterTest.java
+++ b/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/CtsXmlResultReporterTest.java
@@ -173,6 +173,21 @@
assertTrue(output.contains(failureTag));
}
+ public void testDeviceSetup() {
+ Map<String, String> emptyMap = Collections.emptyMap();
+ final TestIdentifier testId = new TestIdentifier("android.tests.devicesetup", "TestDeviceSetup");
+ mResultReporter.invocationStarted(mMockBuild);
+ mResultReporter.testRunStarted(AbiUtils.createId(UnitTests.ABI.getName(), testId.getClassName()), 1);
+ mResultReporter.testStarted(testId);
+ mResultReporter.testEnded(testId, emptyMap);
+ mResultReporter.testRunEnded(3, emptyMap);
+ mResultReporter.invocationEnded(1);
+ String output = getOutput();
+ // TODO: consider doing xml based compare
+ final String deviceSetupTag = "appPackageName=\"android.tests.devicesetup\"";
+ assertFalse(output, output.contains(deviceSetupTag));
+ }
+
/**
* Gets the output produced, stripping it of extraneous whitespace characters.
*/
diff --git a/tools/utils/Android.mk b/tools/utils/Android.mk
index 36081ca..0ba5cf4 100644
--- a/tools/utils/Android.mk
+++ b/tools/utils/Android.mk
@@ -25,6 +25,6 @@
LOCAL_CLASSPATH := $(HOST_JDK_TOOLS_JAR)
LOCAL_JAVA_LIBRARIES := junit
-LOCAL_STATIC_JAVA_LIBRARIES := vogarexpectlib
+LOCAL_STATIC_JAVA_LIBRARIES := ctsabiutilslib vogarexpectlib
include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/tools/utils/CollectAllTests.java b/tools/utils/CollectAllTests.java
index 367fb93..ed74824 100644
--- a/tools/utils/CollectAllTests.java
+++ b/tools/utils/CollectAllTests.java
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+import com.android.cts.util.AbiUtils;
import org.junit.runner.RunWith;
import org.w3c.dom.Document;
@@ -20,6 +21,7 @@
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
+import vogar.Expectation;
import vogar.ExpectationStore;
import java.io.BufferedReader;
@@ -61,9 +63,9 @@
private static final String TEST_TYPE = "LOCAL_TEST_TYPE :";
public static void main(String[] args) {
- if (args.length < 4 || args.length > 6) {
+ if (args.length < 5 || args.length > 7) {
System.err.println("usage: CollectAllTests <output-file> <manifest-file> <jar-file> "
- + "<java-package> [expectation-dir [makefile-file]]");
+ + "<java-package> <architecture> [expectation-dir [makefile-file]]");
if (args.length != 0) {
System.err.println("received:");
for (String arg : args) {
@@ -86,8 +88,14 @@
return;
}
}
- String libcoreExpectationDir = (args.length > 4) ? args[4] : null;
- String androidMakeFile = (args.length > 5) ? args[5] : null;
+ String architecture = args[4];
+ if (architecture == null || architecture.equals("")) {
+ System.err.println("Invalid architecture");
+ System.exit(1);
+ return;
+ }
+ String libcoreExpectationDir = (args.length > 5) ? args[5] : null;
+ String androidMakeFile = (args.length > 6) ? args[6] : null;
final TestType testType = TestType.getTestType(androidMakeFile);
@@ -207,7 +215,7 @@
try {
klass.getConstructor(new Class<?>[] { String.class } );
- addToTests(expectations, testCases, klass);
+ addToTests(expectations, architecture, testCases, klass);
continue;
} catch (NoSuchMethodException e) {
} catch (SecurityException e) {
@@ -218,7 +226,7 @@
try {
klass.getConstructor(new Class<?>[0]);
- addToTests(expectations, testCases, klass);
+ addToTests(expectations, architecture, testCases, klass);
continue;
} catch (NoSuchMethodException e) {
} catch (SecurityException e) {
@@ -356,6 +364,7 @@
}
private static void addToTests(ExpectationStore[] expectations,
+ String architecture,
Map<String,TestClass> testCases,
Class<?> testClass) {
Set<String> testNames = new HashSet<String>();
@@ -386,11 +395,12 @@
}
testNames.add(testName);
- addToTests(expectations, testCases, testClass, testName);
+ addToTests(expectations, architecture, testCases, testClass, testName);
}
}
private static void addToTests(ExpectationStore[] expectations,
+ String architecture,
Map<String,TestClass> testCases,
Class<?> test,
String testName) {
@@ -412,6 +422,10 @@
return;
}
+ Set<String> supportedAbis = VogarUtils.extractSupportedAbis(architecture,
+ expectations,
+ testClassName,
+ testName);
TestClass testClass;
if (testCases.containsKey(testClassName)) {
testClass = testCases.get(testClassName);
@@ -420,7 +434,8 @@
testCases.put(testClassName, testClass);
}
- testClass.mCases.add(new TestMethod(testName, "", "", knownFailure, false, false));
+ testClass.mCases.add(new TestMethod(testName, "", "", supportedAbis,
+ knownFailure, false, false));
}
private static boolean isJunit3Test(Class<?> klass) {
diff --git a/tools/utils/DescriptionGenerator.java b/tools/utils/DescriptionGenerator.java
index 607d2e5..09e1118 100644
--- a/tools/utils/DescriptionGenerator.java
+++ b/tools/utils/DescriptionGenerator.java
@@ -22,6 +22,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
+import java.util.Set;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
@@ -38,6 +39,7 @@
import org.w3c.dom.NodeList;
import vogar.ExpectationStore;
+import vogar.Expectation;
import com.sun.javadoc.AnnotationDesc;
import com.sun.javadoc.AnnotationTypeDoc;
@@ -82,11 +84,13 @@
static final String ATTRIBUTE_VALUE_FRAMEWORK = "Android 1.0";
static final String ATTRIBUTE_NAME = "name";
+ static final String ATTRIBUTE_ABIS = "abis";
static final String ATTRIBUTE_HOST_CONTROLLER = "HostController";
static final String XML_OUTPUT_PATH = "./description.xml";
static final String OUTPUT_PATH_OPTION = "-o";
+ static final String ARCHITECTURE_OPTION = "-a";
/**
* Start to parse the classes passed in by javadoc, and generate
@@ -103,12 +107,21 @@
}
String outputPath = XML_OUTPUT_PATH;
+ String architecture = null;
String[][] options = root.options();
for (String[] option : options) {
- if (option.length == 2 && option[0].equals(OUTPUT_PATH_OPTION)) {
- outputPath = option[1];
+ if (option.length == 2) {
+ if (option[0].equals(OUTPUT_PATH_OPTION)) {
+ outputPath = option[1];
+ } else if (option[0].equals(ARCHITECTURE_OPTION)) {
+ architecture = option[1];
+ }
}
}
+ if (architecture == null || architecture.equals("")) {
+ Log.e("Missing architecture!", null);
+ return false;
+ }
XMLGenerator xmlGenerator = null;
try {
@@ -128,7 +141,7 @@
for (ClassDoc clazz : classes) {
if ((!clazz.isAbstract()) && (isValidJUnitTestCase(clazz))) {
- xmlGenerator.addTestClass(new TestClass(clazz, ctsExpectationStore));
+ xmlGenerator.addTestClass(new TestClass(clazz, ctsExpectationStore, architecture));
}
}
@@ -420,6 +433,8 @@
Node caseNode = elem.appendChild(mDoc.createElement(TAG_TEST));
setAttribute(caseNode, ATTRIBUTE_NAME, caze.mName);
+ String abis = caze.mAbis.toString();
+ setAttribute(caseNode, ATTRIBUTE_ABIS, abis.substring(1, abis.length() - 1));
if ((caze.mController != null) && (caze.mController.length() != 0)) {
setAttribute(caseNode, ATTRIBUTE_HOST_CONTROLLER, caze.mController);
}
@@ -509,9 +524,9 @@
*
* @param clazz The specified ClassDoc.
*/
- TestClass(ClassDoc clazz, ExpectationStore expectationStore) {
+ TestClass(ClassDoc clazz, ExpectationStore expectationStore, String architecture) {
mName = clazz.toString();
- mCases = getTestMethods(expectationStore, clazz);
+ mCases = getTestMethods(expectationStore, architecture, clazz);
}
/**
@@ -520,7 +535,8 @@
* @param clazz The specified ClassDoc.
* @return A collection of TestMethod.
*/
- Collection<TestMethod> getTestMethods(ExpectationStore expectationStore, ClassDoc clazz) {
+ Collection<TestMethod> getTestMethods(ExpectationStore expectationStore,
+ String architecture, ClassDoc clazz) {
Collection<MethodDoc> methods = getAllMethods(clazz);
ArrayList<TestMethod> cases = new ArrayList<TestMethod>();
@@ -553,8 +569,13 @@
}
if (name.startsWith("test")) {
- cases.add(new TestMethod(name, method.commentText(), controller, knownFailure,
- isBroken, isSuppressed));
+ Expectation expectation = expectationStore.get(
+ VogarUtils.buildFullTestName(clazz.toString(), name));
+ Set<String> supportedAbis =
+ VogarUtils.extractSupportedAbis(architecture, expectation);
+ cases.add(new TestMethod(
+ name, method.commentText(), controller, supportedAbis,
+ knownFailure, isBroken, isSuppressed));
}
}
@@ -610,6 +631,7 @@
String mName;
String mDescription;
String mController;
+ Set<String> mAbis;
String mKnownFailure;
boolean mIsBroken;
boolean mIsSuppressed;
@@ -621,11 +643,12 @@
* @param description The description of the test case.
* @param knownFailure The reason of known failure.
*/
- TestMethod(String name, String description, String controller, String knownFailure,
- boolean isBroken, boolean isSuppressed) {
+ TestMethod(String name, String description, String controller, Set<String> abis,
+ String knownFailure, boolean isBroken, boolean isSuppressed) {
mName = name;
mDescription = description;
mController = controller;
+ mAbis = abis;
mKnownFailure = knownFailure;
mIsBroken = isBroken;
mIsSuppressed = isSuppressed;
diff --git a/tools/utils/VogarUtils.java b/tools/utils/VogarUtils.java
index c7070a5..5e8b944 100644
--- a/tools/utils/VogarUtils.java
+++ b/tools/utils/VogarUtils.java
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+import com.android.cts.util.AbiUtils;
+
import vogar.Expectation;
import vogar.ExpectationStore;
import vogar.ModeId;
@@ -38,12 +40,26 @@
return false;
}
+ /**
+ * @return true iff the class/name is found in the vogar known failure list and it is not
+ * a known failure that is a result of an unsupported abi.
+ */
public static boolean isVogarKnownFailure(ExpectationStore expectationStore,
final String testClassName,
final String testMethodName) {
- String fullTestName = String.format("%s#%s", testClassName, testMethodName);
- return expectationStore != null
- && expectationStore.get(fullTestName) != Expectation.SUCCESS;
+ if (expectationStore == null) {
+ return false;
+ }
+ String fullTestName = buildFullTestName(testClassName, testMethodName);
+ Expectation expectation = expectationStore.get(fullTestName);
+ if (expectation == Expectation.SUCCESS) {
+ return false;
+ }
+
+ String description = expectation.getDescription();
+ boolean foundAbi = AbiUtils.parseAbiList(description).size() > 0;
+
+ return expectation != Expectation.SUCCESS && !foundAbi;
}
public static ExpectationStore provideExpectationStore(String dir) throws IOException {
@@ -67,4 +83,49 @@
}
return expectSet;
}
+
+ /** @return the test name in the form of com.android.myclass.TestClass#testMyMethod */
+ public static String buildFullTestName(String testClass, String testMethodName) {
+ return String.format("%s#%s", testClass, testMethodName);
+ }
+
+ /**
+ * This method looks in the description field of the Vogar entry for the ABI_LIST_MARKER
+ * and returns the list of abis found there.
+ *
+ * @return The Set of supported abis parsed from the {@code expectation}'s description.
+ */
+ public static Set<String> extractSupportedAbis(String architecture, Expectation expectation) {
+ Set<String> supportedAbiSet = AbiUtils.getAbisForArch(architecture);
+ if (expectation == null || expectation.getDescription().isEmpty()) {
+ // Include all abis since there was no limitation found in the description
+ return supportedAbiSet;
+ }
+
+ // Remove any abis that are not supported for the test.
+ supportedAbiSet.removeAll(AbiUtils.parseAbiList(expectation.getDescription()));
+
+ return supportedAbiSet;
+ }
+
+ /**
+ * Determine the correct set of ABIs for the given className/testName.
+ *
+ * @return the set of ABIs that can be expected to pass for the given combination of
+ * {@code architecture}, {@code className} and {@code testName}.
+ */
+ public static Set<String> extractSupportedAbis(String architecture,
+ ExpectationStore[] expectationStores,
+ String className,
+ String testName) {
+
+ String fullTestName = VogarUtils.buildFullTestName(className, testName);
+ Set<String> supportedAbiSet = AbiUtils.getAbisForArch(architecture);
+ for (ExpectationStore expectationStore : expectationStores) {
+ Expectation expectation = expectationStore.get(fullTestName);
+ supportedAbiSet.retainAll(extractSupportedAbis(architecture, expectation));
+ }
+
+ return supportedAbiSet;
+ }
}