am c2040741: Merge "Explicitly call out FEATURE_LOCATION_NETWORK as optional" into lmp-sprout-dev
* commit 'c20407415bca4969e1455d541f6a9fcc63a0569f':
Explicitly call out FEATURE_LOCATION_NETWORK as optional
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index 80e1efc..ad482b1 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -174,6 +174,7 @@
CtsDumpsysHostTestCases \
CtsHostJank \
CtsHostUi \
+ CtsJdwpSecurityHostTestCases \
CtsMonkeyTestCases \
CtsThemeHostTestCases \
CtsSecurityHostTestCases \
@@ -196,6 +197,7 @@
cts_device_jars := \
CtsDeviceJank \
+ CtsJdwpApp \
CtsPrintInstrument
cts_device_executables := \
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index f61375a..9d906f6 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -17,8 +17,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.cts.verifier"
- android:versionCode="5"
- android:versionName="5.0_r1.94">
+ android:versionCode="4"
+ android:versionName="5.0_r2">
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="21"/>
@@ -55,8 +55,6 @@
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
- <uses-permission android:name="com.android.providers.tv.permission.READ_EPG_DATA" />
- <uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" />
<!-- Needed by the Audio Quality Verifier to store the sound samples that will be mailed. -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
@@ -816,13 +814,7 @@
</intent-filter>
<meta-data android:name="test_category" android:value="@string/test_category_sensors" />
<meta-data android:name="test_applicable_features"
- android:value="android.hardware.sensor.stepcounter" />
- <meta-data android:name="test_applicable_features"
- android:value="android.hardware.sensor.stepdetector" />
- <meta-data android:name="test_applicable_features"
- android:value="android.hardware.sensor.proximity" />
- <meta-data android:name="test_applicable_features"
- android:value="android.hardware.sensor.light" />
+ android:value="android.hardware.sensor.stepcounter:android.hardware.sensor.stepdetector:android.hardware.sensor.proximity:android.hardware.sensor.light" />
</activity>
<!-- TODO: enable when a more reliable way to identify time synchronization is available -->
@@ -847,13 +839,7 @@
</intent-filter>
<meta-data android:name="test_category" android:value="@string/test_category_sensors"/>
<meta-data android:name="test_applicable_features"
- android:value="android.hardware.sensor.accelerometer" />
- <meta-data android:name="test_applicable_features"
- android:value="android.hardware.sensor.compass" />
- <meta-data android:name="test_applicable_features"
- android:value="android.hardware.sensor.gyroscope" />
- <meta-data android:name="test_applicable_features"
- android:value="android.hardware.sensor.barometer" />
+ android:value="android.hardware.sensor.accelerometer:android.hardware.sensor.compass:android.hardware.sensor.gyroscope:android.hardware.sensor.barometer" />
</activity>
<activity android:name=".sensors.SensorBatchingTestsActivity"
@@ -865,13 +851,7 @@
</intent-filter>
<meta-data android:name="test_category" android:value="@string/test_category_sensors"/>
<meta-data android:name="test_applicable_features"
- android:value="android.hardware.sensor.accelerometer" />
- <meta-data android:name="test_applicable_features"
- android:value="android.hardware.sensor.compass" />
- <meta-data android:name="test_applicable_features"
- android:value="android.hardware.sensor.gyroscope" />
- <meta-data android:name="test_applicable_features"
- android:value="android.hardware.sensor.barometer" />
+ android:value="android.hardware.sensor.accelerometer:android.hardware.sensor.compass:android.hardware.sensor.gyroscope:android.hardware.sensor.barometer" />
</activity>
<activity android:name=".sensors.SensorIntegrationTestsActivity"
@@ -883,11 +863,7 @@
</intent-filter>
<meta-data android:name="test_category" android:value="@string/test_category_sensors"/>
<meta-data android:name="test_applicable_features"
- android:value="android.hardware.sensor.accelerometer" />
- <meta-data android:name="test_applicable_features"
- android:value="android.hardware.sensor.compass" />
- <meta-data android:name="test_applicable_features"
- android:value="android.hardware.sensor.gyroscope" />
+ android:value="android.hardware.sensor.accelerometer:android.hardware.sensor.compass:android.hardware.sensor.gyroscope" />
</activity>
<activity android:name=".sensors.SensorTestActivity"
@@ -899,17 +875,7 @@
</intent-filter>
<meta-data android:name="test_category" android:value="@string/test_category_sensors"/>
<meta-data android:name="test_applicable_features"
- android:value="android.hardware.sensor.accelerometer" />
- <meta-data android:name="test_applicable_features"
- android:value="android.hardware.sensor.stepcounter" />
- <meta-data android:name="test_applicable_features"
- android:value="android.hardware.sensor.stepdetector" />
- <meta-data android:name="test_applicable_features"
- android:value="android.hardware.sensor.heartrate" />
- <meta-data android:name="test_applicable_features"
- android:value="android.hardware.sensor.compass" />
- <meta-data android:name="test_applicable_features"
- android:value="android.hardware.sensor.ambient_temperature" />
+ android:value="android.hardware.sensor.accelerometer:android.hardware.sensor.stepcounter:android.hardware.sensor.stepdetector:android.hardware.sensor.heartrate:android.hardware.sensor.compass:android.hardware.sensor.ambient_temperature" />
</activity>
<!-- End sensor tests definitions -->
@@ -935,10 +901,6 @@
<meta-data android:name="test_category" android:value="@string/test_category_location" />
<meta-data android:name="test_required_features"
android:value="android.hardware.location.network:android.hardware.location.gps" />
- <meta-data android:name="test_excluded_features"
- android:value="android.hardware.type.television" />
- <meta-data android:name="test_excluded_features"
- android:value="android.software.leanback" />
</activity>
<activity android:name=".location.LocationModeBatterySavingTestActivity"
android:label="@string/location_mode_battery_saving_test">
@@ -948,10 +910,6 @@
</intent-filter>
<meta-data android:name="test_category" android:value="@string/test_category_location" />
<meta-data android:name="test_required_features" android:value="android.hardware.location.network" />
- <meta-data android:name="test_excluded_features"
- android:value="android.hardware.type.television" />
- <meta-data android:name="test_excluded_features"
- android:value="android.software.leanback" />
</activity>
<activity android:name=".location.LocationModeDeviceOnlyTestActivity"
android:label="@string/location_mode_device_only_test">
@@ -1239,6 +1197,8 @@
<meta-data android:name="test_category" android:value="@string/test_category_other" />
<meta-data android:name="test_required_features"
android:value="android.software.app_widgets" />
+ <meta-data android:name="test_excluded_features"
+ android:value="android.software.leanback" />
</activity>
<activity android:name=".deskclock.DeskClockTestsActivity"
@@ -1465,68 +1425,6 @@
<!-- Used by the SensorTestScreenManipulator to reset the screen timeout after turn off. -->
<activity android:name=".os.TimeoutResetActivity"/>
- <activity android:name=".tv.TvInputDiscoveryTestActivity"
- android:label="@string/tv_input_discover_test">
- <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/test_category_tv" />
- <meta-data android:name="test_required_features"
- android:value="android.software.live_tv" />
- </activity>
-
- <activity android:name=".tv.ParentalControlTestActivity"
- android:label="@string/tv_parental_control_test">
- <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/test_category_tv" />
- <meta-data android:name="test_required_features"
- android:value="android.software.live_tv" />
- </activity>
-
- <activity android:name=".tv.MultipleTracksTestActivity"
- android:label="@string/tv_multiple_tracks_test">
- <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/test_category_tv" />
- <meta-data android:name="test_required_features"
- android:value="android.software.live_tv" />
- </activity>
-
- <activity android:name=".tv.MockTvInputSettingsActivity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- </intent-filter>
- </activity>
-
- <activity android:name=".tv.MockTvInputSetupActivity">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- </intent-filter>
- </activity>
-
- <service android:name=".tv.MockTvInputService"
- android:permission="android.permission.BIND_TV_INPUT">
- <intent-filter>
- <action android:name="android.media.tv.TvInputService" />
- </intent-filter>
- <meta-data android:name="android.media.tv.input"
- android:resource="@xml/mock_tv_input_service" />
- </service>
-
- <receiver android:name=".tv.TvInputReceiver">
- <intent-filter>
- <action android:name="android.media.tv.action.QUERY_CONTENT_RATING_SYSTEMS" />
- </intent-filter>
- <meta-data android:name="android.media.tv.metadata.CONTENT_RATING_SYSTEMS"
- android:resource="@xml/mock_content_rating_systems" />
- </receiver>
-
</application>
</manifest>
diff --git a/apps/CtsVerifier/res/layout/tv_item.xml b/apps/CtsVerifier/res/layout/tv_item.xml
deleted file mode 100644
index e7311f9..0000000
--- a/apps/CtsVerifier/res/layout/tv_item.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<?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.
--->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" >
-
- <ImageView
- android:id="@+id/status"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_alignParentTop="true"
- android:layout_marginTop="10dip"
- android:contentDescription="@string/pass_button_text"
- android:padding="10dip"
- android:src="@drawable/fs_indeterminate" />
-
- <TextView
- android:id="@+id/instructions"
- style="@style/InstructionsSmallFont"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:layout_alignParentTop="true"
- android:layout_toRightOf="@id/status" />
-
- <Button
- android:id="@+id/user_action_button"
- android:enabled="false"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:layout_below="@id/instructions"
- android:layout_marginLeft="20dip"
- android:layout_marginRight="20dip"
- android:layout_toRightOf="@id/status"
- android:visibility="gone" />
-
-</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/tv_overlay.xml b/apps/CtsVerifier/res/layout/tv_overlay.xml
deleted file mode 100644
index 8cd5dd8..0000000
--- a/apps/CtsVerifier/res/layout/tv_overlay.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?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.
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <TextView
- android:id="@+id/overlay_view_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="20sp"
- android:text="@string/overlay_view_text">
- </TextView>
-
-</LinearLayout>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index e8cc499..429d379 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -36,7 +36,6 @@
<string name="test_category_features">Features</string>
<string name="test_category_deskclock">Clock</string>
<string name="test_category_jobscheduler">Job Scheduler</string>
- <string name="test_category_tv">TV</string>
<string name="test_category_other">Other</string>
<string name="clear">Clear</string>
<string name="test_results_cleared">Test results cleared.</string>
@@ -1330,89 +1329,7 @@
<string name="js_any_connectivity_test">Device with no connectivity will not execute a job with an unmetered connectivity constraint.</string>
<string name="js_no_connectivity_test">Device with no connectivity will still execute a job with no connectivity constraints.</string>
- <!-- String for Live Channels app Tests -->
-
- <string name="tv_input_discover_test">3rd-party TV input app discoverability test</string>
- <string name="tv_input_discover_test_info">
- This test verifies that the pre-loaded Live Channels app is invoked via intents and issues
- appropriate calls to framework APIs, so that TV input apps work properly with the pre-loaded
- Live Channels app.
- </string>
- <string name="tv_input_discover_test_go_to_setup">
- Press the \"Launch Live Channels\" button, and set up the newly installed TV input:
- \"CTS Verifier\".
- </string>
- <string name="tv_input_discover_test_verify_setup">
- Setup activity must have been started.
- </string>
- <string name="tv_input_discover_test_tune_to_channel">
- Press the \"Launch Live Channels\" button, and tune to the channel named \"Dummy\" from
- \"CTS Verifier\" input. If necessary, configure the channel to be visible.
- </string>
- <string name="tv_input_discover_test_verify_tune">
- Tune command must be called.
- </string>
- <string name="tv_input_discover_test_verify_overlay_view">
- Overlay view must be shown. Verify that there is a text view displaying \"Overlay View Dummy Text\"
- when you tune to the \"Dummy\" channel.
- </string>
-
- <string name="tv_parental_control_test">Live Channels app parental control test</string>
- <string name="tv_parental_control_test_info">
- This test verifies that the default Live Channels app invokes proper parental control APIs in
- the framework.
- </string>
- <string name="tv_parental_control_test_turn_on_parental_control">
- Press the \"Launch Live Channels\" button, and turn on the parental control. If it\'s on
- already, turn it off and on again.
- </string>
- <string name="tv_parental_control_test_verify_receive_broadcast1">
- TV input service must have received ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED broadcast.
- </string>
- <string name="tv_parental_control_test_block_tv_ma">
- Press the \"Launch Live Channels\" button, and block \"Fake\" rating for \"CtsVerifier\" rating
- system in the parental control settings. You may have to enable the rating system if it is
- disabled by default. If it\'s already blocked, unblock, save, and then block again.
- </string>
- <string name="tv_parental_control_test_verify_receive_broadcast2">
- TV input service must have received ACTION_BLOCKED_RATINGS_CHANGED broadcast.
- </string>
- <string name="tv_parental_control_test_block_unblock">
- Press the \"Launch Live Channels\" button; verify that the channel is blocked visually.
- Try unblock the screen by entering PIN; verify that it\'s unblocked visually.
- </string>
-
- <string name="tv_launch_tv_app">Launch Live Channels</string>
- <string name="tv_channel_not_found">
- CtsVerifier channel is not set up. Please set up before proceeding.
- </string>
-
- <string name="tv_multiple_tracks_test">Live Channels app multiple tracks / subtitle test</string>
- <string name="tv_multiple_tracks_test_info">
- This test verifies that the default Live Channels app invokes proper mulitple tracks / subtitle
- APIs in the framework.
- </string>
- <string name="tv_multiple_tracks_test_select_subtitle">
- Press the \"Launch Live Channels\" button. Verify that the closed caption is off by default.
- Set closed caption to English.
- </string>
- <string name="tv_multiple_tracks_test_verify_set_caption_enabled">
- Caption should be enabled.
- </string>
- <string name="tv_multiple_tracks_test_verify_select_subtitle">
- The English subtitle track should be selected.
- </string>
- <string name="tv_multiple_tracks_test_select_audio">
- Press the \"Launch Live Channels\" button. Verify that the audio track is English by default.
- Select Spanish audio track.
- </string>
- <string name="tv_multiple_tracks_test_verify_select_audio">
- The Spanish audio track should be selected.
- </string>
-
- <string name="overlay_view_text">Overlay View Dummy Text</string>
- <string name="fake_rating">Fake</string>
-
<!-- A list of fully-qualified test classes that should not be run. -->
<string-array name="disabled_tests" />
+
</resources>
diff --git a/apps/CtsVerifier/res/xml/mock_content_rating_systems.xml b/apps/CtsVerifier/res/xml/mock_content_rating_systems.xml
deleted file mode 100644
index 245d7f5..0000000
--- a/apps/CtsVerifier/res/xml/mock_content_rating_systems.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright 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.
--->
-
-<rating-system-definitions xmlns:android="http://schemas.android.com/apk/res/android"
- android:versionCode="1">
- <rating-system-definition android:name="CTS_VERIFIER"
- android:title="CtsVerifier"
- android:description="@string/app_name">
- <rating-definition android:name="MOCK_FAKE"
- android:title="Fake"
- android:contentAgeHint="0"
- android:description="@string/fake_rating" />
- </rating-system-definition>
-</rating-system-definitions>
diff --git a/apps/CtsVerifier/res/xml/mock_tv_input_service.xml b/apps/CtsVerifier/res/xml/mock_tv_input_service.xml
deleted file mode 100644
index 1a2cf86..0000000
--- a/apps/CtsVerifier/res/xml/mock_tv_input_service.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright 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.
--->
-
-<tv-input xmlns:android="http://schemas.android.com/apk/res/android"
- android:setupActivity="com.android.cts.verifier.tv.MockTvInputSetupActivity"
- android:settingsActivity="com.android.cts.verifier.tv.MockTvInputSettingsActivity" />
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/streamquality/StreamingVideoActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/streamquality/StreamingVideoActivity.java
index fa233e8..9684d97 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/streamquality/StreamingVideoActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/streamquality/StreamingVideoActivity.java
@@ -119,30 +119,30 @@
new Stream("H263 Video, AMR Audio", "http_h263_amr",
"http://redirector.c.play.google.com/"
+ "videoplayback?id=271de9756065677e"
- + "&itag=13&ip=0.0.0.0&ipbits=0&expire=999999999999999999"
- + "&sparams=ip,ipbits,expire,ip,ipbits,expire,id,itag"
- + "&signature=372FA4C532AA49D14EAF049BCDA66460EEE161E9"
- + ".6D8BF096B73B7A68A7032CA8685053CFB498D30A"
+ + "&itag=13&ip=0.0.0.0&ipbits=0&expire=19000000000"
+ + "&sparams=ip,ipbits,expire,id,itag"
+ + "&signature=073A731E2BDF1E05206AC7B9B895C922ABCBA01D"
+ + ".1DDA3F999541D2136E6755F16FC44CA972767169"
+ "&source=youtube"
- + "&key=test_key1&user=android-device-test"),
+ + "&key=ik0&user=android-device-test"),
new Stream("MPEG4 SP Video, AAC Audio", "http_mpeg4_aac",
"http://redirector.c.play.google.com/"
+ "videoplayback?id=271de9756065677e"
- + "&itag=17&ip=0.0.0.0&ipbits=0&expire=999999999999999999"
- + "&sparams=ip,ipbits,expire,ip,ipbits,expire,id,itag"
- + "&signature=3DCD3F79E045F95B6AF661765F046FB0440FF016"
- + ".06A42661B3AF6BAF046F012549CC9BA34EBC80A9"
+ + "&itag=17&ip=0.0.0.0&ipbits=0&expire=19000000000"
+ + "&sparams=ip,ipbits,expire,id,itag"
+ + "&signature=6B0F8B8A6A7FD9E4CDF123349C2E061ED2020D74"
+ + ".3460FC81D6C8894BA2D241597D2E1D059845F5F0"
+ "&source=youtube"
- + "&key=test_key1&user=android-device-test"),
+ + "&key=ik0&user=android-device-test"),
new Stream("H264 Base Video, AAC Audio", "http_h264_aac",
"http://redirector.c.play.google.com/"
+ "videoplayback?id=271de9756065677e"
- + "&itag=18&ip=0.0.0.0&ipbits=0&expire=999999999999999999"
- + "&sparams=ip,ipbits,expire,ip,ipbits,expire,id,itag"
- + "&signature=1219C2B07AF0638C27916307A6093C0E43CB894E"
- + ".126B6B916BD57157782738AA7C03E59F21DBC168"
+ + "&itag=18&ip=0.0.0.0&ipbits=0&expire=19000000000"
+ + "&sparams=ip,ipbits,expire,id,itag"
+ + "&signature=75627CD4CEA73D7868CBDE3CE5C4011955164107"
+ + ".1DCFB0EF1372B48DDCFBE69645FE137AC02AF561"
+ "&source=youtube"
- + "&key=test_key1&user=android-device-test"),
+ + "&key=ik0&user=android-device-test"),
};
@Override
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputService.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputService.java
deleted file mode 100644
index f4460de..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputService.java
+++ /dev/null
@@ -1,325 +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.verifier.tv;
-
-import com.android.cts.verifier.R;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Rect;
-import android.media.tv.TvContentRating;
-import android.media.tv.TvInputManager;
-import android.media.tv.TvInputService;
-import android.media.tv.TvTrackInfo;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.view.Surface;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.TextView;
-
-import com.android.cts.verifier.R;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class MockTvInputService extends TvInputService {
- private static final String TAG = "MockTvInputService";
-
- private static final String BROADCAST_ACTION = "action";
- private static final String SELECT_TRACK_TYPE = "type";
- private static final String SELECT_TRACK_ID = "id";
- private static final String CAPTION_ENABLED = "enabled";
-
- private static Object sLock = new Object();
- private static Callback sTuneCallback = null;
- private static Callback sOverlayViewCallback = null;
- private static Callback sBroadcastCallback = null;
- private static Callback sUnblockContentCallback = null;
- private static Callback sSelectTrackCallback = null;
- private static Callback sSetCaptionEnabledCallback = null;
- private static TvContentRating sRating = null;
-
- static final TvTrackInfo sEngAudioTrack =
- new TvTrackInfo.Builder(TvTrackInfo.TYPE_AUDIO, "audio_eng")
- .setAudioChannelCount(2)
- .setAudioSampleRate(48000)
- .setLanguage("eng")
- .build();
- static final TvTrackInfo sSpaAudioTrack =
- new TvTrackInfo.Builder(TvTrackInfo.TYPE_AUDIO, "audio_spa")
- .setAudioChannelCount(2)
- .setAudioSampleRate(48000)
- .setLanguage("spa")
- .build();
- static final TvTrackInfo sEngSubtitleTrack =
- new TvTrackInfo.Builder(TvTrackInfo.TYPE_SUBTITLE, "subtitle_eng")
- .setLanguage("eng")
- .build();
- static final TvTrackInfo sSpaSubtitleTrack =
- new TvTrackInfo.Builder(TvTrackInfo.TYPE_SUBTITLE, "subtitle_spa")
- .setLanguage("spa")
- .build();
-
- private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- synchronized (sLock) {
- if (sBroadcastCallback != null) {
- String expectedAction =
- sBroadcastCallback.getBundle().getString(BROADCAST_ACTION);
- if (intent.getAction().equals(expectedAction)) {
- sBroadcastCallback.post();
- sBroadcastCallback = null;
- }
- }
- }
- }
- };
-
- static void expectTune(View postTarget, Runnable successCallback) {
- synchronized (sLock) {
- sTuneCallback = new Callback(postTarget, successCallback);
- }
- }
-
- static void expectBroadcast(View postTarget, String action, Runnable successCallback) {
- synchronized (sLock) {
- sBroadcastCallback = new Callback(postTarget, successCallback);
- sBroadcastCallback.getBundle().putString(BROADCAST_ACTION, action);
- }
- }
-
- static void expectUnblockContent(View postTarget, Runnable successCallback) {
- synchronized (sLock) {
- sUnblockContentCallback = new Callback(postTarget, successCallback);
- }
- }
-
- static void setBlockRating(TvContentRating rating) {
- synchronized (sLock) {
- sRating = rating;
- }
- }
-
- static void expectOverlayView(View postTarget, Runnable successCallback) {
- synchronized (sLock) {
- sOverlayViewCallback = new Callback(postTarget, successCallback);
- }
- }
-
- static void expectSelectTrack(int type, String id, View postTarget, Runnable successCallback) {
- synchronized (sLock) {
- sSelectTrackCallback = new Callback(postTarget, successCallback);
- sSelectTrackCallback.getBundle().putInt(SELECT_TRACK_TYPE, type);
- sSelectTrackCallback.getBundle().putString(SELECT_TRACK_ID, id);
- }
- }
-
- static void expectSetCaptionEnabled(boolean enabled, View postTarget,
- Runnable successCallback) {
- synchronized (sLock) {
- sSetCaptionEnabledCallback = new Callback(postTarget, successCallback);
- sSetCaptionEnabledCallback.getBundle().putBoolean(CAPTION_ENABLED, enabled);
- }
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(TvInputManager.ACTION_BLOCKED_RATINGS_CHANGED);
- intentFilter.addAction(TvInputManager.ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED);
- registerReceiver(mBroadcastReceiver, intentFilter);
- }
-
- @Override
- public void onDestroy() {
- unregisterReceiver(mBroadcastReceiver);
- super.onDestroy();
- }
-
- @Override
- public Session onCreateSession(String inputId) {
- Session session = new MockSessionImpl(this);
- session.setOverlayViewEnabled(true);
- return session;
- }
-
- private static class MockSessionImpl extends Session {
- private final Context mContext;
- private Surface mSurface = null;
- private List<TvTrackInfo> mTracks = new ArrayList<>();
-
- private MockSessionImpl(Context context) {
- super(context);
- mContext = context;
- mTracks.add(sEngAudioTrack);
- mTracks.add(sSpaAudioTrack);
- mTracks.add(sEngSubtitleTrack);
- mTracks.add(sSpaSubtitleTrack);
- }
-
- @Override
- public void onRelease() {
- }
-
- private void draw() {
- Surface surface = mSurface;
- if (surface == null) return;
- if (!surface.isValid()) return;
-
- Canvas c = surface.lockCanvas(null);
- if (c == null) return;
- try {
- Bitmap b = BitmapFactory.decodeResource(
- mContext.getResources(), R.drawable.icon);
- int srcWidth = b.getWidth();
- int srcHeight = b.getHeight();
- int dstWidth = c.getWidth();
- int dstHeight = c.getHeight();
- c.drawColor(Color.BLACK);
- c.drawBitmap(b, new Rect(0, 0, srcWidth, srcHeight),
- new Rect(10, 10, dstWidth - 10, dstHeight - 10), null);
- } finally {
- surface.unlockCanvasAndPost(c);
- }
- }
-
- @Override
- public View onCreateOverlayView() {
- LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
- LAYOUT_INFLATER_SERVICE);
- View view = inflater.inflate(R.layout.tv_overlay, null);
- TextView textView = (TextView) view.findViewById(R.id.overlay_view_text);
- textView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
- @Override
- public void onLayoutChange(View v, int left, int top, int right, int bottom,
- int oldLeft, int oldTop, int oldRight, int oldBottom) {
- Callback overlayViewCallback = null;
- synchronized (sLock) {
- overlayViewCallback = sOverlayViewCallback;
- sOverlayViewCallback = null;
- }
- if (overlayViewCallback != null) {
- overlayViewCallback.post();
- }
- }
- });
- return view;
- }
-
- @Override
- public boolean onSetSurface(Surface surface) {
- mSurface = surface;
- draw();
- return true;
- }
-
- @Override
- public void onSetStreamVolume(float volume) {
- }
-
- @Override
- public boolean onTune(Uri channelUri) {
- synchronized (sLock) {
- if (sRating != null) {
- notifyContentBlocked(sRating);
- }
- if (sTuneCallback != null) {
- sTuneCallback.post();
- sTuneCallback = null;
- }
- if (sRating == null) {
- notifyContentAllowed();
- }
- }
- notifyVideoAvailable();
- notifyTracksChanged(mTracks);
- notifyTrackSelected(TvTrackInfo.TYPE_AUDIO, sEngAudioTrack.getId());
- notifyTrackSelected(TvTrackInfo.TYPE_SUBTITLE, null);
- return true;
- }
-
- @Override
- public boolean onSelectTrack(int type, String trackId) {
- synchronized (sLock) {
- if (sSelectTrackCallback != null) {
- Bundle bundle = sSelectTrackCallback.getBundle();
- if (bundle.getInt(SELECT_TRACK_TYPE) == type
- && bundle.getString(SELECT_TRACK_ID).equals(trackId)) {
- sSelectTrackCallback.post();
- sSelectTrackCallback = null;
- }
- }
- }
- notifyTrackSelected(type, trackId);
- return true;
- }
-
- @Override
- public void onSetCaptionEnabled(boolean enabled) {
- synchronized (sLock) {
- if (sSetCaptionEnabledCallback != null) {
- Bundle bundle = sSetCaptionEnabledCallback.getBundle();
- if (bundle.getBoolean(CAPTION_ENABLED) == enabled) {
- sSetCaptionEnabledCallback.post();
- sSetCaptionEnabledCallback = null;
- }
- }
- }
- }
-
- @Override
- public void onUnblockContent(TvContentRating unblockedRating) {
- synchronized (sLock) {
- if (sRating != null && sRating.equals(unblockedRating)) {
- sUnblockContentCallback.post();
- sRating = null;
- notifyContentAllowed();
- }
- }
- }
- }
-
- private static class Callback {
- private final View mPostTarget;
- private final Runnable mAction;
- private final Bundle mBundle = new Bundle();
-
- Callback(View postTarget, Runnable action) {
- mPostTarget = postTarget;
- mAction = action;
- }
-
- public void post() {
- mPostTarget.post(mAction);
- }
-
- public Bundle getBundle() {
- return mBundle;
- }
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputSettingsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputSettingsActivity.java
deleted file mode 100644
index 4231db7..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputSettingsActivity.java
+++ /dev/null
@@ -1,23 +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.verifier.tv;
-
-import android.preference.PreferenceActivity;
-
-public class MockTvInputSettingsActivity extends PreferenceActivity {
-
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputSetupActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputSetupActivity.java
deleted file mode 100644
index 81a8edc..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputSetupActivity.java
+++ /dev/null
@@ -1,82 +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.verifier.tv;
-
-import android.app.Activity;
-import android.content.ContentUris;
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.media.tv.TvContract;
-import android.media.tv.TvInputInfo;
-import android.net.Uri;
-import android.os.Bundle;
-import android.util.Pair;
-import android.view.View;
-
-public class MockTvInputSetupActivity extends Activity {
- private static final String TAG = "MockTvInputSetupActivity";
-
- private static final String CHANNEL_NUMBER = "999-0";
- private static final String CHANNEL_NAME = "Dummy";
-
- private static Object sLock = new Object();
- private static Pair<View, Runnable> sLaunchCallback = null;
-
- static void expectLaunch(View postTarget, Runnable successCallback) {
- synchronized (sLock) {
- sLaunchCallback = Pair.create(postTarget, successCallback);
- }
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- try {
- super.onCreate(savedInstanceState);
- final String inputId = getIntent().getStringExtra(TvInputInfo.EXTRA_INPUT_ID);
- final Uri uri = TvContract.buildChannelsUriForInput(inputId);
- final String[] projection = { TvContract.Channels._ID };
- try (Cursor cursor = getContentResolver().query(uri, projection, null, null, null)) {
- // If we already have channels, just finish without doing anything.
- if (cursor != null && cursor.getCount() > 0) {
- return;
- }
- }
- ContentValues values = new ContentValues();
- values.put(TvContract.Channels.COLUMN_INPUT_ID, inputId);
- values.put(TvContract.Channels.COLUMN_DISPLAY_NUMBER, CHANNEL_NUMBER);
- values.put(TvContract.Channels.COLUMN_DISPLAY_NAME, CHANNEL_NAME);
- Uri channelUri = getContentResolver().insert(uri, values);
- // If the channel's ID happens to be zero, we add another and delete the one.
- if (ContentUris.parseId(channelUri) == 0) {
- getContentResolver().insert(uri, values);
- getContentResolver().delete(channelUri, null, null);
- }
- } finally {
- Pair<View, Runnable> launchCallback = null;
- synchronized (sLock) {
- launchCallback = sLaunchCallback;
- sLaunchCallback = null;
- }
- if (launchCallback != null) {
- launchCallback.first.post(launchCallback.second);
- }
-
- setResult(Activity.RESULT_OK);
- finish();
- }
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/MultipleTracksTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/MultipleTracksTestActivity.java
deleted file mode 100644
index 66af4c6..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/MultipleTracksTestActivity.java
+++ /dev/null
@@ -1,154 +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.verifier.tv;
-
-import com.android.cts.verifier.R;
-
-import android.content.Intent;
-import android.database.Cursor;
-import android.media.tv.TvContentRating;
-import android.media.tv.TvContract;
-import android.media.tv.TvInputManager;
-import android.media.tv.TvTrackInfo;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.TextView;
-import android.widget.Toast;
-
-/**
- * Tests for verifying TV app behavior on multiple tracks and subtitle.
- */
-public class MultipleTracksTestActivity extends TvAppVerifierActivity
- implements View.OnClickListener {
- private static final String TAG = "MultipleTracksTestActivity";
-
- private static final long TIMEOUT_MS = 5l * 60l * 1000l; // 5 mins.
-
- private View mSelectSubtitleItem;
- private View mVerifySetCaptionEnabledItem;
- private View mVerifySelectSubtitleItem;
- private View mSelectAudioItem;
- private View mVerifySelectAudioItem;
-
- private Intent mTvAppIntent = null;
-
- @Override
- public void onClick(View v) {
- final View postTarget = getPostTarget();
-
- if (containsButton(mSelectSubtitleItem, v)) {
- final Runnable failCallback = new Runnable() {
- @Override
- public void run() {
- setPassState(mVerifySetCaptionEnabledItem, false);
- setPassState(mVerifySelectSubtitleItem, false);
- }
- };
- postTarget.postDelayed(failCallback, TIMEOUT_MS);
- MockTvInputService.expectSetCaptionEnabled(true, postTarget, new Runnable() {
- @Override
- public void run() {
- postTarget.removeCallbacks(failCallback);
- setPassState(mSelectSubtitleItem, true);
- setPassState(mVerifySetCaptionEnabledItem, true);
- Integer tag = (Integer) mSelectAudioItem.getTag();
- if (tag == 0) {
- mSelectAudioItem.setTag(Integer.valueOf(1));
- } else if (tag == 1) {
- setButtonEnabled(mSelectAudioItem, true);
- }
- }
- });
- MockTvInputService.expectSelectTrack(TvTrackInfo.TYPE_SUBTITLE,
- MockTvInputService.sEngSubtitleTrack.getId(), postTarget, new Runnable() {
- @Override
- public void run() {
- postTarget.removeCallbacks(failCallback);
- setPassState(mSelectSubtitleItem, true);
- setPassState(mVerifySelectSubtitleItem, true);
- Integer tag = (Integer) mSelectAudioItem.getTag();
- if (tag == 0) {
- mSelectAudioItem.setTag(Integer.valueOf(1));
- } else if (tag == 1) {
- setButtonEnabled(mSelectAudioItem, true);
- }
- }
- });
- } else if (containsButton(mSelectAudioItem, v)) {
- final Runnable failCallback = new Runnable() {
- @Override
- public void run() {
- setPassState(mVerifySelectAudioItem, false);
- }
- };
- postTarget.postDelayed(failCallback, TIMEOUT_MS);
- MockTvInputService.expectSelectTrack(TvTrackInfo.TYPE_AUDIO,
- MockTvInputService.sSpaAudioTrack.getId(), postTarget, new Runnable() {
- @Override
- public void run() {
- postTarget.removeCallbacks(failCallback);
- setPassState(mSelectAudioItem, true);
- setPassState(mVerifySelectAudioItem, true);
- getPassButton().setEnabled(true);
- }
- });
- }
- if (mTvAppIntent == null) {
- String[] projection = { TvContract.Channels._ID };
- try (Cursor cursor = getContentResolver().query(TvContract.Channels.CONTENT_URI,
- projection, null, null, null)) {
- if (cursor != null && cursor.moveToNext()) {
- mTvAppIntent = new Intent(Intent.ACTION_VIEW,
- TvContract.buildChannelUri(cursor.getLong(0)));
- }
- }
- if (mTvAppIntent == null) {
- Toast.makeText(this, R.string.tv_channel_not_found, Toast.LENGTH_SHORT).show();
- return;
- }
- }
- startActivity(mTvAppIntent);
- }
-
- @Override
- protected void createTestItems() {
- mSelectSubtitleItem = createUserItem(
- R.string.tv_multiple_tracks_test_select_subtitle,
- R.string.tv_launch_tv_app, this);
- setButtonEnabled(mSelectSubtitleItem, true);
- mVerifySetCaptionEnabledItem = createAutoItem(
- R.string.tv_multiple_tracks_test_verify_set_caption_enabled);
- mVerifySelectSubtitleItem = createAutoItem(
- R.string.tv_multiple_tracks_test_verify_select_subtitle);
- mSelectAudioItem = createUserItem(
- R.string.tv_multiple_tracks_test_select_audio,
- R.string.tv_launch_tv_app, this);
- mSelectAudioItem.setTag(Integer.valueOf(0));
- mVerifySelectAudioItem = createAutoItem(
- R.string.tv_multiple_tracks_test_verify_select_audio);
- }
-
- @Override
- protected void setInfoResources() {
- setInfoResources(R.string.tv_multiple_tracks_test,
- R.string.tv_multiple_tracks_test_info, -1);
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/ParentalControlTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/ParentalControlTestActivity.java
deleted file mode 100644
index 284b485..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/ParentalControlTestActivity.java
+++ /dev/null
@@ -1,149 +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.verifier.tv;
-
-import com.android.cts.verifier.R;
-
-import android.content.Intent;
-import android.database.Cursor;
-import android.media.tv.TvContentRating;
-import android.media.tv.TvContract;
-import android.media.tv.TvInputManager;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.TextView;
-import android.widget.Toast;
-
-/**
- * Tests for verifying TV app behavior on parental control.
- */
-public class ParentalControlTestActivity extends TvAppVerifierActivity
- implements View.OnClickListener {
- private static final String TAG = "ParentalControlTestActivity";
-
- private static final long TIMEOUT_MS = 5l * 60l * 1000l; // 5 mins.
-
- private View mTurnOnParentalControlItem;
- private View mVerifyReceiveBroadcast1Item;
- private View mBlockTvMaItem;
- private View mVerifyReceiveBroadcast2Item;
- private View mBlockUnblockItem;
-
- private Intent mTvAppIntent = null;
-
- @Override
- public void onClick(View v) {
- final View postTarget = getPostTarget();
-
- if (containsButton(mTurnOnParentalControlItem, v)) {
- final Runnable failCallback = new Runnable() {
- @Override
- public void run() {
- setPassState(mVerifyReceiveBroadcast1Item, false);
- }
- };
- postTarget.postDelayed(failCallback, TIMEOUT_MS);
- MockTvInputService.expectBroadcast(postTarget,
- TvInputManager.ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED, new Runnable() {
- @Override
- public void run() {
- postTarget.removeCallbacks(failCallback);
- setPassState(mTurnOnParentalControlItem, true);
- setPassState(mVerifyReceiveBroadcast1Item, true);
- setButtonEnabled(mBlockTvMaItem, true);
- }
- });
- } else if (containsButton(mBlockTvMaItem, v)) {
- final Runnable failCallback = new Runnable() {
- @Override
- public void run() {
- setPassState(mVerifyReceiveBroadcast2Item, false);
- }
- };
- postTarget.postDelayed(failCallback, TIMEOUT_MS);
- MockTvInputService.expectBroadcast(postTarget,
- TvInputManager.ACTION_BLOCKED_RATINGS_CHANGED, new Runnable() {
- @Override
- public void run() {
- postTarget.removeCallbacks(failCallback);
- setPassState(mBlockTvMaItem, true);
- setPassState(mVerifyReceiveBroadcast2Item, true);
- setButtonEnabled(mBlockUnblockItem, true);
- }
- });
- } else if (containsButton(mBlockUnblockItem, v)) {
- final Runnable failCallback = new Runnable() {
- @Override
- public void run() {
- setPassState(mBlockUnblockItem, false);
- }
- };
- postTarget.postDelayed(failCallback, TIMEOUT_MS);
- MockTvInputService.setBlockRating(TvContentRating.createRating(
- "com.android.cts.verifier", "CTS_VERIFIER", "FAKE"));
- MockTvInputService.expectUnblockContent(postTarget, new Runnable() {
- @Override
- public void run() {
- postTarget.removeCallbacks(failCallback);
- setPassState(mBlockUnblockItem, true);
- getPassButton().setEnabled(true);
- }
- });
- }
- if (mTvAppIntent == null) {
- String[] projection = { TvContract.Channels._ID };
- try (Cursor cursor = getContentResolver().query(TvContract.Channels.CONTENT_URI,
- projection, null, null, null)) {
- if (cursor != null && cursor.moveToNext()) {
- mTvAppIntent = new Intent(Intent.ACTION_VIEW,
- TvContract.buildChannelUri(cursor.getLong(0)));
- }
- }
- if (mTvAppIntent == null) {
- Toast.makeText(this, R.string.tv_channel_not_found, Toast.LENGTH_SHORT).show();
- return;
- }
- }
- startActivity(mTvAppIntent);
- }
-
- @Override
- protected void createTestItems() {
- mTurnOnParentalControlItem = createUserItem(
- R.string.tv_parental_control_test_turn_on_parental_control,
- R.string.tv_launch_tv_app, this);
- setButtonEnabled(mTurnOnParentalControlItem, true);
- mVerifyReceiveBroadcast1Item = createAutoItem(
- R.string.tv_parental_control_test_verify_receive_broadcast1);
- mBlockTvMaItem = createUserItem(R.string.tv_parental_control_test_block_tv_ma,
- R.string.tv_launch_tv_app, this);
- mVerifyReceiveBroadcast2Item = createAutoItem(
- R.string.tv_parental_control_test_verify_receive_broadcast2);
- mBlockUnblockItem = createUserItem(R.string.tv_parental_control_test_block_unblock,
- R.string.tv_launch_tv_app, this);
- }
-
- @Override
- protected void setInfoResources() {
- setInfoResources(R.string.tv_parental_control_test,
- R.string.tv_parental_control_test_info, -1);
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvAppVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvAppVerifierActivity.java
deleted file mode 100644
index 3529237..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvAppVerifierActivity.java
+++ /dev/null
@@ -1,113 +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.verifier.tv;
-
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-import android.content.Intent;
-import android.media.tv.TvContract;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-/**
- * Base class for TV app tests.
- */
-public abstract class TvAppVerifierActivity extends PassFailButtons.Activity {
- private static final String TAG = "TvAppVerifierActivity";
-
- private static final long TIMEOUT_MS = 5l * 60l * 1000l; // 5 mins.
-
- private LayoutInflater mInflater;
- private ViewGroup mItemList;
- private View mPostTarget;
-
- protected View getPostTarget() {
- return mPostTarget;
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- mInflater = getLayoutInflater();
- // Reusing location_mode_main.
- View view = mInflater.inflate(R.layout.location_mode_main, null);
- mPostTarget = mItemList = (ViewGroup) view.findViewById(R.id.test_items);
- createTestItems();
- setContentView(view);
- setPassFailButtonClickListeners();
- setInfoResources();
-
- getPassButton().setEnabled(false);
- }
-
- protected void setButtonEnabled(View item, boolean enabled) {
- View button = item.findViewById(R.id.user_action_button);
- button.setClickable(enabled);
- button.setEnabled(enabled);
- }
-
- protected void setPassState(View item, boolean passed) {
- ImageView status = (ImageView) item.findViewById(R.id.status);
- status.setImageResource(passed ? R.drawable.fs_good : R.drawable.fs_error);
- View button = item.findViewById(R.id.user_action_button);
- button.setClickable(false);
- button.setEnabled(false);
- status.invalidate();
- }
-
- protected abstract void createTestItems();
-
- protected abstract void setInfoResources();
-
- /**
- * Call this to create a test step where the user must perform some action.
- */
- protected View createUserItem(int instructionTextId, int buttonTextId, View.OnClickListener l) {
- View item = mInflater.inflate(R.layout.tv_item, mItemList, false);
- TextView instructions = (TextView) item.findViewById(R.id.instructions);
- instructions.setText(instructionTextId);
- Button button = (Button) item.findViewById(R.id.user_action_button);
- button.setVisibility(View.VISIBLE);
- button.setText(buttonTextId);
- button.setOnClickListener(l);
- mItemList.addView(item);
- return item;
- }
-
- /**
- * Call this to create a test step where the test automatically evaluates whether
- * an expected condition is satisfied.
- */
- protected View createAutoItem(int stringId) {
- View item = mInflater.inflate(R.layout.tv_item, mItemList, false);
- TextView instructions = (TextView) item.findViewById(R.id.instructions);
- instructions.setText(stringId);
- mItemList.addView(item);
- return item;
- }
-
- static boolean containsButton(View item, View button) {
- return item.findViewById(R.id.user_action_button) == button;
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvInputDiscoveryTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvInputDiscoveryTestActivity.java
deleted file mode 100644
index 3d17a1a..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvInputDiscoveryTestActivity.java
+++ /dev/null
@@ -1,123 +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.verifier.tv;
-
-import android.content.Intent;
-import android.media.tv.TvContract;
-import android.view.View;
-
-import com.android.cts.verifier.R;
-
-/**
- * Tests for verifying TV app behavior for third-party TV input apps.
- */
-public class TvInputDiscoveryTestActivity extends TvAppVerifierActivity
- implements View.OnClickListener {
- private static final String TAG = "TvInputDiscoveryTestActivity";
-
- private static final Intent TV_APP_INTENT = new Intent(Intent.ACTION_VIEW,
- TvContract.buildChannelUri(0));
-
- private static final long TIMEOUT_MS = 5l * 60l * 1000l; // 5 mins.
-
- private View mGoToSetupItem;
- private View mVerifySetupItem;
- private View mTuneToChannelItem;
- private View mVerifyTuneItem;
- private View mVerifyOverlayViewItem;
- private boolean mTuneVerified;
- private boolean mOverlayViewVerified;
-
- @Override
- public void onClick(View v) {
- final View postTarget = getPostTarget();
-
- if (containsButton(mGoToSetupItem, v)) {
- final Runnable failCallback = new Runnable() {
- @Override
- public void run() {
- setPassState(mVerifySetupItem, false);
- }
- };
- postTarget.postDelayed(failCallback, TIMEOUT_MS);
- MockTvInputSetupActivity.expectLaunch(postTarget, new Runnable() {
- @Override
- public void run() {
- postTarget.removeCallbacks(failCallback);
- setPassState(mGoToSetupItem, true);
- setPassState(mVerifySetupItem, true);
- setButtonEnabled(mTuneToChannelItem, true);
- }
- });
- } else if (containsButton(mTuneToChannelItem, v)) {
- final Runnable failCallback = new Runnable() {
- @Override
- public void run() {
- setPassState(mVerifyTuneItem, false);
- }
- };
- postTarget.postDelayed(failCallback, TIMEOUT_MS);
- MockTvInputService.expectTune(postTarget, new Runnable() {
- @Override
- public void run() {
- setPassState(mTuneToChannelItem, true);
- setPassState(mVerifyTuneItem, true);
-
- mTuneVerified = true;
- updatePassState(postTarget, failCallback);
- }
- });
- MockTvInputService.expectOverlayView(postTarget, new Runnable() {
- @Override
- public void run() {
- postTarget.removeCallbacks(failCallback);
- setPassState(mVerifyOverlayViewItem, true);
-
- mOverlayViewVerified = true;
- updatePassState(postTarget, failCallback);
- }
- });
- }
- startActivity(TV_APP_INTENT);
- }
-
- @Override
- protected void createTestItems() {
- mGoToSetupItem = createUserItem(R.string.tv_input_discover_test_go_to_setup,
- R.string.tv_launch_tv_app, this);
- setButtonEnabled(mGoToSetupItem, true);
- mVerifySetupItem = createAutoItem(R.string.tv_input_discover_test_verify_setup);
- mTuneToChannelItem = createUserItem(R.string.tv_input_discover_test_tune_to_channel,
- R.string.tv_launch_tv_app, this);
- mVerifyTuneItem = createAutoItem(R.string.tv_input_discover_test_verify_tune);
- mVerifyOverlayViewItem = createAutoItem(
- R.string.tv_input_discover_test_verify_overlay_view);
- }
-
- private void updatePassState(View postTarget, Runnable failCallback) {
- if (mTuneVerified && mOverlayViewVerified) {
- postTarget.removeCallbacks(failCallback);
- getPassButton().setEnabled(true);
- }
- }
-
- @Override
- protected void setInfoResources() {
- setInfoResources(R.string.tv_input_discover_test,
- R.string.tv_input_discover_test_info, -1);
- }
-}
diff --git a/hostsidetests/jdwpsecurity/Android.mk b/hostsidetests/jdwpsecurity/Android.mk
new file mode 100644
index 0000000..561d346
--- /dev/null
+++ b/hostsidetests/jdwpsecurity/Android.mk
@@ -0,0 +1,32 @@
+# Copyright (C) 2015 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_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_MODULE_TAGS := optional
+
+# Must match the package name in CtsTestCaseList.mk
+LOCAL_MODULE := CtsJdwpSecurityHostTestCases
+
+LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt
+
+LOCAL_CTS_TEST_PACKAGE := android.host.jdwpsecurity
+
+include $(BUILD_CTS_HOST_JAVA_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/jdwpsecurity/app/Android.mk b/hostsidetests/jdwpsecurity/app/Android.mk
new file mode 100644
index 0000000..13b5be4
--- /dev/null
+++ b/hostsidetests/jdwpsecurity/app/Android.mk
@@ -0,0 +1,30 @@
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := CtsJdwpApp
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+include $(BUILD_JAVA_LIBRARY)
+
+# Copy the built module to the cts dir
+cts_library_jar := $(CTS_TESTCASES_OUT)/$(LOCAL_MODULE).jar
+$(cts_library_jar): $(LOCAL_BUILT_MODULE)
+ $(copy-file-to-target)
+
+# Have the module name depend on the cts files; so the cts files get generated when you run mm/mmm/mma/mmma.
+$(my_register_name) : $(cts_library_jar)
+
diff --git a/hostsidetests/jdwpsecurity/app/src/com/android/cts/jdwpsecurity/JdwpTest.java b/hostsidetests/jdwpsecurity/app/src/com/android/cts/jdwpsecurity/JdwpTest.java
new file mode 100644
index 0000000..f2e5980
--- /dev/null
+++ b/hostsidetests/jdwpsecurity/app/src/com/android/cts/jdwpsecurity/JdwpTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2015 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.jdwpsecurity;
+
+public class JdwpTest {
+ private static final long LOOP_TIMEOUT_MS = 60 * 1000;
+
+ public static void main(String[] args) throws Exception {
+ // Print pid so the test knows who we are.
+ int pid = android.os.Process.myPid();
+ System.out.println(pid);
+
+ // Loop to keep alive so the host test has the time to check whether we have a JDWP
+ // connection.
+ // Note: we use a timeout to avoid indefinite loop in case something wrong happens
+ // with the test harness.
+ long start = System.currentTimeMillis();
+ while(getElapsedTime(start) < LOOP_TIMEOUT_MS) {
+ Thread.sleep(100);
+ }
+ }
+
+ private static long getElapsedTime(long start) {
+ return System.currentTimeMillis() - start;
+ }
+}
diff --git a/hostsidetests/jdwpsecurity/src/android/jdwpsecurity/cts/JdwpSecurityHostTest.java b/hostsidetests/jdwpsecurity/src/android/jdwpsecurity/cts/JdwpSecurityHostTest.java
new file mode 100644
index 0000000..8e276ed
--- /dev/null
+++ b/hostsidetests/jdwpsecurity/src/android/jdwpsecurity/cts/JdwpSecurityHostTest.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.jdwpsecurity.cts;
+
+import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+import com.android.tradefed.util.ArrayUtil;
+import com.android.tradefed.util.RunUtil;
+
+import java.io.BufferedReader;
+import java.io.EOFException;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Test to check non-zygote apps do not have an active JDWP connection.
+ */
+public class JdwpSecurityHostTest extends DeviceTestCase implements IBuildReceiver {
+
+ private static final String DEVICE_LOCATION = "/data/local/tmp/jdwpsecurity";
+ private static final String DEVICE_SCRIPT_FILENAME = "jdwptest";
+ private static final String DEVICE_JAR_FILENAME = "CtsJdwpApp.jar";
+ private static final String JAR_MAIN_CLASS_NAME = "com.android.cts.jdwpsecurity.JdwpTest";
+
+ private CtsBuildHelper mCtsBuild;
+
+ private static String getDeviceScriptFilepath() {
+ return DEVICE_LOCATION + File.separator + DEVICE_SCRIPT_FILENAME;
+ }
+
+ private static String getDeviceJarFilepath() {
+ return DEVICE_LOCATION + File.separator + DEVICE_JAR_FILENAME;
+ }
+
+ @Override
+ public void setBuild(IBuildInfo buildInfo) {
+ mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // Create test directory on the device.
+ createRemoteDir(DEVICE_LOCATION);
+
+ // Also create the dalvik-cache directory. It needs to exist before the runtime starts.
+ createRemoteDir(DEVICE_LOCATION + File.separator + "dalvik-cache");
+
+ // Create and push script on the device.
+ File tempFile = createScriptTempFile();
+ try {
+ boolean success = getDevice().pushFile(tempFile, getDeviceScriptFilepath());
+ assertTrue("Failed to push script to " + getDeviceScriptFilepath(), success);
+ } finally {
+ if (tempFile != null) {
+ tempFile.delete();
+ }
+ }
+
+ // Make the script executable.
+ getDevice().executeShellCommand("chmod 755 " + getDeviceScriptFilepath());
+
+ // Push jar file.
+ File jarFile = mCtsBuild.getTestApp(DEVICE_JAR_FILENAME);
+ boolean success = getDevice().pushFile(jarFile, getDeviceJarFilepath());
+ assertTrue("Failed to push jar file to " + getDeviceScriptFilepath(), success);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ // Delete the whole test directory on the device.
+ getDevice().executeShellCommand(String.format("rm -r %s", DEVICE_LOCATION));
+
+ super.tearDown();
+ }
+
+ /**
+ * Tests a non-zygote app does not have a JDWP connection, thus not being
+ * debuggable.
+ *
+ * Runs a script executing a Java app (jar file) with app_process,
+ * without forking from zygote. Then checks its pid is not returned
+ * by 'adb jdwp', meaning it has no JDWP connection and cannot be
+ * debugged.
+ *
+ * @throws Exception
+ */
+ public void testNonZygoteProgramIsNotDebuggable() throws Exception {
+ String scriptFilepath = getDeviceScriptFilepath();
+ Process scriptProcess = null;
+ String scriptPid = null;
+ List<String> activeJdwpPids = null;
+ try {
+ // Run the script on the background so it's running when we collect the list of
+ // pids with a JDWP connection using 'adb jdwp'.
+ // command.
+ scriptProcess = runScriptInBackground(scriptFilepath);
+
+ // On startup, the script will print its pid on its output.
+ scriptPid = readScriptPid(scriptProcess);
+
+ // Collect the list of pids with a JDWP connection.
+ activeJdwpPids = getJdwpPids();
+ } finally {
+ // Stop the script.
+ if (scriptProcess != null) {
+ scriptProcess.destroy();
+ }
+ }
+
+ assertNotNull("Failed to get script pid", scriptPid);
+ assertNotNull("Failed to get active JDWP pids", activeJdwpPids);
+ assertFalse("Test app should not have an active JDWP connection" +
+ " (pid " + scriptPid + " is returned by 'adb jdwp')",
+ activeJdwpPids.contains(scriptPid));
+ }
+
+ private Process runScriptInBackground(String scriptFilepath) throws IOException {
+ String[] shellScriptCommand = buildAdbCommand("shell", scriptFilepath);
+ return RunUtil.getDefault().runCmdInBackground(shellScriptCommand);
+ }
+
+ private String readScriptPid(Process scriptProcess) throws IOException {
+ BufferedReader br = null;
+ try {
+ br = new BufferedReader(new InputStreamReader(scriptProcess.getInputStream()));
+ // We only expect to read one line containing the pid.
+ return br.readLine();
+ } finally {
+ if (br != null) {
+ br.close();
+ }
+ }
+ }
+
+ private List<String> getJdwpPids() throws Exception {
+ return new AdbJdwpOutputReader().listPidsWithAdbJdwp();
+ }
+
+ /**
+ * Creates the script file on the host so it can be pushed onto the device.
+ *
+ * @return the script file
+ * @throws IOException
+ */
+ private static File createScriptTempFile() throws IOException {
+ File tempFile = File.createTempFile("jdwptest", ".tmp");
+
+ PrintWriter pw = null;
+ try {
+ pw = new PrintWriter(tempFile);
+
+ // We need a dalvik-cache in /data/local/tmp so we have read-write access.
+ // Note: this will cause the runtime to optimize the DEX file (contained in
+ // the jar file) before executing it.
+ pw.println(String.format("export ANDROID_DATA=%s", DEVICE_LOCATION));
+ pw.println(String.format("export CLASSPATH=%s", getDeviceJarFilepath()));
+ pw.println(String.format("exec app_process /system/bin %s \"$@\"",
+ JAR_MAIN_CLASS_NAME));
+ } finally {
+ if (pw != null) {
+ pw.close();
+ }
+ }
+
+ return tempFile;
+ }
+
+ /**
+ * Helper class collecting all pids returned by 'adb jdwp' command.
+ */
+ private class AdbJdwpOutputReader implements Runnable {
+ /**
+ * A list of all pids with a JDWP connection returned by 'adb jdwp'.
+ */
+ private final List<String> lines = new ArrayList<String>();
+
+ /**
+ * The input stream of the process running 'adb jdwp'.
+ */
+ private InputStream in;
+
+ public List<String> listPidsWithAdbJdwp() throws Exception {
+ // The 'adb jdwp' command does not return normally, it only terminates with Ctrl^C.
+ // Therefore we cannot use ITestDevice.executeAdbCommand but need to run that command
+ // in the background. Since we know the tested app is already running, we only need to
+ // capture the output for a short amount of time before stopping the 'adb jdwp'
+ // command.
+ String[] adbJdwpCommand = buildAdbCommand("jdwp");
+ Process adbProcess = RunUtil.getDefault().runCmdInBackground(adbJdwpCommand);
+ in = adbProcess.getInputStream();
+
+ // Read the output for 5s in a separate thread before stopping the command.
+ Thread t = new Thread(this);
+ t.start();
+ Thread.sleep(5000);
+
+ // Kill the 'adb jdwp' process and wait for the thread to stop.
+ adbProcess.destroy();
+ t.join();
+
+ return lines;
+ }
+
+ @Override
+ public void run() {
+ BufferedReader br = null;
+ try {
+ br = new BufferedReader(new InputStreamReader(in));
+ String line;
+ while ((line = readLineIgnoreException(br)) != null) {
+ lines.add(line);
+ }
+ } catch (IOException e) {
+ CLog.e(e);
+ } finally {
+ if (br != null) {
+ try {
+ br.close();
+ } catch (IOException e) {
+ // Ignore it.
+ }
+ }
+ }
+ }
+
+ private String readLineIgnoreException(BufferedReader reader) throws IOException {
+ try {
+ return reader.readLine();
+ } catch (IOException e) {
+ if (e instanceof EOFException) {
+ // This is expected when the process's input stream is closed.
+ return null;
+ } else {
+ throw e;
+ }
+ }
+ }
+ }
+
+ private String[] buildAdbCommand(String... args) {
+ return ArrayUtil.buildArray(new String[] {"adb", "-s", getDevice().getSerialNumber()},
+ args);
+ }
+
+ private boolean createRemoteDir(String remoteFilePath) throws DeviceNotAvailableException {
+ if (getDevice().doesFileExist(remoteFilePath)) {
+ return true;
+ }
+ File remoteFile = new File(remoteFilePath);
+ String parentPath = remoteFile.getParent();
+ if (parentPath != null) {
+ if (!createRemoteDir(parentPath)) {
+ return false;
+ }
+ }
+ getDevice().executeShellCommand(String.format("mkdir %s", remoteFilePath));
+ return getDevice().doesFileExist(remoteFilePath);
+ }
+}
diff --git a/libs/deviceutil/src/android/cts/util/MediaUtils.java b/libs/deviceutil/src/android/cts/util/MediaUtils.java
index 2b76c99..eab4808 100644
--- a/libs/deviceutil/src/android/cts/util/MediaUtils.java
+++ b/libs/deviceutil/src/android/cts/util/MediaUtils.java
@@ -18,8 +18,6 @@
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.media.MediaCodecInfo;
-import android.media.MediaCodecInfo.CodecCapabilities;
-import android.media.MediaCodecInfo.VideoCapabilities;
import android.media.MediaCodecList;
import android.media.MediaExtractor;
import android.media.MediaFormat;
@@ -321,44 +319,11 @@
public static boolean canDecodeVideo(String mime, int width, int height, float rate) {
MediaFormat format = MediaFormat.createVideoFormat(mime, width, height);
-
- // WORKAROUND for MediaCodecList.findDecoderForFormat() that does not
- // work if frame rate is specified.
- return findCodecForFormat(format, (double)rate, false /* encoder */) != null;
+ format.setFloat(MediaFormat.KEY_FRAME_RATE, rate);
+ return canDecode(format);
}
public static boolean checkDecoderForFormat(MediaFormat format) {
return check(canDecode(format), "no decoder for " + format);
}
-
- // WORKAROUND for MediaCodecList.findEncoderForFormat() that does not
- // work if frame rate is specified.
- public static String findEncoderForFormat(MediaFormat format, double rate) {
- return findCodecForFormat(format, rate, true /* encoder */);
- }
-
- private static String findCodecForFormat(MediaFormat format, double rate, boolean encoder) {
- String mime = format.getString(MediaFormat.KEY_MIME);
- for (MediaCodecInfo info : sMCL.getCodecInfos()) {
- if (info.isEncoder() != encoder) {
- continue;
- }
- CodecCapabilities codecCaps = null;
- try {
- codecCaps = info.getCapabilitiesForType(mime);
- } catch (IllegalArgumentException | NullPointerException e) {
- continue;
- }
- if (codecCaps != null && codecCaps.isFormatSupported(format)) {
- int width = format.getInteger(MediaFormat.KEY_WIDTH);
- int height = format.getInteger(MediaFormat.KEY_HEIGHT);
- VideoCapabilities caps = codecCaps.getVideoCapabilities();
- if (caps != null && caps.areSizeAndRateSupported(width, height, rate)) {
- return info.getName();
- }
- }
- }
- return null;
- }
-
}
diff --git a/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/VideoEncoderDecoderTest.java b/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/VideoEncoderDecoderTest.java
index 6747acf..aacb7a5 100644
--- a/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/VideoEncoderDecoderTest.java
+++ b/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/VideoEncoderDecoderTest.java
@@ -16,7 +16,6 @@
package com.android.cts.videoperf;
-import android.cts.util.MediaUtils;
import android.graphics.Point;
import android.media.MediaCodec;
import android.media.MediaCodecList;
@@ -158,9 +157,10 @@
format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
infoEnc.mSupportSemiPlanar ? CodecCapabilities.COLOR_FormatYUV420SemiPlanar :
CodecCapabilities.COLOR_FormatYUV420Planar);
+ format.setInteger(MediaFormat.KEY_FRAME_RATE, infoEnc.mFps);
mFrameRate = infoEnc.mFps;
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, KEY_I_FRAME_INTERVAL);
- double encodingTime = runEncoder(VIDEO_AVC, format, TOTAL_FRAMES, mFrameRate);
+ double encodingTime = runEncoder(VIDEO_AVC, format, TOTAL_FRAMES);
// re-initialize format for decoder
format = new MediaFormat();
format.setString(MediaFormat.KEY_MIME, mimeType);
@@ -208,12 +208,11 @@
* @param totalFrames total number of frames to encode
* @return time taken in ms to encode the frames. This does not include initialization time.
*/
- private double runEncoder(String mimeType, MediaFormat format, int totalFrames, int frameRate) {
+ private double runEncoder(String mimeType, MediaFormat format, int totalFrames) {
MediaCodec codec = null;
try {
MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
- String encoderName = MediaUtils.findEncoderForFormat(format, frameRate);
- format.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate);
+ String encoderName = mcl.findEncoderForFormat(format);
codec = MediaCodec.createByCodecName(encoderName);
codec.configure(
format,
diff --git a/tests/app/src/android/app/cts/MockAlarmReceiver.java b/tests/app/src/android/app/cts/MockAlarmReceiver.java
index 5060cef..8745db6 100644
--- a/tests/app/src/android/app/cts/MockAlarmReceiver.java
+++ b/tests/app/src/android/app/cts/MockAlarmReceiver.java
@@ -25,17 +25,21 @@
* this class receive alarm from AlarmManagerTest
*/
public class MockAlarmReceiver extends BroadcastReceiver {
- public boolean alarmed = false;
- private Object mSync = new Object();
- public static final String MOCKACTION = "android.app.AlarmManagerTest.TEST_ALARMRECEIVER";
+ private final Object mSync = new Object();
+ public final String mTargetAction;
- public long elapsedTime;
- public long rtcTime;
+ public volatile boolean alarmed = false;
+ public volatile long elapsedTime;
+ public volatile long rtcTime;
+
+ public MockAlarmReceiver(String targetAction) {
+ mTargetAction = targetAction;
+ }
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
- if (action.equals(MOCKACTION)) {
+ if (action.equals(mTargetAction)) {
synchronized (mSync) {
alarmed = true;
elapsedTime = SystemClock.elapsedRealtime();
diff --git a/tests/tests/app/src/android/app/cts/AlarmManagerTest.java b/tests/tests/app/src/android/app/cts/AlarmManagerTest.java
index 0780101..bfc3e1d 100644
--- a/tests/tests/app/src/android/app/cts/AlarmManagerTest.java
+++ b/tests/tests/app/src/android/app/cts/AlarmManagerTest.java
@@ -25,45 +25,86 @@
import android.cts.util.PollingCheck;
import android.os.SystemClock;
import android.test.AndroidTestCase;
+import android.util.Log;
public class AlarmManagerTest extends AndroidTestCase {
- private AlarmManager mAlarmManager;
+ public static final String MOCKACTION = "android.app.AlarmManagerTest.TEST_ALARMRECEIVER";
+ public static final String MOCKACTION2 = "android.app.AlarmManagerTest.TEST_ALARMRECEIVER2";
+
+ private AlarmManager mAm;
private Intent mIntent;
private PendingIntent mSender;
- private Intent mServiceIntent;
+ private Intent mIntent2;
+ private PendingIntent mSender2;
/*
* The default snooze delay: 5 seconds
*/
- private final long SNOOZE_DELAY = 5 * 1000L;
+ private static final long SNOOZE_DELAY = 5 * 1000L;
private long mWakeupTime;
private MockAlarmReceiver mMockAlarmReceiver;
+ private MockAlarmReceiver mMockAlarmReceiver2;
- private final int TIME_DELTA = 1000;
- private final int TIME_DELAY = 5000;
+ private static final int TIME_DELTA = 1000;
+ private static final int TIME_DELAY = 10000;
- class Sync {
- public boolean mIsConnected;
- public boolean mIsDisConnected;
- }
+ // Receiver registration/unregistration between tests races with the system process, so
+ // we add a little buffer time here to allow the system to process before we proceed.
+ // This value is in milliseconds.
+ private static final long REGISTER_PAUSE = 250;
+
+ // Constants used for validating exact vs inexact alarm batching immunity. We run a few
+ // trials of an exact alarm that is placed within an inexact alarm's window of opportunity,
+ // and mandate that the average observed delivery skew between the two be statistically
+ // significant -- i.e. that the two alarms are not being coalesced. We also place an
+ // additional exact alarm only a short time after the inexact alarm's nominal trigger time.
+ // If exact alarms are allowed to batch with inexact ones this will tend to have no effect,
+ // but in the correct behavior -- inexact alarms not permitted to batch with exact ones --
+ // this additional exact alarm will have the effect of guaranteeing that the inexact alarm
+ // must fire no later than it -- i.e. a considerable time before the significant, later
+ // exact alarm.
+ //
+ // The test essentially amounts to requiring that the inexact MOCKACTION alarm and
+ // the much later exact MOCKACTION2 alarm fire far apart, always; with an implicit
+ // insistence that alarm batches are delivered at the head of their window.
+ private static final long TEST_WINDOW_LENGTH = 5 * 1000L;
+ private static final long TEST_ALARM_FUTURITY = 6 * 1000L;
+ private static final long FAIL_DELTA = 50;
+ private static final long NUM_TRIALS = 5;
+ private static final long MAX_NEAR_DELIVERIES = 2;
@Override
protected void setUp() throws Exception {
super.setUp();
- mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
- mIntent = new Intent(MockAlarmReceiver.MOCKACTION);
+
+ mAm = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
+
+ mIntent = new Intent(MOCKACTION)
+ .addFlags(Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER_REGISTERED_ONLY);
mSender = PendingIntent.getBroadcast(mContext, 0, mIntent, 0);
- mMockAlarmReceiver = new MockAlarmReceiver();
- IntentFilter filter = new IntentFilter(MockAlarmReceiver.MOCKACTION);
+ mMockAlarmReceiver = new MockAlarmReceiver(mIntent.getAction());
+
+ mIntent2 = new Intent(MOCKACTION2)
+ .addFlags(Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ mSender2 = PendingIntent.getBroadcast(mContext, 0, mIntent2, 0);
+ mMockAlarmReceiver2 = new MockAlarmReceiver(mIntent2.getAction());
+
+ IntentFilter filter = new IntentFilter(mIntent.getAction());
mContext.registerReceiver(mMockAlarmReceiver, filter);
+
+ IntentFilter filter2 = new IntentFilter(mIntent2.getAction());
+ mContext.registerReceiver(mMockAlarmReceiver2, filter2);
+
+ Thread.sleep(REGISTER_PAUSE);
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
- if (mServiceIntent != null) {
- mContext.stopService(mServiceIntent);
- }
+ mContext.unregisterReceiver(mMockAlarmReceiver);
+ mContext.unregisterReceiver(mMockAlarmReceiver2);
+
+ Thread.sleep(REGISTER_PAUSE);
}
public void testSetTypes() throws Exception {
@@ -73,7 +114,7 @@
// test parameter type is RTC_WAKEUP
mMockAlarmReceiver.setAlarmedFalse();
mWakeupTime = System.currentTimeMillis() + SNOOZE_DELAY;
- mAlarmManager.set(AlarmManager.RTC_WAKEUP, mWakeupTime, mSender);
+ mAm.setExact(AlarmManager.RTC_WAKEUP, mWakeupTime, mSender);
new PollingCheck(SNOOZE_DELAY + TIME_DELAY) {
@Override
protected boolean check() {
@@ -85,7 +126,7 @@
// test parameter type is RTC
mMockAlarmReceiver.setAlarmedFalse();
mWakeupTime = System.currentTimeMillis() + SNOOZE_DELAY;
- mAlarmManager.set(AlarmManager.RTC, mWakeupTime, mSender);
+ mAm.setExact(AlarmManager.RTC, mWakeupTime, mSender);
new PollingCheck(SNOOZE_DELAY + TIME_DELAY) {
@Override
protected boolean check() {
@@ -97,7 +138,7 @@
// test parameter type is ELAPSED_REALTIME
mMockAlarmReceiver.setAlarmedFalse();
mWakeupTime = SystemClock.elapsedRealtime() + SNOOZE_DELAY;
- mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, mWakeupTime, mSender);
+ mAm.setExact(AlarmManager.ELAPSED_REALTIME, mWakeupTime, mSender);
new PollingCheck(SNOOZE_DELAY + TIME_DELAY) {
@Override
protected boolean check() {
@@ -109,7 +150,7 @@
// test parameter type is ELAPSED_REALTIME_WAKEUP
mMockAlarmReceiver.setAlarmedFalse();
mWakeupTime = SystemClock.elapsedRealtime() + SNOOZE_DELAY;
- mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, mWakeupTime, mSender);
+ mAm.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, mWakeupTime, mSender);
new PollingCheck(SNOOZE_DELAY + TIME_DELAY) {
@Override
protected boolean check() {
@@ -125,7 +166,7 @@
// that would instead cause such alarms to never be triggered.
mMockAlarmReceiver.setAlarmedFalse();
mWakeupTime = -1000;
- mAlarmManager.set(AlarmManager.RTC, mWakeupTime, mSender);
+ mAm.set(AlarmManager.RTC, mWakeupTime, mSender);
new PollingCheck(TIME_DELAY) {
@Override
protected boolean check() {
@@ -134,10 +175,54 @@
}.run();
}
+ public void testExactAlarmBatching() throws Exception {
+ int deliveriesTogether = 0;
+ for (int i = 0; i < NUM_TRIALS; i++) {
+ final long now = System.currentTimeMillis();
+ final long windowStart = now + TEST_ALARM_FUTURITY;
+ final long exactStart = windowStart + TEST_WINDOW_LENGTH - 1;
+
+ mMockAlarmReceiver.setAlarmedFalse();
+ mMockAlarmReceiver2.setAlarmedFalse();
+ mAm.setWindow(AlarmManager.RTC_WAKEUP, windowStart, TEST_WINDOW_LENGTH, mSender);
+ mAm.setExact(AlarmManager.RTC_WAKEUP, exactStart, mSender2);
+
+ // Wait until a half-second beyond its target window, just to provide a
+ // little safety slop.
+ new PollingCheck(TEST_WINDOW_LENGTH + (windowStart - now) + 500) {
+ @Override
+ protected boolean check() {
+ return mMockAlarmReceiver.alarmed;
+ }
+ }.run();
+
+ // Now wait until 1 sec beyond the expected exact alarm fire time, or for at
+ // least one second if we're already past the nominal exact alarm fire time
+ long timeToExact = Math.max(exactStart - System.currentTimeMillis() + 1000, 1000);
+ new PollingCheck(timeToExact) {
+ @Override
+ protected boolean check() {
+ return mMockAlarmReceiver2.alarmed;
+ }
+ }.run();
+
+ // Success when we observe that the exact and windowed alarm are not being often
+ // delivered close together -- that is, when we can be confident that they are not
+ // being coalesced.
+ final long delta = Math.abs(mMockAlarmReceiver2.rtcTime - mMockAlarmReceiver.rtcTime);
+ Log.i("TEST", "[" + i + "] delta = " + delta);
+ if (delta < FAIL_DELTA) {
+ deliveriesTogether++;
+ assertTrue("Exact alarms appear to be coalescing with inexact alarms",
+ deliveriesTogether <= MAX_NEAR_DELIVERIES);
+ }
+ }
+ }
+
public void testSetRepeating() throws Exception {
mMockAlarmReceiver.setAlarmedFalse();
mWakeupTime = System.currentTimeMillis() + SNOOZE_DELAY;
- mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, mWakeupTime, TIME_DELAY / 2, mSender);
+ mAm.setRepeating(AlarmManager.RTC_WAKEUP, mWakeupTime, TIME_DELAY / 2, mSender);
new PollingCheck(SNOOZE_DELAY + TIME_DELAY) {
@Override
protected boolean check() {
@@ -151,13 +236,13 @@
return mMockAlarmReceiver.alarmed;
}
}.run();
- mAlarmManager.cancel(mSender);
+ mAm.cancel(mSender);
}
public void testCancel() throws Exception {
mMockAlarmReceiver.setAlarmedFalse();
mWakeupTime = System.currentTimeMillis() + SNOOZE_DELAY;
- mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, mWakeupTime, 1000, mSender);
+ mAm.setRepeating(AlarmManager.RTC_WAKEUP, mWakeupTime, 1000, mSender);
new PollingCheck(SNOOZE_DELAY + TIME_DELAY) {
@Override
protected boolean check() {
@@ -171,7 +256,7 @@
return mMockAlarmReceiver.alarmed;
}
}.run();
- mAlarmManager.cancel(mSender);
+ mAm.cancel(mSender);
Thread.sleep(TIME_DELAY);
mMockAlarmReceiver.setAlarmedFalse();
Thread.sleep(TIME_DELAY * 5);
@@ -179,8 +264,7 @@
}
public void testSetInexactRepeating() throws Exception {
-
- mAlarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),
+ mAm.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),
AlarmManager.INTERVAL_FIFTEEN_MINUTES, mSender);
SystemClock.setCurrentTimeMillis(System.currentTimeMillis()
+ AlarmManager.INTERVAL_FIFTEEN_MINUTES);
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java
index bccc89c..37302dc 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java
@@ -14,7 +14,6 @@
import static android.hardware.camera2.cts.CameraTestUtils.*;
import static com.android.ex.camera2.blocking.BlockingSessionCallback.*;
-import android.cts.util.MediaUtils;
import android.graphics.ImageFormat;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraCaptureSession;
@@ -80,7 +79,6 @@
private static final int MAX_VIDEO_SNAPSHOT_IMAGES = 5;
private static final int BURST_VIDEO_SNAPSHOT_NUM = 3;
private static final int SLOWMO_SLOW_FACTOR = 4;
- private static final int MAX_NUM_FRAME_DROP_ALLOWED = 4;
private List<Size> mSupportedVideoSizes;
private Surface mRecordingSurface;
private MediaRecorder mMediaRecorder;
@@ -912,15 +910,6 @@
// Snapshots in legacy mode pause the preview briefly. Skip the duration
// requirements for legacy mode unless this is fixed.
if (!mStaticInfo.isHardwareLevelLegacy()) {
- mCollector.expectTrue(
- String.format(
- "Video %dx%d Frame drop detected before video snapshot: " +
- "duration %dms (expected %dms)",
- mVideoSize.getWidth(), mVideoSize.getHeight(),
- durationMs, expectedDurationMs
- ),
- durationMs <= (expectedDurationMs * MAX_NUM_FRAME_DROP_ALLOWED)
- );
// Log a warning is there is any frame drop detected.
if (durationMs >= expectedDurationMs * 2) {
Log.w(TAG, String.format(
@@ -932,15 +921,6 @@
}
durationMs = (int) (nextTS - currentTS) / 1000000;
- mCollector.expectTrue(
- String.format(
- "Video %dx%d Frame drop detected after video snapshot: " +
- "duration %dms (expected %dms)",
- mVideoSize.getWidth(), mVideoSize.getHeight(),
- durationMs, expectedDurationMs
- ),
- durationMs <= (expectedDurationMs * MAX_NUM_FRAME_DROP_ALLOWED)
- );
// Log a warning is there is any frame drop detected.
if (durationMs >= expectedDurationMs * 2) {
Log.w(TAG, String.format(
@@ -1054,7 +1034,8 @@
private static boolean isSupportedByAVCEncoder(Size sz, int frameRate) {
MediaFormat format = MediaFormat.createVideoFormat(
MediaFormat.MIMETYPE_VIDEO_AVC, sz.getWidth(), sz.getHeight());
+ format.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate);
MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
- return MediaUtils.findEncoderForFormat(format, frameRate) != null;
+ return mcl.findEncoderForFormat(format) != null;
}
}
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyChainTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyChainTest.java
index db6d6ba..7aa6a9d 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyChainTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyChainTest.java
@@ -16,10 +16,11 @@
package android.keystore.cts;
+import android.content.pm.PackageManager;
import android.security.KeyChain;
-import junit.framework.TestCase;
+import android.test.AndroidTestCase;
-public class KeyChainTest extends TestCase {
+public class KeyChainTest extends AndroidTestCase {
public void testIsKeyAlgorithmSupported_RequiredAlgorithmsSupported() throws Exception {
assertTrue("DSA must be supported", KeyChain.isKeyAlgorithmSupported("DSA"));
assertTrue("EC must be supported", KeyChain.isKeyAlgorithmSupported("EC"));
@@ -34,11 +35,21 @@
* tests in hardware/libhardware/tests/keymaster/
*/
public void testIsBoundKeyAlgorithm_RequiredAlgorithmsSupported() throws Exception {
- assertTrue("RSA must be hardware-backed by a hardware-specific Keymaster HAL",
- KeyChain.isBoundKeyAlgorithm("RSA"));
+ if (isLeanbackOnly()) {
+ KeyChain.isBoundKeyAlgorithm("RSA");
+ }
+ else {
+ assertTrue("RSA must be hardware-backed by a hardware-specific Keymaster HAL",
+ KeyChain.isBoundKeyAlgorithm("RSA"));
+ }
// These are not required, but must not throw an exception
KeyChain.isBoundKeyAlgorithm("DSA");
KeyChain.isBoundKeyAlgorithm("EC");
}
+
+ private boolean isLeanbackOnly() {
+ PackageManager pm = getContext().getPackageManager();
+ return (pm != null && pm.hasSystemFeature("android.software.leanback_only"));
+ }
}
diff --git a/tests/tests/media/res/raw/heap_oob_flac.mp3 b/tests/tests/media/res/raw/heap_oob_flac.mp3
new file mode 100644
index 0000000..ae542d0
--- /dev/null
+++ b/tests/tests/media/res/raw/heap_oob_flac.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/midi8sec.mid b/tests/tests/media/res/raw/midi8sec.mid
new file mode 100644
index 0000000..746aca1
--- /dev/null
+++ b/tests/tests/media/res/raw/midi8sec.mid
Binary files differ
diff --git a/tests/tests/media/res/raw/midi_a.mid b/tests/tests/media/res/raw/midi_a.mid
new file mode 100644
index 0000000..941885f
--- /dev/null
+++ b/tests/tests/media/res/raw/midi_a.mid
Binary files differ
diff --git a/tests/tests/media/res/raw/midi_b.mid b/tests/tests/media/res/raw/midi_b.mid
new file mode 100644
index 0000000..424c960
--- /dev/null
+++ b/tests/tests/media/res/raw/midi_b.mid
Binary files differ
diff --git a/tests/tests/media/res/raw/midi_cs.mid b/tests/tests/media/res/raw/midi_cs.mid
new file mode 100644
index 0000000..ee9cb23
--- /dev/null
+++ b/tests/tests/media/res/raw/midi_cs.mid
Binary files differ
diff --git a/tests/tests/media/res/raw/midi_e.mid b/tests/tests/media/res/raw/midi_e.mid
new file mode 100644
index 0000000..dac820d
--- /dev/null
+++ b/tests/tests/media/res/raw/midi_e.mid
Binary files differ
diff --git a/tests/tests/media/res/raw/midi_gs.mid b/tests/tests/media/res/raw/midi_gs.mid
new file mode 100644
index 0000000..1d43841
--- /dev/null
+++ b/tests/tests/media/res/raw/midi_gs.mid
Binary files differ
diff --git a/tests/tests/media/res/raw/video_2840x2160_mp4_hevc_20480kbps_30fps_aac_stereo_128kbps_44100hz.mp4 b/tests/tests/media/res/raw/video_2840x2160_mp4_hevc_20480kbps_30fps_aac_stereo_128kbps_44100hz.mp4
new file mode 100644
index 0000000..7b663a4
--- /dev/null
+++ b/tests/tests/media/res/raw/video_2840x2160_mp4_hevc_20480kbps_30fps_aac_stereo_128kbps_44100hz.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/video_3840x2160_mp4_hevc_20480kbps_30fps_aac_stereo_128kbps_44100hz.mp4 b/tests/tests/media/res/raw/video_3840x2160_mp4_hevc_20480kbps_30fps_aac_stereo_128kbps_44100hz.mp4
deleted file mode 100644
index 9277fbd..0000000
--- a/tests/tests/media/res/raw/video_3840x2160_mp4_hevc_20480kbps_30fps_aac_stereo_128kbps_44100hz.mp4
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java b/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
index 2ef223e..3b46360 100644
--- a/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
+++ b/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
@@ -1348,7 +1348,7 @@
class CodecFactory {
protected boolean hasCodec(String codecName) {
- MediaCodecList list = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ MediaCodecList list = new MediaCodecList(MediaCodecList.ALL_CODECS);
for (MediaCodecInfo info : list.getCodecInfos()) {
if (codecName.equals(info.getName())) {
return true;
diff --git a/tests/tests/media/src/android/media/cts/DecoderTest.java b/tests/tests/media/src/android/media/cts/DecoderTest.java
index 5371f67..c8f2064 100644
--- a/tests/tests/media/src/android/media/cts/DecoderTest.java
+++ b/tests/tests/media/src/android/media/cts/DecoderTest.java
@@ -1047,8 +1047,8 @@
testDecode(R.raw.video_1920x1080_mp4_hevc_10240kbps_30fps_aac_stereo_128kbps_44100hz, 299);
}
- public void testHEVCDecode30fps3840x2160() throws Exception {
- testDecode(R.raw.video_3840x2160_mp4_hevc_20480kbps_30fps_aac_stereo_128kbps_44100hz, 299);
+ public void testHEVCDecode30fps2840x2160() throws Exception {
+ testDecode(R.raw.video_2840x2160_mp4_hevc_20480kbps_30fps_aac_stereo_128kbps_44100hz, 299);
}
private void testCodecEarlyEOS(int resid, int eosFrame) throws Exception {
diff --git a/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayTest.java b/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayTest.java
index 12fcd30..ba67a42 100755
--- a/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayTest.java
+++ b/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayTest.java
@@ -22,7 +22,6 @@
import android.media.MediaCodecList;
import android.media.MediaFormat;
import android.content.Context;
-import android.cts.util.MediaUtils;
import android.graphics.drawable.ColorDrawable;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
@@ -166,10 +165,12 @@
* Returns true if the encoder level, specified in the ENCODER_PARAM_TABLE, can be supported.
*/
private static boolean verifySupportForEncoderLevel(int i) {
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
MediaFormat format = MediaFormat.createVideoFormat(
MIME_TYPE, ENCODER_PARAM_TABLE[i][0], ENCODER_PARAM_TABLE[i][1]);
format.setInteger(MediaFormat.KEY_BIT_RATE, ENCODER_PARAM_TABLE[i][2]);
- return MediaUtils.findEncoderForFormat(format, ENCODER_PARAM_TABLE[i][3]) != null;
+ format.setInteger(MediaFormat.KEY_FRAME_RATE, ENCODER_PARAM_TABLE[i][3]);
+ return mcl.findEncoderForFormat(format) != null;
}
/**
@@ -210,10 +211,11 @@
encoderFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,
MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
encoderFormat.setInteger(MediaFormat.KEY_BIT_RATE, sBitRate);
+ encoderFormat.setInteger(MediaFormat.KEY_FRAME_RATE, sFrameRate);
encoderFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
- String codec = MediaUtils.findEncoderForFormat(encoderFormat, sFrameRate);
- encoderFormat.setInteger(MediaFormat.KEY_FRAME_RATE, sFrameRate);
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ String codec = mcl.findEncoderForFormat(encoderFormat);
if (codec == null) {
// Don't run the test if the codec isn't present.
Log.i(TAG, "SKIPPING test: no support for " + encoderFormat);
diff --git a/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTest.java b/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTest.java
index 4a42791..89d6efa 100644
--- a/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTest.java
+++ b/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTest.java
@@ -22,7 +22,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
-import android.cts.util.MediaUtils;
import android.graphics.SurfaceTexture;
import android.graphics.Typeface;
import android.graphics.drawable.ColorDrawable;
@@ -1326,11 +1325,12 @@
new Size(352, 576)
};
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
for (Size sz : standardSizes) {
MediaFormat format = MediaFormat.createVideoFormat(
MIME_TYPE, sz.getWidth(), sz.getHeight());
- // require at least 15fps
- if (MediaUtils.findEncoderForFormat(format, 15) != null) {
+ format.setInteger(MediaFormat.KEY_FRAME_RATE, 15); // require at least 15fps
+ if (mcl.findEncoderForFormat(format) != null) {
return sz;
}
}
diff --git a/tests/tests/media/src/android/media/cts/ExtractDecodeEditEncodeMuxTest.java b/tests/tests/media/src/android/media/cts/ExtractDecodeEditEncodeMuxTest.java
index 8d1a816..029a632 100644
--- a/tests/tests/media/src/android/media/cts/ExtractDecodeEditEncodeMuxTest.java
+++ b/tests/tests/media/src/android/media/cts/ExtractDecodeEditEncodeMuxTest.java
@@ -18,7 +18,6 @@
import android.annotation.TargetApi;
import android.content.res.AssetFileDescriptor;
-import android.cts.util.MediaUtils;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaCodecList;
@@ -274,12 +273,12 @@
outputVideoFormat.setInteger(
MediaFormat.KEY_COLOR_FORMAT, OUTPUT_VIDEO_COLOR_FORMAT);
outputVideoFormat.setInteger(MediaFormat.KEY_BIT_RATE, OUTPUT_VIDEO_BIT_RATE);
+ outputVideoFormat.setInteger(MediaFormat.KEY_FRAME_RATE, OUTPUT_VIDEO_FRAME_RATE);
outputVideoFormat.setInteger(
MediaFormat.KEY_I_FRAME_INTERVAL, OUTPUT_VIDEO_IFRAME_INTERVAL);
+ if (VERBOSE) Log.d(TAG, "video format: " + outputVideoFormat);
String videoEncoderName = mcl.findEncoderForFormat(outputVideoFormat);
- outputVideoFormat.setInteger(MediaFormat.KEY_FRAME_RATE, OUTPUT_VIDEO_FRAME_RATE);
- if (VERBOSE) Log.d(TAG, "video format: " + outputVideoFormat);
if (videoEncoderName == null) {
// Don't fail CTS if they don't have an AVC codec (not here, anyway).
Log.e(TAG, "Unable to find an appropriate codec for " + outputVideoFormat);
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java b/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
index 1f6b3cf..979a5d1 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
@@ -131,13 +131,11 @@
hasDecoder(MIMETYPE_VIDEO_HEVC, HEVCProfileMain, HEVCMainTierLevel41));
}
- /* this check is not yet working
if (MediaUtils.canDecodeVideo(MIMETYPE_VIDEO_HEVC, 3840, 2160, 30)) {
assertTrue(
"H.265 must support Main10 Profile Main Tier Level 5 if UHD is supported",
hasDecoder(MIMETYPE_VIDEO_HEVC, HEVCProfileMain10, HEVCMainTierLevel5));
}
- */
}
public void testAvcBaseline1() throws Exception {
@@ -153,13 +151,14 @@
if (!checkDecoder(MIMETYPE_VIDEO_AVC, AVCProfileBaseline, AVCLevel12)) {
return; // skip
}
+
playVideoWithRetries("http://redirector.c.youtube.com/videoplayback?id=271de9756065677e"
+ "&itag=160&source=youtube&user=android-device-test"
+ "&sparams=ip,ipbits,expire,id,itag,source,user"
- + "&ip=0.0.0.0&ipbits=0&expire=999999999999999999"
- + "&signature=341692D20FACCAE25B90EA2C131EA6ADCD8E2384."
- + "9EB08C174BE401AAD20FB85EE4DBA51A2882BB60"
- + "&key=test_key1", 256, 144, PLAY_TIME_MS);
+ + "&ip=0.0.0.0&ipbits=0&expire=19000000000"
+ + "&signature=9EDCA0B395B8A949C511FD5E59B9F805CFF797FD."
+ + "702DE9BA7AF96785FD6930AD2DD693A0486C880E"
+ + "&key=ik0", 256, 144, PLAY_TIME_MS);
}
public void testAvcBaseline30() throws Exception {
@@ -169,10 +168,10 @@
playVideoWithRetries("http://redirector.c.youtube.com/videoplayback?id=271de9756065677e"
+ "&itag=18&source=youtube&user=android-device-test"
+ "&sparams=ip,ipbits,expire,id,itag,source,user"
- + "&ip=0.0.0.0&ipbits=0&expire=999999999999999999"
- + "&signature=8701A45F6422229D46ABB25A22E2C00C94024606."
- + "08BCDF16C3F744C49D4C8A8AD1C38B3DC1810918"
- + "&key=test_key1", 640, 360, PLAY_TIME_MS);
+ + "&ip=0.0.0.0&ipbits=0&expire=19000000000"
+ + "&signature=7DCDE3A6594D0B91A27676A3CDC3A87B149F82EA."
+ + "7A83031734CB1EDCE06766B6228842F954927960"
+ + "&key=ik0", 640, 360, PLAY_TIME_MS);
}
public void testAvcHigh31() throws Exception {
@@ -182,11 +181,10 @@
playVideoWithRetries("http://redirector.c.youtube.com/videoplayback?id=271de9756065677e"
+ "&itag=22&source=youtube&user=android-device-test"
+ "&sparams=ip,ipbits,expire,id,itag,source,user"
- + "&ip=0.0.0.0&ipbits=0&expire=999999999999999999"
- + "&signature=42969CA8F7FFAE432B7135BC811F96F7C4172C3F."
- + "1A8A92EA714C1B7C98A05DDF2DE90854CDD7638B"
- + "&key=test_key1", 1280, 720, PLAY_TIME_MS);
-
+ + "&ip=0.0.0.0&ipbits=0&expire=19000000000"
+ + "&signature=179525311196616BD8E1381759B0E5F81A9E91B5."
+ + "C4A50E44059FEBCC6BBC78E3B3A4E0E0065777"
+ + "&key=ik0", 1280, 720, PLAY_TIME_MS);
}
public void testAvcHigh40() throws Exception {
@@ -200,10 +198,10 @@
playVideoWithRetries("http://redirector.c.youtube.com/videoplayback?id=271de9756065677e"
+ "&itag=137&source=youtube&user=android-device-test"
+ "&sparams=ip,ipbits,expire,id,itag,source,user"
- + "&ip=0.0.0.0&ipbits=0&expire=999999999999999999"
- + "&signature=2C836E04C4DDC98649CD44C8B91813D98342D1D1."
- + "870A848D54CA08C197E5FDC34ED45E6ED7DB5CDA"
- + "&key=test_key1", 1920, 1080, PLAY_TIME_MS);
+ + "&ip=0.0.0.0&ipbits=0&expire=19000000000"
+ + "&signature=B0976085596DD42DEA3F08307F76587241CB132B."
+ + "043B719C039E8B92F45391ADC0BE3665E2332930"
+ + "&key=ik0", 1920, 1080, PLAY_TIME_MS);
}
public void testHevcMain1() throws Exception {
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecTest.java b/tests/tests/media/src/android/media/cts/MediaCodecTest.java
index 4688f80..1ff5048 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecTest.java
@@ -1064,7 +1064,7 @@
}
private static boolean supportsCodec(String mimeType, boolean encoder) {
- MediaCodecList list = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ MediaCodecList list = new MediaCodecList(MediaCodecList.ALL_CODECS);
for (MediaCodecInfo info : list.getCodecInfos()) {
if (encoder && !info.isEncoder()) {
continue;
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
index 65a34f4..7cdc483 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
@@ -89,6 +89,37 @@
}
}
+ public void testFlacHeapOverflow() throws Exception {
+ testIfMediaServerDied(R.raw.heap_oob_flac);
+ }
+
+ private void testIfMediaServerDied(int res) throws Exception {
+ mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
+ @Override
+ public boolean onError(MediaPlayer mp, int what, int extra) {
+ assertTrue(mp == mMediaPlayer);
+ assertTrue("mediaserver process died", what != MediaPlayer.MEDIA_ERROR_SERVER_DIED);
+ return false;
+ }
+ });
+
+ mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
+ @Override
+ public void onCompletion(MediaPlayer mp) {
+ assertTrue(mp == mMediaPlayer);
+ mOnCompletionCalled.signal();
+ }
+ });
+
+ AssetFileDescriptor afd = mResources.openRawResourceFd(res);
+ mMediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
+ afd.close();
+ mMediaPlayer.prepare();
+ mMediaPlayer.start();
+ mOnCompletionCalled.waitForSignal();
+ mMediaPlayer.release();
+ }
+
// Bug 13652927
public void testVorbisCrash() throws Exception {
MediaPlayer mp = mMediaPlayer;
@@ -243,6 +274,46 @@
}
}
+ public void testPlayMidi() throws Exception {
+ final int resid = R.raw.midi8sec;
+ final int midiDuration = 8000;
+ final int tolerance = 70;
+ final int seekDuration = 1000;
+
+ MediaPlayer mp = MediaPlayer.create(mContext, resid);
+ try {
+ mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
+ mp.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
+
+ mp.start();
+
+ assertFalse(mp.isLooping());
+ mp.setLooping(true);
+ assertTrue(mp.isLooping());
+
+ assertEquals(midiDuration, mp.getDuration(), tolerance);
+ int pos = mp.getCurrentPosition();
+ assertTrue(pos >= 0);
+ assertTrue(pos < midiDuration - seekDuration);
+
+ mp.seekTo(pos + seekDuration);
+ assertEquals(pos + seekDuration, mp.getCurrentPosition(), tolerance);
+
+ // test stop and restart
+ mp.stop();
+ mp.reset();
+ AssetFileDescriptor afd = mResources.openRawResourceFd(resid);
+ mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
+ afd.close();
+ mp.prepare();
+ mp.start();
+
+ Thread.sleep(SLEEP_TIME);
+ } finally {
+ mp.release();
+ }
+ }
+
static class OutputListener {
int mSession;
AudioEffect mVc;
diff --git a/tests/tests/media/src/android/media/cts/SoundPoolMidiTest.java b/tests/tests/media/src/android/media/cts/SoundPoolMidiTest.java
new file mode 100644
index 0000000..a8c640e
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/SoundPoolMidiTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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 android.media.cts;
+
+import com.android.cts.media.R;
+
+public class SoundPoolMidiTest extends SoundPoolTest {
+
+ @Override
+ protected int getSoundA() {
+ return R.raw.midi_a;
+ }
+
+ @Override
+ protected int getSoundCs() {
+ return R.raw.midi_cs;
+ }
+
+ @Override
+ protected int getSoundE() {
+ return R.raw.midi_e;
+ }
+
+ @Override
+ protected int getSoundB() {
+ return R.raw.midi_b;
+ }
+
+ @Override
+ protected int getSoundGs() {
+ return R.raw.midi_gs;
+ }
+
+ @Override
+ protected String getFileName() {
+ return "midi_a.mid";
+ }
+}
diff --git a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
index 748cda7..dd7c1f6 100644
--- a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
@@ -72,9 +72,9 @@
playVideoTest("http://redirector.c.youtube.com/videoplayback?id=271de9756065677e"
+ "&itag=13&source=youtube&ip=0.0.0.0&ipbits=0&expire=19000000000"
+ "&sparams=ip,ipbits,expire,id,itag,source"
- + "&signature=6F5AEC448AAF88466D7A10EBB76020745405D33F."
- + "5050D35AE997E1535FE828B0DE99EF31A699D9D0"
- + "&key=test_key1&user=android-device-test", 176, 144);
+ + "&signature=5729247E22691EBB3E804DDD523EC42DC17DD8CE"
+ + ".443B81C1E8E6D64E4E1555F568BA46C206507D78"
+ + "&key=ik0&user=android-device-test", 176, 144);
}
public void testHTTP_H263_AMR_Video2() throws Exception {
if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_H263, MediaFormat.MIMETYPE_AUDIO_AMR_NB)) {
@@ -84,9 +84,9 @@
playVideoTest("http://redirector.c.youtube.com/videoplayback?id=c80658495af60617"
+ "&itag=13&source=youtube&ip=0.0.0.0&ipbits=0&expire=19000000000"
+ "&sparams=ip,ipbits,expire,id,itag,source"
- + "&signature=71749754E28115FD1C233E3BE96CDDC3F430CB74."
- + "49D1506DE694CC8FCEE63CB4F3AD41EB76C198CE"
- + "&key=test_key1&user=android-device-test", 176, 144);
+ + "&signature=508D82AB36939345BF6B8D0623CB6CABDD9C64C3"
+ + ".9B3336A96846DF38E5343C46AA57F6CF2956E427"
+ + "&key=ik0&user=android-device-test", 176, 144);
}
public void testHTTP_MPEG4SP_AAC_Video1() throws Exception {
@@ -97,9 +97,9 @@
playVideoTest("http://redirector.c.youtube.com/videoplayback?id=271de9756065677e"
+ "&itag=17&source=youtube&ip=0.0.0.0&ipbits=0&expire=19000000000"
+ "&sparams=ip,ipbits,expire,id,itag,source"
- + "&signature=197A9742C1EFCA95725F2F26DFFD512FC48C149F."
- + "A59B42FD490F6B591B292F3B2659A9723B980351"
- + "&key=test_key1&user=android-device-test", 176, 144);
+ + "&signature=837198AAADF6F36BA6B2D324F690A7C5B7AFE3FF"
+ + ".7138CE5E36D718220726C1FC305497FF2D082249"
+ + "&key=ik0&user=android-device-test", 176, 144);
}
public void testHTTP_MPEG4SP_AAC_Video2() throws Exception {
if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_MPEG4)) {
@@ -109,9 +109,9 @@
playVideoTest("http://redirector.c.youtube.com/videoplayback?id=c80658495af60617"
+ "&itag=17&source=youtube&ip=0.0.0.0&ipbits=0&expire=19000000000"
+ "&sparams=ip,ipbits,expire,id,itag,source"
- + "&signature=0F84740A7E06F884127E78A6D7DE6DEA8F4B8BFD."
- + "248DF1E90B8137C30769C79BF23147F6BB3DFCDF"
- + "&key=test_key1&user=android-device-test", 176, 144);
+ + "&signature=70E979A621001201BC18622BDBF914FA870BDA40"
+ + ".6E78890B80F4A33A18835F775B1FF64F0A4D0003"
+ + "&key=ik0&user=android-device-test", 176, 144);
}
public void testHTTP_H264Base_AAC_Video1() throws Exception {
@@ -122,9 +122,9 @@
playVideoTest("http://redirector.c.youtube.com/videoplayback?id=271de9756065677e"
+ "&itag=18&source=youtube&ip=0.0.0.0&ipbits=0&expire=19000000000"
+ "&sparams=ip,ipbits,expire,id,itag,source"
- + "&signature=3CFCAFB87EB9FC943FACDC54FEC8C725A801642C."
- + "7D77ACBC4CAF40349BF093E302B635757E45F345"
- + "&key=test_key1&user=android-device-test", 640, 360);
+ + "&signature=667AEEF54639926662CE62361400B8F8C1753B3F"
+ + ".15F46C382C68A9F121BA17BF1F56BEDEB4B06091"
+ + "&key=ik0&user=android-device-test", 640, 360);
}
public void testHTTP_H264Base_AAC_Video2() throws Exception {
if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
@@ -134,9 +134,9 @@
playVideoTest("http://redirector.c.youtube.com/videoplayback?id=c80658495af60617"
+ "&itag=18&source=youtube&ip=0.0.0.0&ipbits=0&expire=19000000000"
+ "&sparams=ip,ipbits,expire,id,itag,source"
- + "&signature=A11D8BA0AA67A27F1409BE0C0B96B756625DB88B."
- + "9BF4C93A130583ADBDF2B953AD5A8A58F518B012"
- + "&key=test_key1&user=android-device-test", 640, 360);
+ + "&signature=46A04ED550CA83B79B60060BA80C79FDA5853D26"
+ + ".49582D382B4A9AFAA163DED38D2AE531D85603C0"
+ + "&key=ik0&user=android-device-test", 640, 360);
}
// Streaming HLS video from YouTube
diff --git a/tests/tests/os/src/android/os/cts/BuildVersionTest.java b/tests/tests/os/src/android/os/cts/BuildVersionTest.java
index 4c92da7..e335901 100644
--- a/tests/tests/os/src/android/os/cts/BuildVersionTest.java
+++ b/tests/tests/os/src/android/os/cts/BuildVersionTest.java
@@ -28,7 +28,8 @@
public class BuildVersionTest extends TestCase {
private static final String LOG_TAG = "BuildVersionTest";
- private static final Set<String> EXPECTED_RELEASES = new HashSet<String>(Arrays.asList("5.0.1"));
+ private static final Set<String> EXPECTED_RELEASES =
+ new HashSet<String>(Arrays.asList("5.0", "5.0.1", "5.0.2"));
private static final int EXPECTED_SDK = 21;
private static final String EXPECTED_BUILD_VARIANT = "user";
private static final String EXPECTED_TAG = "release-keys";
diff --git a/tests/tests/security/AndroidManifest.xml b/tests/tests/security/AndroidManifest.xml
index 8ed74ba..9086b0b 100644
--- a/tests/tests/security/AndroidManifest.xml
+++ b/tests/tests/security/AndroidManifest.xml
@@ -22,6 +22,7 @@
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<application>
<uses-library android:name="android.test.runner" />
diff --git a/tests/tests/security/jni/Android.mk b/tests/tests/security/jni/Android.mk
index 46d0868..69ccdf0 100644
--- a/tests/tests/security/jni/Android.mk
+++ b/tests/tests/security/jni/Android.mk
@@ -32,7 +32,8 @@
android_security_cts_SELinuxTest.cpp \
android_security_cts_MMapExecutableTest.cpp \
android_security_cts_NetlinkSocket.cpp \
- android_security_cts_AudioPolicyBinderTest.cpp
+ android_security_cts_AudioPolicyBinderTest.cpp \
+ android_security_cts_AudioflingerBinderTest.cpp
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
diff --git a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
index ca8e841..22e0997 100644
--- a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
+++ b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
@@ -27,6 +27,7 @@
extern int register_android_security_cts_SELinuxTest(JNIEnv*);
extern int register_android_security_cts_MMapExecutableTest(JNIEnv* env);
extern int register_android_security_cts_AudioPolicyBinderTest(JNIEnv* env);
+extern int register_android_security_cts_AudioFlingerBinderTest(JNIEnv* env);
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *env = NULL;
@@ -75,5 +76,9 @@
return JNI_ERR;
}
+ if (register_android_security_cts_AudioFlingerBinderTest(env)) {
+ return JNI_ERR;
+ }
+
return JNI_VERSION_1_4;
}
diff --git a/tests/tests/security/jni/android_security_cts_AudioflingerBinderTest.cpp b/tests/tests/security/jni/android_security_cts_AudioflingerBinderTest.cpp
new file mode 100644
index 0000000..aa988fc
--- /dev/null
+++ b/tests/tests/security/jni/android_security_cts_AudioflingerBinderTest.cpp
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#define LOG_TAG "AudioFlingerBinderTest-JNI"
+
+#include <jni.h>
+#include <binder/IServiceManager.h>
+#include <media/IAudioFlinger.h>
+#include <media/AudioSystem.h>
+#include <system/audio.h>
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+
+using namespace android;
+
+/*
+ * Native methods used by
+ * cts/tests/tests/security/src/android/security/cts/AudioFlingerBinderTest.java
+ */
+
+#define TEST_ARRAY_SIZE 10000
+#define MAX_ARRAY_SIZE 1024
+#define TEST_PATTERN 0x55
+
+class MyDeathClient: public IBinder::DeathRecipient
+{
+public:
+ MyDeathClient() :
+ mAfIsDead(false) {
+ }
+
+ bool afIsDead() const { return mAfIsDead; }
+
+ // DeathRecipient
+ virtual void binderDied(const wp<IBinder>& who __unused) { mAfIsDead = true; }
+
+private:
+ bool mAfIsDead;
+};
+
+
+static bool connectAudioFlinger(sp<IAudioFlinger>& af, sp<MyDeathClient> &dr)
+{
+ int64_t startTime = 0;
+ while (af == 0) {
+ sp<IBinder> binder = defaultServiceManager()->checkService(String16("media.audio_flinger"));
+ if (binder == 0) {
+ if (startTime == 0) {
+ startTime = uptimeMillis();
+ } else if ((uptimeMillis()-startTime) > 10000) {
+ ALOGE("timeout while getting audio flinger service");
+ return false;
+ }
+ sleep(1);
+ } else {
+ af = interface_cast<IAudioFlinger>(binder);
+ dr = new MyDeathClient();
+ binder->linkToDeath(dr);
+ }
+ }
+ return true;
+}
+
+/*
+ * Checks that AudioSystem::setMasterMute() does not crash mediaserver if a duplicated output
+ * is opened.
+ */
+jboolean android_security_cts_AudioFlinger_test_setMasterMute(JNIEnv* env __unused,
+ jobject thiz __unused)
+{
+ sp<IAudioFlinger> af;
+ sp<MyDeathClient> dr;
+
+ if (!connectAudioFlinger(af, dr)) {
+ return false;
+ }
+
+ // force opening of a duplicating output
+ status_t status = AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ "0");
+ if (status != NO_ERROR) {
+ return false;
+ }
+
+ bool mute;
+ status = AudioSystem::getMasterMute(&mute);
+ if (status != NO_ERROR) {
+ return false;
+ }
+
+ AudioSystem::setMasterMute(!mute);
+
+ sleep(1);
+
+ // Check that mediaserver did not crash
+ if (dr->afIsDead()) {
+ return false;
+ }
+
+ AudioSystem::setMasterMute(mute);
+
+ AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+ AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ "0");
+
+ AudioSystem::setMasterMute(false);
+
+ return true;
+}
+
+jboolean android_security_cts_AudioFlinger_test_setMasterVolume(JNIEnv* env __unused,
+ jobject thiz __unused)
+{
+ sp<IAudioFlinger> af;
+ sp<MyDeathClient> dr;
+
+ if (!connectAudioFlinger(af, dr)) {
+ return false;
+ }
+
+ // force opening of a duplicating output
+ status_t status = AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ "0");
+ if (status != NO_ERROR) {
+ return false;
+ }
+
+ float vol;
+ status = AudioSystem::getMasterVolume(&vol);
+ if (status != NO_ERROR) {
+ return false;
+ }
+
+ AudioSystem::setMasterVolume(vol < 0.5 ? 1.0 : 0.0);
+
+ sleep(1);
+
+ // Check that mediaserver did not crash
+ if (dr->afIsDead()) {
+ return false;
+ }
+
+ AudioSystem::setMasterMute(vol);
+
+ AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+ AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ "0");
+
+ return true;
+}
+
+jboolean android_security_cts_AudioFlinger_test_listAudioPorts(JNIEnv* env __unused,
+ jobject thiz __unused)
+{
+ sp<IAudioFlinger> af;
+ sp<MyDeathClient> dr;
+
+ if (!connectAudioFlinger(af, dr)) {
+ return false;
+ }
+
+ unsigned int num_ports = TEST_ARRAY_SIZE;
+ struct audio_port *ports =
+ (struct audio_port *)calloc(TEST_ARRAY_SIZE, sizeof(struct audio_port));
+
+ memset(ports, TEST_PATTERN, TEST_ARRAY_SIZE * sizeof(struct audio_port));
+
+ status_t status = af->listAudioPorts(&num_ports, ports);
+
+ sleep(1);
+
+ // Check that the memory content above the max allowed array size was not changed
+ char *ptr = (char *)(ports + MAX_ARRAY_SIZE);
+ for (size_t i = 0; i < TEST_ARRAY_SIZE - MAX_ARRAY_SIZE; i++) {
+ if (ptr[i * sizeof(struct audio_port)] != TEST_PATTERN) {
+ free(ports);
+ return false;
+ }
+ }
+
+ free(ports);
+
+ // Check that mediaserver did not crash
+ if (dr->afIsDead()) {
+ return false;
+ }
+
+ return true;
+}
+
+jboolean android_security_cts_AudioFlinger_test_listAudioPatches(JNIEnv* env __unused,
+ jobject thiz __unused)
+{
+ sp<IAudioFlinger> af;
+ sp<MyDeathClient> dr;
+
+ if (!connectAudioFlinger(af, dr)) {
+ return false;
+ }
+
+ unsigned int num_patches = TEST_ARRAY_SIZE;
+ struct audio_patch *patches =
+ (struct audio_patch *)calloc(TEST_ARRAY_SIZE, sizeof(struct audio_patch));
+
+ memset(patches, TEST_PATTERN, TEST_ARRAY_SIZE * sizeof(struct audio_patch));
+
+ status_t status = af->listAudioPatches(&num_patches, patches);
+
+ sleep(1);
+
+ // Check that the memory content above the max allowed array size was not changed
+ char *ptr = (char *)(patches + MAX_ARRAY_SIZE);
+ for (size_t i = 0; i < TEST_ARRAY_SIZE - MAX_ARRAY_SIZE; i++) {
+ if (ptr[i * sizeof(struct audio_patch)] != TEST_PATTERN) {
+ free(patches);
+ return false;
+ }
+ }
+
+ free(patches);
+
+ // Check that mediaserver did not crash
+ if (dr->afIsDead()) {
+ return false;
+ }
+
+ return true;
+}
+
+static JNINativeMethod gMethods[] = {
+ { "native_test_setMasterMute", "()Z",
+ (void *) android_security_cts_AudioFlinger_test_setMasterMute },
+ { "native_test_setMasterVolume", "()Z",
+ (void *) android_security_cts_AudioFlinger_test_setMasterVolume },
+ { "native_test_listAudioPorts", "()Z",
+ (void *) android_security_cts_AudioFlinger_test_listAudioPorts },
+ { "native_test_listAudioPatches", "()Z",
+ (void *) android_security_cts_AudioFlinger_test_listAudioPatches },
+};
+
+int register_android_security_cts_AudioFlingerBinderTest(JNIEnv* env)
+{
+ jclass clazz = env->FindClass("android/security/cts/AudioFlingerBinderTest");
+ return env->RegisterNatives(clazz, gMethods,
+ sizeof(gMethods) / sizeof(JNINativeMethod));
+}
diff --git a/tests/tests/security/src/android/security/cts/AudioFlingerBinderTest.java b/tests/tests/security/src/android/security/cts/AudioFlingerBinderTest.java
new file mode 100644
index 0000000..37c472e
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/AudioFlingerBinderTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import junit.framework.TestCase;
+
+public class AudioFlingerBinderTest extends TestCase {
+
+ static {
+ System.loadLibrary("ctssecurity_jni");
+ }
+
+ /**
+ * Checks that AudioSystem::setMasterMute() does not crash mediaserver if a duplicated output
+ * is opened.
+ */
+ public void test_setMasterMute() throws Exception {
+ assertTrue(native_test_setMasterMute());
+ }
+
+ /**
+ * Checks that AudioSystem::setMasterVolume() does not crash mediaserver if a duplicated output
+ * is opened.
+ */
+ public void test_setMasterVolume() throws Exception {
+ assertTrue(native_test_setMasterVolume());
+ }
+
+ /**
+ * Checks that IAudioFlinger::listAudioPorts() does not cause a memory overflow when passed a
+ * large number of ports.
+ */
+ public void test_listAudioPorts() throws Exception {
+ assertTrue(native_test_listAudioPorts());
+ }
+
+ /**
+ * Checks that IAudioFlinger::listAudioPatches() does not cause a memory overflow when passed a
+ * large number of ports.
+ */
+ public void test_listAudioPatches() throws Exception {
+ assertTrue(native_test_listAudioPatches());
+ }
+
+ private static native boolean native_test_setMasterMute();
+ private static native boolean native_test_setMasterVolume();
+ private static native boolean native_test_listAudioPorts();
+ private static native boolean native_test_listAudioPatches();
+}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java b/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
index 7e8a19e..25431b2 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
@@ -31,7 +31,7 @@
@Option(name="cts-install-path", description="the path to the cts installation to use")
private String mCtsRootDirPath = System.getProperty("CTS_ROOT");
- public static final String CTS_BUILD_VERSION = "5.0_r1.94";
+ public static final String CTS_BUILD_VERSION = "5.0_r2";
/**
* {@inheritDoc}