am f47c1f71: am d101eb99: Merge "Tests for LauncherApps" into lmp-sprout-dev
* commit 'f47c1f71bdf5086e394ba08a3b71d545f7ef9d3b':
diff --git a/apps/CameraITS/CameraITS.pdf b/apps/CameraITS/CameraITS.pdf
index 0d10bae..2430420 100644
--- a/apps/CameraITS/CameraITS.pdf
+++ b/apps/CameraITS/CameraITS.pdf
Binary files differ
diff --git a/apps/CameraITS/pymodules/its/device.py b/apps/CameraITS/pymodules/its/device.py
index beba0ae..035e70b 100644
--- a/apps/CameraITS/pymodules/its/device.py
+++ b/apps/CameraITS/pymodules/its/device.py
@@ -53,7 +53,9 @@
PACKAGE = 'com.android.cts.verifier.camera.its'
INTENT_START = 'com.android.cts.verifier.camera.its.START'
ACTION_ITS_RESULT = 'com.android.cts.verifier.camera.its.ACTION_ITS_RESULT'
+ EXTRA_CAMERA_ID = 'camera.its.extra.CAMERA_ID'
EXTRA_SUCCESS = 'camera.its.extra.SUCCESS'
+ EXTRA_SUMMARY = 'camera.its.extra.SUMMARY'
# TODO: Handle multiple connected devices.
ADB = "adb -d"
@@ -241,6 +243,20 @@
raise its.error.Error('Invalid command response')
return data['objValue']
+ def get_camera_ids(self):
+ """Get a list of camera device Ids that can be opened.
+
+ Returns:
+ a list of camera ID string
+ """
+ cmd = {}
+ cmd["cmdName"] = "getCameraIds"
+ self.sock.send(json.dumps(cmd) + "\n")
+ data,_ = self.__read_response_from_socket()
+ if data['tag'] != 'cameraIds':
+ raise its.error.Error('Invalid command response')
+ return data['objValue']['cameraIdArray']
+
def get_camera_properties(self):
"""Get the camera properties object for the device.
@@ -510,21 +526,32 @@
rets.append(objs if ncap>1 else objs[0])
return rets if len(rets)>1 else rets[0]
-def report_result(camera_id, success):
+def report_result(camera_id, success, summary_path=None):
"""Send a pass/fail result to the device, via an intent.
Args:
camera_id: The ID string of the camera for which to report pass/fail.
success: Boolean, indicating if the result was pass or fail.
+ summary_path: (Optional) path to ITS summary file on host PC
Returns:
Nothing.
"""
- resultstr = "%s=%s" % (camera_id, 'True' if success else 'False')
- _run(('%s shell am broadcast '
- '-a %s --es %s %s') % (ItsSession.ADB, ItsSession.ACTION_ITS_RESULT,
- ItsSession.EXTRA_SUCCESS, resultstr))
-
+ device_summary_path = "/sdcard/camera_" + camera_id + "_its_summary.txt"
+ if summary_path is not None:
+ _run("%s push %s %s" % (
+ ItsSession.ADB, summary_path, device_summary_path))
+ _run("%s shell am broadcast -a %s --es %s %s --es %s %s --es %s %s" % (
+ ItsSession.ADB, ItsSession.ACTION_ITS_RESULT,
+ ItsSession.EXTRA_CAMERA_ID, camera_id,
+ ItsSession.EXTRA_SUCCESS, 'True' if success else 'False',
+ ItsSession.EXTRA_SUMMARY, device_summary_path))
+ else:
+ _run("%s shell am broadcast -a %s --es %s %s --es %s %s --es %s %s" % (
+ ItsSession.ADB, ItsSession.ACTION_ITS_RESULT,
+ ItsSession.EXTRA_CAMERA_ID, camera_id,
+ ItsSession.EXTRA_SUCCESS, 'True' if success else 'False',
+ ItsSession.EXTRA_SUMMARY, "null"))
def _run(cmd):
"""Replacement for os.system, with hiding of stdout+stderr messages.
diff --git a/apps/CameraITS/tests/scene1/test_capture_result.py b/apps/CameraITS/tests/scene1/test_capture_result.py
index 331d1cd..ec919f8 100644
--- a/apps/CameraITS/tests/scene1/test_capture_result.py
+++ b/apps/CameraITS/tests/scene1/test_capture_result.py
@@ -39,14 +39,15 @@
its.caps.per_frame_control(props))
manual_tonemap = [0,0, 1,1] # Linear
- manual_transform = its.objects.int_to_rational([1,2,3, 4,5,6, 7,8,9])
- manual_gains = [1,2,3,4]
+ manual_transform = its.objects.float_to_rational(
+ [-1.5,-1.0,-0.5, 0.0,0.5,1.0, 1.5,2.0,3.0])
+ manual_gains = [1,1.5,2.0,3.0]
manual_region = [{"x":8,"y":8,"width":128,"height":128,"weight":1}]
manual_exp_time = min(props['android.sensor.info.exposureTimeRange'])
manual_sensitivity = min(props['android.sensor.info.sensitivityRange'])
# The camera HAL may not support different gains for two G channels.
- manual_gains_ok = [[1,2,3,4],[1,2,2,4],[1,3,3,4]]
+ manual_gains_ok = [[1,1.5,2.0,3.0],[1,1.5,1.5,3.0],[1,2.0,2.0,3.0]]
auto_req = its.objects.auto_capture_request()
auto_req["android.statistics.lensShadingMapMode"] = 1
diff --git a/apps/CameraITS/tools/get_camera_ids.py b/apps/CameraITS/tools/get_camera_ids.py
new file mode 100644
index 0000000..010b046
--- /dev/null
+++ b/apps/CameraITS/tools/get_camera_ids.py
@@ -0,0 +1,37 @@
+# Copyright 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.
+
+import sys
+import its.device
+import its.objects
+import its.image
+
+def main():
+ """get camera ids and save it to disk.
+ """
+ out_path = ""
+ for s in sys.argv[1:]:
+ if s[:4] == "out=" and len(s) > 4:
+ out_path = s[4:]
+ # kind of weird we need to open a camera to get camera ids, but
+ # this is how ITS is working now.
+ with its.device.ItsSession() as cam:
+ camera_ids = cam.get_camera_ids()
+ if out_path != "":
+ with open(out_path, "w") as f:
+ for camera_id in camera_ids:
+ f.write(camera_id + "\n")
+
+if __name__ == '__main__':
+ main()
diff --git a/apps/CameraITS/tools/run_all_tests.py b/apps/CameraITS/tools/run_all_tests.py
index f5a53b1..b56281d 100644
--- a/apps/CameraITS/tools/run_all_tests.py
+++ b/apps/CameraITS/tools/run_all_tests.py
@@ -18,6 +18,7 @@
import subprocess
import time
import sys
+import textwrap
import its.device
def main():
@@ -57,62 +58,111 @@
# Make output directories to hold the generated files.
topdir = tempfile.mkdtemp()
- for d in scenes:
- os.mkdir(os.path.join(topdir, d))
print "Saving output files to:", topdir, "\n"
- # determine camera id
- camera_id = 0
+ camera_ids = []
for s in sys.argv[1:]:
if s[:7] == "camera=" and len(s) > 7:
- camera_id = s[7:]
+ camera_ids.append(s[7:])
- # Run each test, capturing stdout and stderr.
- numpass = 0
- numskip = 0
- numnotmandatedfail = 0
- numfail = 0
- for (scene,testname,testpath) in tests:
- cmd = ['python', os.path.join(os.getcwd(),testpath)] + sys.argv[1:]
- outdir = os.path.join(topdir,scene)
- outpath = os.path.join(outdir,testname+"_stdout.txt")
- errpath = os.path.join(outdir,testname+"_stderr.txt")
- t0 = time.time()
- with open(outpath,"w") as fout, open(errpath,"w") as ferr:
- retcode = subprocess.call(cmd,stderr=ferr,stdout=fout,cwd=outdir)
- t1 = time.time()
+ # user doesn't specify camera id, run through all cameras
+ if not camera_ids:
+ camera_ids_path = os.path.join(topdir, "camera_ids.txt")
+ out_arg = "out=" + camera_ids_path
+ cmd = ['python',
+ os.path.join(os.getcwd(),"tools/get_camera_ids.py"), out_arg]
+ retcode = subprocess.call(cmd,cwd=topdir)
+ assert(retcode == 0)
+ with open(camera_ids_path, "r") as f:
+ for line in f:
+ camera_ids.append(line.replace('\n', ''))
- if retcode == 0:
- retstr = "PASS "
- numpass += 1
- elif retcode == SKIP_RET_CODE:
- retstr = "SKIP "
- numskip += 1
- elif retcode != 0 and testname in NOT_YET_MANDATED[scene]:
- retstr = "FAIL*"
- numnotmandatedfail += 1
+ print "Running ITS on the following cameras:", camera_ids
+
+ for camera_id in camera_ids:
+ # Loop capturing images until user confirm test scene is correct
+ camera_id_arg = "camera=" + camera_id
+ print "Preparing to run ITS on camera", camera_id
+
+ os.mkdir(os.path.join(topdir, camera_id))
+ for d in scenes:
+ os.mkdir(os.path.join(topdir, camera_id, d))
+
+ out_path = os.path.join(topdir, camera_id, "scene.jpg")
+ out_arg = "out=" + out_path
+ cmd = ['python',
+ os.path.join(os.getcwd(),"tools/validate_scene.py"),
+ camera_id_arg, out_arg]
+ retcode = subprocess.call(cmd,cwd=topdir)
+ assert(retcode == 0)
+
+ print "Start running ITS on camera: ", camera_id
+ # Run each test, capturing stdout and stderr.
+ summary = "ITS test result summary for camera " + camera_id + "\n"
+ numpass = 0
+ numskip = 0
+ numnotmandatedfail = 0
+ numfail = 0
+
+ for (scene,testname,testpath) in tests:
+ cmd = ['python', os.path.join(os.getcwd(),testpath)] + \
+ sys.argv[1:] + [camera_id_arg]
+ outdir = os.path.join(topdir,camera_id,scene)
+ outpath = os.path.join(outdir,testname+"_stdout.txt")
+ errpath = os.path.join(outdir,testname+"_stderr.txt")
+ t0 = time.time()
+ with open(outpath,"w") as fout, open(errpath,"w") as ferr:
+ retcode = subprocess.call(cmd,stderr=ferr,stdout=fout,cwd=outdir)
+ t1 = time.time()
+
+ if retcode == 0:
+ retstr = "PASS "
+ numpass += 1
+ elif retcode == SKIP_RET_CODE:
+ retstr = "SKIP "
+ numskip += 1
+ elif retcode != 0 and testname in NOT_YET_MANDATED[scene]:
+ retstr = "FAIL*"
+ numnotmandatedfail += 1
+ else:
+ retstr = "FAIL "
+ numfail += 1
+
+ msg = "%s %s/%s [%.1fs]" % (retstr, scene, testname, t1-t0)
+ print msg
+ summary += msg + "\n"
+ if retcode != 0 and retcode != SKIP_RET_CODE:
+ # Dump the stderr if the test fails
+ with open (errpath, "r") as error_file:
+ errors = error_file.read()
+ summary += errors + "\n"
+
+ if numskip > 0:
+ skipstr = ", %d test%s skipped" % (numskip, "s" if numskip > 1 else "")
else:
- retstr = "FAIL "
- numfail += 1
+ skipstr = ""
- print "%s %s/%s [%.1fs]" % (retstr, scene, testname, t1-t0)
+ test_result = "\n%d / %d tests passed (%.1f%%)%s" % (
+ numpass + numnotmandatedfail, len(tests) - numskip,
+ 100.0 * float(numpass + numnotmandatedfail) / (len(tests) - numskip)
+ if len(tests) != numskip else 100.0,
+ skipstr)
+ print test_result
+ summary += test_result + "\n"
- if numskip > 0:
- skipstr = ", %d test%s skipped" % (numskip, "s" if numskip > 1 else "")
- else:
- skipstr = ""
+ if numnotmandatedfail > 0:
+ msg = "(*) tests are not yet mandated"
+ print msg
+ summary += msg + "\n"
- print "\n%d / %d tests passed (%.1f%%)%s" % (
- numpass + numnotmandatedfail, len(tests) - numskip,
- 100.0 * float(numpass + numnotmandatedfail) / (len(tests) - numskip)
- if len(tests) != numskip else 100.0,
- skipstr)
+ result = numfail == 0
+ print "Reporting ITS result to CtsVerifier"
+ summary_path = os.path.join(topdir, camera_id, "summary.txt")
+ with open(summary_path, "w") as f:
+ f.write(summary)
+ its.device.report_result(camera_id, result, summary_path)
- if numnotmandatedfail > 0:
- print "(*) tests are not yet mandated"
-
- its.device.report_result(camera_id, numfail == 0)
+ print "ITS tests finished. Please go back to CtsVerifier and proceed"
if __name__ == '__main__':
main()
-
diff --git a/apps/CameraITS/tools/validate_scene.py b/apps/CameraITS/tools/validate_scene.py
new file mode 100644
index 0000000..e1e89f2
--- /dev/null
+++ b/apps/CameraITS/tools/validate_scene.py
@@ -0,0 +1,60 @@
+# Copyright 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.
+
+import sys
+import its.device
+import its.objects
+import its.image
+
+def main():
+ """capture a yuv image and save it to argv[1]
+ """
+ camera_id = -1
+ out_path = ""
+ for s in sys.argv[1:]:
+ if s[:7] == "camera=" and len(s) > 7:
+ camera_id = s[7:]
+ elif s[:4] == "out=" and len(s) > 4:
+ out_path = s[4:]
+
+ if camera_id == -1:
+ print "Error: need to specify which camera to use"
+ assert(False)
+
+ with its.device.ItsSession() as cam:
+ raw_input("Press Enter after placing camera " + camera_id +
+ " to frame the test scene")
+ # Converge 3A prior to capture.
+ cam.do_3a(do_af=True, lock_ae=True, lock_awb=True)
+ props = cam.get_camera_properties()
+ req = its.objects.fastest_auto_capture_request(props)
+ req["android.control.awbLock"] = True
+ req["android.control.aeLock"] = True
+ while True:
+ print "Capture an image to check the test scene"
+ cap = cam.do_capture(req)
+ img = its.image.convert_capture_to_rgb_image(cap)
+ if out_path != "":
+ its.image.write_image(img, out_path)
+ print "Please check scene setup in", out_path
+ choice = raw_input(
+ "Is the image okay for ITS scene1? (Y/N)").lower()
+ if choice == "y":
+ break
+ else:
+ raw_input("Press Enter after placing camera " + camera_id +
+ " to frame the test scene")
+
+if __name__ == '__main__':
+ main()
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index cfac5b7..ed0da02 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="4"
- android:versionName="5.0_r2">
+ android:versionCode="5"
+ android:versionName="5.0_r2.5">
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="21"/>
@@ -55,6 +55,8 @@
<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" />
@@ -240,8 +242,8 @@
<service android:name=".bluetooth.BleScannerService"
android:label="@string/ble_scanner_service_name" />
- <!-- TODO: Enable when test quality issues listed in b/18283088 is resolved -->
- <!-- activity android:name=".bluetooth.BleClientTestActivity"
+ <!-- Uncomment until b/15657182, b/18283088 fixed
+ <activity android:name=".bluetooth.BleClientStartActivity"
android:label="@string/ble_client_test_name"
android:configChanges="keyboardHidden|orientation|screenSize">
<intent-filter>
@@ -252,98 +254,9 @@
<meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BluetoothTestActivity" />
<meta-data android:name="test_required_features"
android:value="android.hardware.bluetooth_le"/>
- </activity -->
-
- <activity android:name=".bluetooth.BleClientConnectActivity"
- android:label="@string/ble_client_connect_name"
- android:configChanges="keyboardHidden|orientation|screenSize">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
- <meta-data android:name="test_category" android:value="@string/bt_le" />
- <meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BleClientTestActivity" />
</activity>
- <activity android:name=".bluetooth.BleDiscoverServiceActivity"
- android:label="@string/ble_discover_service_name"
- android:configChanges="keyboardHidden|orientation|screenSize">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
- <meta-data android:name="test_category" android:value="@string/bt_le" />
- <meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BleClientTestActivity" />
- </activity>
-
- <activity android:name=".bluetooth.BleClientCharacteristicActivity"
- android:label="@string/ble_client_characteristic_name"
- android:configChanges="keyboardHidden|orientation|screenSize">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
- <meta-data android:name="test_category" android:value="@string/bt_le" />
- <meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BleClientTestActivity" />
- </activity>
-
- <activity android:name=".bluetooth.BleNotifyCharacteristicActivity"
- android:label="@string/ble_notify_characteristic_name"
- android:configChanges="keyboardHidden|orientation|screenSize">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
- <meta-data android:name="test_category" android:value="@string/bt_le" />
- <meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BleClientTestActivity" />
- </activity>
-
- <activity android:name=".bluetooth.BleClientDescriptorActivity"
- android:label="@string/ble_client_descriptor_name"
- android:configChanges="keyboardHidden|orientation|screenSize">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
- <meta-data android:name="test_category" android:value="@string/bt_le" />
- <meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BleClientTestActivity" />
- </activity>
-
- <activity android:name=".bluetooth.BleReliableWriteActivity"
- android:label="@string/ble_reliable_write_name"
- android:configChanges="keyboardHidden|orientation|screenSize">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
- <meta-data android:name="test_category" android:value="@string/bt_le" />
- <meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BleClientTestActivity" />
- </activity>
-
- <activity android:name=".bluetooth.BleReadRssiActivity"
- android:label="@string/ble_read_rssi_name"
- android:configChanges="keyboardHidden|orientation|screenSize">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
- <meta-data android:name="test_category" android:value="@string/bt_le" />
- <meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BleClientTestActivity" />
- </activity>
-
- <activity android:name=".bluetooth.BleClientDisconnectActivity"
- android:label="@string/ble_client_disconnect_name"
- android:configChanges="keyboardHidden|orientation|screenSize">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
- <meta-data android:name="test_category" android:value="@string/bt_le" />
- <meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BleClientTestActivity" />
- </activity>
-
- <!-- TODO: Enable when test quality issues listed in b/18283088 is resolved -->
- <!-- activity android:name=".bluetooth.BleServerStartActivity"
+ <activity android:name=".bluetooth.BleServerStartActivity"
android:label="@string/ble_server_start_name"
android:configChanges="keyboardHidden|orientation|screenSize">
<intent-filter>
@@ -354,10 +267,9 @@
<meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BluetoothTestActivity" />
<meta-data android:name="test_required_features"
android:value="android.hardware.bluetooth_le"/>
- </activity -->
+ </activity> -->
- <!-- TODO: Enable when test quality issues listed in b/18282549 is resolved -->
- <!-- activity android:name=".bluetooth.BleScannerTestActivity"
+ <activity android:name=".bluetooth.BleScannerTestActivity"
android:label="@string/ble_scanner_test_name"
android:configChanges="keyboardHidden|orientation|screenSize">
<intent-filter>
@@ -368,7 +280,7 @@
<meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BluetoothTestActivity" />
<meta-data android:name="test_required_features"
android:value="android.hardware.bluetooth_le"/>
- </activity -->
+ </activity>
<activity android:name=".bluetooth.BleScannerPowerLevelActivity"
android:label="@string/ble_power_level_name"
@@ -381,6 +293,7 @@
<meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BleScannerTestActivity" />
</activity>
+ <!-- Comment out until we have a better way to validate the hardware scan filter
<activity android:name=".bluetooth.BleScannerHardwareScanFilterActivity"
android:label="@string/ble_scanner_scan_filter_name"
android:configChanges="keyboardHidden|orientation|screenSize">
@@ -391,9 +304,9 @@
<meta-data android:name="test_category" android:value="@string/bt_le" />
<meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BleScannerTestActivity" />
</activity>
+ -->
- <!-- TODO: Enable when test quality issues listed in b/18282549 is resolved -->
- <!-- activity android:name=".bluetooth.BleAdvertiserTestActivity"
+ <activity android:name=".bluetooth.BleAdvertiserTestActivity"
android:label="@string/ble_advertiser_test_name"
android:configChanges="keyboardHidden|orientation|screenSize">
<intent-filter>
@@ -404,7 +317,7 @@
<meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BluetoothTestActivity" />
<meta-data android:name="test_required_features"
android:value="android.hardware.bluetooth_le"/>
- </activity -->
+ </activity>
<activity android:name=".bluetooth.BleAdvertiserPowerLevelActivity"
android:label="@string/ble_power_level_name"
@@ -417,6 +330,7 @@
<meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BleAdvertiserTestActivity" />
</activity>
+ <!-- Comment out until we have a better way to validate the hardware scan filter
<activity android:name=".bluetooth.BleAdvertiserHardwareScanFilterActivity"
android:label="@string/ble_advertiser_scan_filter_name"
android:configChanges="keyboardHidden|orientation|screenSize">
@@ -427,6 +341,7 @@
<meta-data android:name="test_category" android:value="@string/bt_le" />
<meta-data android:name="test_parent" android:value="com.android.cts.verifier.bluetooth.BleAdvertiserTestActivity" />
</activity>
+ -->
<activity android:name=".suid.SuidFilesActivity"
android:label="@string/suid_files"
@@ -914,6 +829,10 @@
<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">
@@ -923,6 +842,10 @@
</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">
@@ -1103,11 +1026,7 @@
</intent-filter>
<meta-data android:name="test_category" android:value="@string/test_category_notifications" />
<meta-data android:name="test_excluded_features"
- android:value="android.hardware.type.watch" />
- <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" />
+ android:value="android.hardware.type.watch:android.software.leanback" />
</activity>
<service android:name=".notifications.MockListener"
@@ -1457,6 +1376,79 @@
<!-- 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=".screenpinning.ScreenPinningTestActivity"
+ android:label="@string/screen_pinning_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_other" />
+ <meta-data android:name="test_excluded_features"
+ android:value="android.hardware.type.television:android.software.leanback:android.hardware.type.watch" />
+ </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/ble_client_connect.xml b/apps/CtsVerifier/res/layout/ble_client_connect.xml
deleted file mode 100644
index 30b4edb..0000000
--- a/apps/CtsVerifier/res/layout/ble_client_connect.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:padding="10dip"
- >
-
- <LinearLayout android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- >
- <Button android:id="@+id/ble_scan_start"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/ble_scan_start"/>
- <Button android:id="@+id/ble_scan_stop"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/ble_scan_stop"/>
- </LinearLayout>
-
- <include android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- layout="@layout/pass_fail_buttons"
- />
-</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/ble_client_read_write.xml b/apps/CtsVerifier/res/layout/ble_client_read_write.xml
deleted file mode 100644
index a263916..0000000
--- a/apps/CtsVerifier/res/layout/ble_client_read_write.xml
+++ /dev/null
@@ -1,71 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:padding="10dip"
- >
- <LinearLayout android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- >
- <LinearLayout android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- >
- <EditText android:id="@+id/write_text"
- android:layout_width="0dp"
- android:layout_weight="1"
- android:layout_height="wrap_content"
- android:text="@string/ble_test_text"
- android:hint="@string/ble_write_hint"
- android:padding="10dip"
- />
- <Button android:id="@+id/ble_write"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:text="@string/ble_write"
- />
- </LinearLayout>
-
- <LinearLayout android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- >
- <TextView android:id="@+id/read_text"
- android:layout_width="0dp"
- android:layout_weight="1"
- android:layout_height="wrap_content"
- android:hint="@string/ble_read_hint"
- android:padding="10dip"
- android:textSize="18sp"
- />
- <Button android:id="@+id/ble_read"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/ble_read"
- />
- </LinearLayout>
- </LinearLayout>
-
- <include android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- layout="@layout/pass_fail_buttons"
- />
-</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/ble_client_test.xml b/apps/CtsVerifier/res/layout/ble_client_start.xml
similarity index 79%
rename from apps/CtsVerifier/res/layout/ble_client_test.xml
rename to apps/CtsVerifier/res/layout/ble_client_start.xml
index 660abd5..c377ca1 100644
--- a/apps/CtsVerifier/res/layout/ble_client_test.xml
+++ b/apps/CtsVerifier/res/layout/ble_client_start.xml
@@ -19,15 +19,17 @@
android:orientation="vertical"
android:padding="10dip"
>
- <ListView android:id="@+id/ble_client_tests"
- android:layout_height="fill_parent"
+ <include android:id="@+id/pass_fail_buttons"
android:layout_width="match_parent"
- android:padding="10dip"
- />
-
- <include android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
layout="@layout/pass_fail_buttons"
/>
-</RelativeLayout>
\ No newline at end of file
+ <ListView android:id="@+id/ble_server_tests"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:layout_above="@id/pass_fail_buttons"
+ android:layout_alignParentTop="true"
+ android:padding="10dip"
+ />
+</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/ble_notify_characteristic.xml b/apps/CtsVerifier/res/layout/ble_notify_characteristic.xml
deleted file mode 100644
index 786918a..0000000
--- a/apps/CtsVerifier/res/layout/ble_notify_characteristic.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:padding="10dip"
- >
- <RelativeLayout android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- >
- <Button android:id="@+id/ble_notify"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerHorizontal="true"
- android:text="@string/ble_begin_notification"
- android:padding="10dip"
- />
- <TextView android:id="@+id/ble_notify_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerHorizontal="true"
- android:layout_below="@id/ble_notify"
- android:textSize="20sp"
- android:padding="10dip"
- />
- </RelativeLayout>
-
- <include android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- layout="@layout/pass_fail_buttons"
- />
-</RelativeLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/layout/ble_read_rssi.xml b/apps/CtsVerifier/res/layout/ble_read_rssi.xml
deleted file mode 100644
index 8aa3193..0000000
--- a/apps/CtsVerifier/res/layout/ble_read_rssi.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:padding="10dip"
- >
- <RelativeLayout android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- >
- <Button android:id="@+id/ble_read_rssi"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerHorizontal="true"
- android:text="@string/ble_read_rssi"
- android:padding="10dip"
- />
- <TextView android:id="@+id/ble_rssi_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerHorizontal="true"
- android:layout_below="@id/ble_read_rssi"
- android:textSize="20sp"
- android:padding="10dip"
- />
- </RelativeLayout>
-
- <include android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- layout="@layout/pass_fail_buttons"
- />
-</RelativeLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/layout/ble_reliable_write.xml b/apps/CtsVerifier/res/layout/ble_reliable_write.xml
deleted file mode 100644
index 05b1812..0000000
--- a/apps/CtsVerifier/res/layout/ble_reliable_write.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:padding="10dip"
- >
- <LinearLayout android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- >
- <EditText android:id="@+id/write_text"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/ble_test_text"
- android:hint="@string/ble_write_hint"
- android:padding="5dip"
- />
- <LinearLayout android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- >
- <Button android:id="@+id/ble_begin"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:text="@string/ble_begin_write"
- />
- <Button android:id="@+id/ble_write"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:text="@string/ble_write"
- />
- <Button android:id="@+id/ble_execute"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:text="@string/ble_execute_write"
- />
- </LinearLayout>
- </LinearLayout>
-
- <include android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- layout="@layout/pass_fail_buttons"
- />
-</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/ble_server_start.xml b/apps/CtsVerifier/res/layout/ble_server_start.xml
index 9ce714d..c377ca1 100644
--- a/apps/CtsVerifier/res/layout/ble_server_start.xml
+++ b/apps/CtsVerifier/res/layout/ble_server_start.xml
@@ -19,7 +19,7 @@
android:orientation="vertical"
android:padding="10dip"
>
- <include android:id="@+id/pass_fail_buttons"
+ <include android:id="@+id/pass_fail_buttons"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
@@ -32,4 +32,4 @@
android:layout_alignParentTop="true"
android:padding="10dip"
/>
-</RelativeLayout>
\ No newline at end of file
+</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/ble_server_start_item.xml b/apps/CtsVerifier/res/layout/ble_test_item.xml
similarity index 100%
rename from apps/CtsVerifier/res/layout/ble_server_start_item.xml
rename to apps/CtsVerifier/res/layout/ble_test_item.xml
diff --git a/apps/CtsVerifier/res/layout/provisioning_byod.xml b/apps/CtsVerifier/res/layout/provisioning_byod.xml
index 989266f..b1b75ba 100644
--- a/apps/CtsVerifier/res/layout/provisioning_byod.xml
+++ b/apps/CtsVerifier/res/layout/provisioning_byod.xml
@@ -21,8 +21,8 @@
<ScrollView
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1">
+ android:layout_height="320dp"
+ android:layout_weight="2">
<TextView
android:id="@+id/byod_instructions"
android:layout_width="match_parent"
@@ -39,9 +39,10 @@
android:text="@string/provisioning_byod_start" />
<ListView
- android:id="@id/android:list"
+ android:id="@+id/android:list"
android:layout_width="match_parent"
- android:layout_height="wrap_content" />
+ android:layout_height="wrap_content"
+ android:layout_weight="3" />
<include layout="@layout/pass_fail_buttons" />
diff --git a/apps/CtsVerifier/res/layout/screen_pinning.xml b/apps/CtsVerifier/res/layout/screen_pinning.xml
new file mode 100644
index 0000000..f1d7b65
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/screen_pinning.xml
@@ -0,0 +1,62 @@
+<?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="match_parent" >
+
+ <TextView
+ android:id="@+id/error_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true" >
+
+ <RelativeLayout
+ android:id="@+id/instructions_group"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+
+ <LinearLayout
+ android:id="@+id/instructions_list"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+
+ </LinearLayout>
+
+ <Button
+ android:id="@+id/next_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentEnd="true"
+ android:layout_below="@id/instructions_list"
+ android:text="@string/next_button_text" />
+
+ </RelativeLayout>
+ </ScrollView>
+
+ <include
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ layout="@layout/pass_fail_buttons" />
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/apps/CtsVerifier/res/layout/tv_item.xml b/apps/CtsVerifier/res/layout/tv_item.xml
new file mode 100644
index 0000000..e7311f9
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/tv_item.xml
@@ -0,0 +1,53 @@
+<?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
new file mode 100644
index 0000000..8cd5dd8
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/tv_overlay.xml
@@ -0,0 +1,29 @@
+<?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 bfa7b55..bd748ac 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -36,6 +36,7 @@
<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>
@@ -187,14 +188,16 @@
<!-- BLE client side strings -->
<string name="ble_client_service_name">Bluetooth LE GATT Client Handler Service</string>
<string name="ble_client_test_name">BLE Client Test</string>
- <string name="ble_client_connect_name">1. BLE Client Connect</string>
- <string name="ble_discover_service_name">2. BLE Discover Service</string>
- <string name="ble_client_characteristic_name">3. BLE Read/Write Characteristic</string>
- <string name="ble_reliable_write_name">4. BLE Reliable Write</string>
- <string name="ble_notify_characteristic_name">5. BLE Notify Characteristic</string>
- <string name="ble_client_descriptor_name">6. BLE Read/Write Descriptor</string>
- <string name="ble_read_rssi_name">7. BLE Read RSSI</string>
- <string name="ble_client_disconnect_name">8. BLE Client Disconnect</string>
+ <string name="ble_client_connect_name">BLE Client Connect</string>
+ <string name="ble_discover_service_name">BLE Discover Service</string>
+ <string name="ble_read_characteristic_name">BLE Read Characteristic</string>
+ <string name="ble_write_characteristic_name">BLE Write Characteristic</string>
+ <string name="ble_reliable_write_name">BLE Reliable Write</string>
+ <string name="ble_notify_characteristic_name">BLE Notify Characteristic</string>
+ <string name="ble_read_descriptor_name">BLE Read Descriptor</string>
+ <string name="ble_write_descriptor_name">BLE Write Descriptor</string>
+ <string name="ble_read_rssi_name">BLE Read RSSI</string>
+ <string name="ble_client_disconnect_name">BLE Client Disconnect</string>
<string name="ble_client_test_info">The BLE test must be done simultaneously on two devices. This device is the client. All tests listed here must be done in order.</string>
<string name="ble_client_send_connect_info">Type in the Bluetooth address of the remote device to connect to, and verify that the devices are connected.</string>
<string name="ble_discover_service_info">Verify that the service is discovered when you press the "Discover Service" button.</string>
@@ -786,7 +789,7 @@
\n\n3. Setup the test scene described in the CameraITS README file, and aim the camera
at it.
\n\n4. Run the full ITS test suite on all possible camera Ids.
- (cd CameraITS; python tools/run_all_tests.py camera=[cameraId]). Once all
+ (cd CameraITS; python tools/run_all_tests.py). Once all
of the tests have been run, the \'PASS\' button will be enabled if all of the tests have
succeeded. Please note that these tests can take 20+ minutes to run.
</string>
@@ -794,8 +797,8 @@
No camera manager exists! This test device is in a bad state.
</string>
<string name="all_legacy_devices">
- All cameras on this device are LEGACY mode only - ITS tests will only be applied to LIMITED
- or better devices. \'PASS\' button enabled.
+ All cameras on this device are LEGACY mode only - ITS tests are only required on LIMITED
+ or better devices. Pass.
</string>
<string name="its_test_passed">All Camera ITS tests passed. Pass button enabled!</string>
<string name="its_test_failed">Some Camera ITS tests failed.</string>
@@ -1267,8 +1270,8 @@
</string>
<string name="provisioning_byod_profileowner">Profile owner installed</string>
<string name="provisioning_byod_diskencryption">Full disk encryption enabled</string>
- <string name="provisioning_byod_profile_visible">Work profile visible in Settings</string>
- <string name="provisioning_byod_admin_visible">Device administrator visible in Settings</string>
+ <string name="provisioning_byod_profile_visible">Profile-aware accounts settings</string>
+ <string name="provisioning_byod_admin_visible">Profile-aware device administrator settings</string>
<string name="provisioning_byod_workapps_visible">Badged work apps visible in Launcher</string>
<string name="provisioning_byod_cross_profile">Open app cross profiles</string>
<string name="provisioning_byod_cross_profile_app_personal">
@@ -1317,6 +1320,47 @@
\n
Then navigate back to this screen using Recents button.
</string>
+
+ <string name="provisioning_byod_app_settings">Profile-aware app settings</string>
+ <string name="provisioning_byod_app_settings_instruction">
+ Please press the Go button to open Apps page in settings.\n
+ \n
+ Verify that work profile exists in the dropdown list and selecting it will
+ bring up apps setting in the work profile.\n
+ \n
+ Then use the Back button to return to this test and mark accordingly.
+ </string>
+
+ <string name="provisioning_byod_location_settings">Profile-aware location settings</string>
+ <string name="provisioning_byod_location_settings_instruction">
+ Please press the Go button to open Location page in settings.\n
+ \n
+ Verify that work profile entry exists in the page.\n
+ \n
+ Then use the Back button to return to this test and mark accordingly.
+ </string>
+
+ <string name="provisioning_byod_cred_settings">Profile-aware trusted credential settings</string>
+ <string name="provisioning_byod_cred_settings_instruction">
+ Please press the Go button to open the Security settings.
+ Navigate to "Trusted credentials" and wait for the UI to load.
+ After the list is loaded, confirm that:\n
+ \n
+ The page list credentials for both "Personal" and "Work" profiles.\n
+ \n
+ Then use the Back button to return to this test and mark accordingly.
+ </string>
+
+ <string name="provisioning_byod_print_settings">Profile-aware printing settings</string>
+ <string name="provisioning_byod_print_settings_instruction">
+ Please press the Go button to open the Printing settings.
+ \n
+ Verify that work profile exists in the dropdown list and selecting it will
+ bring up printing setting in the work profile.\n
+ \n
+ Then use the Back button to return to this test and mark accordingly.
+ </string>
+
<string name="provisioning_byod_no_activity">Cannot communicate with activity in the work profile.</string>
<string name="provisioning_byod_delete_profile">Initiate deletion of work profile.</string>
<string name="provisioning_byod_profile_deleted">Work profile deleted.</string>
@@ -1358,7 +1402,103 @@
<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" />
+ <!-- Strings for screen pinning test -->
+ <string name="screen_pinning_test">Screen Pinning Test</string>
+ <string name="screen_pin_instructions">Pressing next will prompt you to enter screen pinning, allow this app to enter screen pinning.</string>
+ <string name="screen_pin_check_pinned">Press Next to verify the app is pinned.</string>
+ <string name="screen_pin_no_exit">Try to leave the app without unpinning the screen. Press next once you have verified you cannot leave.</string>
+ <string name="screen_pin_exit">Use interactions defined by your device to unpin such as long pressing the back and overview button, then press next.</string>
+ <string name="screen_pinning_done">All tests completed successfully.</string>
+
+ <string name="error_screen_no_longer_pinned">The screen was no longer pinned.</string>
+ <string name="error_screen_already_pinned">Cannot start the test with the screen already pinned.</string>
+ <string name="error_screen_pinning_did_not_start">Screen was not pinned.</string>
+ <string name="error_screen_pinning_did_not_exit">Screen was not unpinned.</string>
+ <string name="error_screen_pinning_couldnt_exit">Could not exit screen pinning through API.</string>
</resources>
diff --git a/apps/CtsVerifier/res/xml/mock_content_rating_systems.xml b/apps/CtsVerifier/res/xml/mock_content_rating_systems.xml
new file mode 100644
index 0000000..245d7f5
--- /dev/null
+++ b/apps/CtsVerifier/res/xml/mock_content_rating_systems.xml
@@ -0,0 +1,27 @@
+<?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
new file mode 100644
index 0000000..1a2cf86
--- /dev/null
+++ b/apps/CtsVerifier/res/xml/mock_tv_input_service.xml
@@ -0,0 +1,19 @@
+<?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/bluetooth/BleAdvertiserService.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertiserService.java
index 281b2e8..b4a6416 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertiserService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertiserService.java
@@ -89,8 +89,11 @@
public static final byte MANUFACTURER_TEST_ID = (byte)0x07;
public static final byte[] PRIVACY_MAC_DATA = new byte[]{3, 1, 4};
public static final byte[] PRIVACY_RESPONSE = new byte[]{9, 2, 6};
- public static final byte[] POWER_LEVEL_DATA = new byte[]{1, 5, 0};
- public static final byte[] POWER_LEVEL_MASK = new byte[]{1, 1, 0};
+ public static final byte[] POWER_LEVEL_DATA = new byte[]{1, 5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // 15 bytes
+ public static final byte[] POWER_LEVEL_MASK = new byte[]{1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // 15 bytes
+ public static final int POWER_LEVEL_DATA_LENGTH = 15;
public static final byte[] SCANNABLE_DATA = new byte[]{5, 3, 5};
public static final byte[] UNSCANNABLE_DATA = new byte[]{8, 9, 7};
@@ -221,8 +224,26 @@
break;
case COMMAND_START_POWER_LEVEL:
for (int t : mPowerLevel) {
- AdvertiseData d =
- generateAdvertiseData(POWER_LEVEL_UUID, new byte[]{1, 5, (byte)t});
+ // Service data:
+ // field overhead = 2 bytes
+ // uuid = 2 bytes
+ // data = 15 bytes
+ // Manufacturer data:
+ // field overhead = 2 bytes
+ // Specific data length = 2 bytes
+ // data length = 2 bytes
+ // Include power level:
+ // field overhead = 2 bytes
+ // 1 byte
+ // Connectable flag: 3 bytes (0 byte for Android 5.1+)
+ // SUM = 31 bytes
+ byte[] dataBytes = new byte[POWER_LEVEL_DATA_LENGTH];
+ dataBytes[0] = 0x01;
+ dataBytes[1] = 0x05;
+ for (int i = 2; i < POWER_LEVEL_DATA_LENGTH; i++) {
+ dataBytes[i] = (byte)t;
+ }
+ AdvertiseData d = generateAdvertiseData(POWER_LEVEL_UUID, dataBytes);
AdvertiseSettings settings = generateSetting(t);
mAdvertiser.startAdvertising(settings, d, mPowerCallback.get(t));
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertiserTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertiserTestActivity.java
index 637ef71..64c50bc 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertiserTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertiserTestActivity.java
@@ -20,8 +20,12 @@
import com.android.cts.verifier.PassFailButtons;
import com.android.cts.verifier.R;
+import android.bluetooth.BluetoothAdapter;
import android.os.Bundle;
+import java.util.ArrayList;
+import java.util.List;
+
public class BleAdvertiserTestActivity extends PassFailButtons.TestListActivity {
@Override
@@ -31,6 +35,14 @@
setPassFailButtonClickListeners();
setInfoResources(R.string.ble_advertiser_test_name, R.string.ble_advertiser_test_info, -1);
- setTestListAdapter(new ManifestTestListAdapter(this, getClass().getName()));
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ List<String> disabledTest = new ArrayList<String>();
+ if (adapter == null || !adapter.isOffloadedFilteringSupported()) {
+ disabledTest.add(
+ "com.android.cts.verifier.bluetooth.BleAdvertiserHardwareScanFilterActivity.");
+ }
+
+ setTestListAdapter(new ManifestTestListAdapter(this, getClass().getName(),
+ disabledTest.toArray(new String[disabledTest.size()])));
}
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientCharacteristicActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientCharacteristicActivity.java
deleted file mode 100644
index 1e1941f..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientCharacteristicActivity.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.verifier.bluetooth;
-
-public class BleClientCharacteristicActivity extends BleReadWriteActivity {
- public BleClientCharacteristicActivity() {
- super(BleReadWriteActivity.CHARACTERISTIC);
- }
-}
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientConnectActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientConnectActivity.java
deleted file mode 100755
index 4e1c268..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientConnectActivity.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.verifier.bluetooth;
-
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Bundle;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.Toast;
-
-public class BleClientConnectActivity extends PassFailButtons.Activity {
-
- private EditText mEditText;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.ble_client_connect);
- setPassFailButtonClickListeners();
- setInfoResources(R.string.ble_client_connect_name,
- R.string.ble_client_send_connect_info, -1);
- getPassButton().setEnabled(false);
-
- ((Button) findViewById(R.id.ble_scan_start)).setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(BleClientConnectActivity.this,
- BleClientService.class);
- intent.putExtra(BleClientService.EXTRA_COMMAND,
- BleClientService.COMMAND_SCAN_START);
- startService(intent);
- }
- });
-
- ((Button) findViewById(R.id.ble_scan_stop)).setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(BleClientConnectActivity.this,
- BleClientService.class);
- intent.putExtra(BleClientService.EXTRA_COMMAND,
- BleClientService.COMMAND_SCAN_STOP);
- startService(intent);
- }
- });
-
- IntentFilter filter = new IntentFilter();
- filter.addAction(BleClientService.BLE_BLUETOOTH_CONNECTED);
- registerReceiver(onBroadcast, filter);
- }
-
- @Override
- protected void onDestroy(){
- super.onDestroy();
- unregisterReceiver(onBroadcast);
- }
-
- private void showMessage(String msg) {
- Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
- }
-
- private BroadcastReceiver onBroadcast = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- showMessage("Bluetooth LE connected");
- getPassButton().setEnabled(true);
- }
- };
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientDescriptorActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientDescriptorActivity.java
deleted file mode 100644
index ab2229a..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientDescriptorActivity.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.verifier.bluetooth;
-
-public class BleClientDescriptorActivity extends BleReadWriteActivity {
- public BleClientDescriptorActivity() {
- super(BleReadWriteActivity.DESCRIPTOR);
- }
-}
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientService.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientService.java
index 6765362..10f862d 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientService.java
@@ -96,6 +96,8 @@
"com.android.cts.verifier.bluetooth.EXTRA_DESCRIPTOR_VALUE";
public static final String EXTRA_RSSI_VALUE =
"com.android.cts.verifier.bluetooth.EXTRA_RSSI_VALUE";
+ public static final String EXTRA_ERROR_MESSAGE =
+ "com.android.cts.verifier.bluetooth.EXTRA_ERROR_MESSAGE";
private static final UUID SERVICE_UUID =
UUID.fromString("00009999-0000-1000-8000-00805f9b34fb");
@@ -106,13 +108,15 @@
private static final UUID DESCRIPTOR_UUID =
UUID.fromString("00009996-0000-1000-8000-00805f9b34fb");
+ private static final String WRITE_VALUE = "TEST";
+
private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
private BluetoothDevice mDevice;
private BluetoothGatt mBluetoothGatt;
+ private BluetoothLeScanner mScanner;
private Handler mHandler;
private Context mContext;
- private BluetoothLeScanner mScanner;
@Override
public void onCreate() {
@@ -120,14 +124,14 @@
mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = mBluetoothManager.getAdapter();
+ mScanner = mBluetoothAdapter.getBluetoothLeScanner();
mHandler = new Handler();
mContext = this;
- mScanner = mBluetoothAdapter.getBluetoothLeScanner();
+ startScan();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
- if (intent != null) handleIntent(intent);
return START_NOT_STICKY;
}
@@ -141,68 +145,10 @@
super.onDestroy();
mBluetoothGatt.disconnect();
mBluetoothGatt.close();
+ mBluetoothGatt = null;
stopScan();
}
- private void handleIntent(Intent intent) {
- int command = intent.getIntExtra(EXTRA_COMMAND, -1);
- String address = intent.getStringExtra(BluetoothDevice.EXTRA_DEVICE); // sometimes null
- String writeValue = intent.getStringExtra(EXTRA_WRITE_VALUE); // sometimes null
- boolean enable = intent.getBooleanExtra(EXTRA_BOOL, false);
- BluetoothGattService service;
- BluetoothGattCharacteristic characteristic;
- BluetoothGattDescriptor descriptor;
-
- switch (command) {
- case COMMAND_CONNECT:
- mDevice = mBluetoothAdapter.getRemoteDevice(address);
- mBluetoothGatt = mDevice.connectGatt(this, false, mGattCallbacks);
- break;
- case COMMAND_DISCONNECT:
- if (mBluetoothGatt != null) mBluetoothGatt.disconnect();
- break;
- case COMMAND_DISCOVER_SERVICE:
- if (mBluetoothGatt != null) mBluetoothGatt.discoverServices();
- break;
- case COMMAND_READ_RSSI:
- if (mBluetoothGatt != null) mBluetoothGatt.readRemoteRssi();
- break;
- case COMMAND_WRITE_CHARACTERISTIC:
- writeCharacteristic(writeValue);
- break;
- case COMMAND_READ_CHARACTERISTIC:
- readCharacteristic();
- break;
- case COMMAND_WRITE_DESCRIPTOR:
- writeDescriptor(writeValue);
- break;
- case COMMAND_READ_DESCRIPTOR:
- readDescriptor();
- break;
- case COMMAND_SET_NOTIFICATION:
- setNotification(enable);
- break;
- case COMMAND_BEGIN_WRITE:
- if (mBluetoothGatt != null) mBluetoothGatt.beginReliableWrite();
- break;
- case COMMAND_EXECUTE_WRITE:
- if (mBluetoothGatt != null) mBluetoothGatt.executeReliableWrite();
- break;
- case COMMAND_ABORT_RELIABLE:
- if (mBluetoothGatt != null) mBluetoothGatt.abortReliableWrite(mDevice);
- break;
- case COMMAND_SCAN_START:
- startScan();
- break;
- case COMMAND_SCAN_STOP:
- stopScan();
- break;
- default:
- showMessage("Unrecognized command: " + command);
- break;
- }
- }
-
private void writeCharacteristic(String writeValue) {
BluetoothGattCharacteristic characteristic = getCharacteristic(CHARACTERISTIC_UUID);
if (characteristic == null) return;
@@ -233,55 +179,69 @@
mBluetoothGatt.setCharacteristicNotification(characteristic, enable);
}
+ private void notifyError(String message) {
+ showMessage(message);
+ }
+
private void notifyConnected() {
+ showMessage("BLE connected");
Intent intent = new Intent(BLE_BLUETOOTH_CONNECTED);
sendBroadcast(intent);
}
private void notifyDisconnected() {
+ showMessage("BLE disconnected");
Intent intent = new Intent(BLE_BLUETOOTH_DISCONNECTED);
sendBroadcast(intent);
}
private void notifyServicesDiscovered() {
+ showMessage("Service discovered");
Intent intent = new Intent(BLE_SERVICES_DISCOVERED);
sendBroadcast(intent);
}
private void notifyCharacteristicRead(String value) {
+ showMessage("Characteristic read: " + value);
Intent intent = new Intent(BLE_CHARACTERISTIC_READ);
intent.putExtra(EXTRA_CHARACTERISTIC_VALUE, value);
sendBroadcast(intent);
}
- private void notifyCharacteristicWrite() {
+ private void notifyCharacteristicWrite(String value) {
+ showMessage("Characteristic write: " + value);
Intent intent = new Intent(BLE_CHARACTERISTIC_WRITE);
sendBroadcast(intent);
}
private void notifyCharacteristicChanged(String value) {
+ showMessage("Characteristic changed: " + value);
Intent intent = new Intent(BLE_CHARACTERISTIC_CHANGED);
intent.putExtra(EXTRA_CHARACTERISTIC_VALUE, value);
sendBroadcast(intent);
}
private void notifyDescriptorRead(String value) {
+ showMessage("Descriptor read: " + value);
Intent intent = new Intent(BLE_DESCRIPTOR_READ);
intent.putExtra(EXTRA_DESCRIPTOR_VALUE, value);
sendBroadcast(intent);
}
- private void notifyDescriptorWrite() {
+ private void notifyDescriptorWrite(String value) {
+ showMessage("Descriptor write: " + value);
Intent intent = new Intent(BLE_DESCRIPTOR_WRITE);
sendBroadcast(intent);
}
private void notifyReliableWriteCompleted() {
+ showMessage("Reliable write compelte");
Intent intent = new Intent(BLE_RELIABLE_WRITE_COMPLETED);
sendBroadcast(intent);
}
private void notifyReadRemoteRssi(int rssi) {
+ showMessage("Remote rssi read: " + rssi);
Intent intent = new Intent(BLE_READ_REMOTE_RSSI);
intent.putExtra(EXTRA_RSSI_VALUE, rssi);
sendBroadcast(intent);
@@ -330,88 +290,159 @@
});
}
+ private void sleep(int millis) {
+ try {
+ Thread.sleep(millis);
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Error in thread sleep", e);
+ }
+ }
+
+ private void reliableWrite() {
+ mBluetoothGatt.beginReliableWrite();
+ sleep(1000);
+ writeCharacteristic(WRITE_VALUE);
+ sleep(1000);
+ if (!mBluetoothGatt.executeReliableWrite()) {
+ Log.w(TAG, "reliable write failed");
+ }
+ sleep(1000);
+ mBluetoothGatt.abortReliableWrite();
+ }
+
private final BluetoothGattCallback mGattCallbacks = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (DEBUG) Log.d(TAG, "onConnectionStateChange");
if (status == BluetoothGatt.GATT_SUCCESS) {
- if (newState == BluetoothProfile.STATE_CONNECTED) notifyConnected();
- else if (status == BluetoothProfile.STATE_DISCONNECTED) {
+ if (newState == BluetoothProfile.STATE_CONNECTED) {
+ notifyConnected();
+ stopScan();
+ sleep(1000);
+ mBluetoothGatt.discoverServices();
+ } else if (status == BluetoothProfile.STATE_DISCONNECTED) {
notifyDisconnected();
- showMessage("Bluetooth LE disconnected");
}
+ } else {
+ showMessage("Failed to connect");
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
+ if (DEBUG) Log.d(TAG, "onServiceDiscovered");
if ((status == BluetoothGatt.GATT_SUCCESS) &&
(mBluetoothGatt.getService(SERVICE_UUID) != null)) {
notifyServicesDiscovered();
- }
- }
-
- @Override
- public void onCharacteristicRead(BluetoothGatt gatt,
- BluetoothGattCharacteristic characteristic, int status) {
- if ((status == BluetoothGatt.GATT_SUCCESS) &&
- (characteristic.getUuid().equals(CHARACTERISTIC_UUID))) {
- notifyCharacteristicRead(characteristic.getStringValue(0));
+ sleep(1000);
+ writeCharacteristic(WRITE_VALUE);
}
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
+ String value = characteristic.getStringValue(0);
if (DEBUG) Log.d(TAG, "onCharacteristicWrite: characteristic.val="
- + characteristic.getStringValue(0) + " status=" + status);
+ + value + " status=" + status);
BluetoothGattCharacteristic mCharacteristic = getCharacteristic(CHARACTERISTIC_UUID);
if ((status == BluetoothGatt.GATT_SUCCESS) &&
- (characteristic.getStringValue(0).equals(mCharacteristic.getStringValue(0)))) {
- notifyCharacteristicWrite();
+ (value.equals(mCharacteristic.getStringValue(0)))) {
+ notifyCharacteristicWrite(value);
+ sleep(1000);
+ readCharacteristic();
+ } else {
+ notifyError("Failed to write characteristic: " + value);
}
}
@Override
- public void onCharacteristicChanged(BluetoothGatt gatt,
- BluetoothGattCharacteristic characteristic) {
- if (characteristic.getUuid().equals(UPDATE_CHARACTERISTIC_UUID))
- notifyCharacteristicChanged(characteristic.getStringValue(0));
- }
-
- @Override
- public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
- int status) {
+ public void onCharacteristicRead(BluetoothGatt gatt,
+ BluetoothGattCharacteristic characteristic, int status) {
+ if (DEBUG) Log.d(TAG, "onCharacteristicRead");
if ((status == BluetoothGatt.GATT_SUCCESS) &&
- (descriptor.getUuid().equals(DESCRIPTOR_UUID))) {
- notifyDescriptorRead(new String(descriptor.getValue()));
+ (characteristic.getUuid().equals(CHARACTERISTIC_UUID))) {
+ notifyCharacteristicRead(characteristic.getStringValue(0));
+ sleep(1000);
+ writeDescriptor(WRITE_VALUE);
+ } else {
+ notifyError("Failed to read characteristic");
}
}
@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
int status) {
+ if (DEBUG) Log.d(TAG, "onDescriptorWrite");
if ((status == BluetoothGatt.GATT_SUCCESS) &&
(descriptor.getUuid().equals(DESCRIPTOR_UUID))) {
- notifyDescriptorWrite();
+ notifyDescriptorWrite(new String(descriptor.getValue()));
+ sleep(1000);
+ readDescriptor();
+ } else {
+ notifyError("Failed to write descriptor");
+ }
+ }
+
+ @Override
+ public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
+ int status) {
+ if (DEBUG) Log.d(TAG, "onDescriptorRead");
+ if ((status == BluetoothGatt.GATT_SUCCESS) &&
+ (descriptor.getUuid() != null) &&
+ (descriptor.getUuid().equals(DESCRIPTOR_UUID))) {
+ notifyDescriptorRead(new String(descriptor.getValue()));
+ sleep(1000);
+ setNotification(true);
+ } else {
+ notifyError("Failed to read descriptor");
+ }
+ }
+
+ @Override
+ public void onCharacteristicChanged(BluetoothGatt gatt,
+ BluetoothGattCharacteristic characteristic) {
+ if (DEBUG) Log.d(TAG, "onCharacteristicChanged");
+ if ((characteristic.getUuid() != null) &&
+ (characteristic.getUuid().equals(UPDATE_CHARACTERISTIC_UUID))) {
+ notifyCharacteristicChanged(characteristic.getStringValue(0));
+ setNotification(false);
+ sleep(1000);
+ mBluetoothGatt.readRemoteRssi();
}
}
@Override
public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
- if (status == BluetoothGatt.GATT_SUCCESS) notifyReliableWriteCompleted();
+ if (DEBUG) Log.d(TAG, "onReliableWriteComplete: " + status);
+ if (status == BluetoothGatt.GATT_SUCCESS) {
+ notifyReliableWriteCompleted();
+ } else {
+ notifyError("Failed to complete reliable write: " + status);
+ }
+ sleep(1000);
+ mBluetoothGatt.disconnect();
}
@Override
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
- if (status == BluetoothGatt.GATT_SUCCESS) notifyReadRemoteRssi(rssi);
+ if (DEBUG) Log.d(TAG, "onReadRemoteRssi");
+ if (status == BluetoothGatt.GATT_SUCCESS) {
+ notifyReadRemoteRssi(rssi);
+ } else {
+ notifyError("Failed to read remote rssi");
+ }
+ sleep(1000);
+ reliableWrite();
}
};
private final ScanCallback mScanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
- mBluetoothGatt = result.getDevice().connectGatt(mContext, false, mGattCallbacks);
+ if (mBluetoothGatt == null) {
+ mBluetoothGatt = result.getDevice().connectGatt(mContext, false, mGattCallbacks);
+ }
}
};
@@ -420,7 +451,7 @@
List<ScanFilter> filter = Arrays.asList(new ScanFilter.Builder().setServiceUuid(
new ParcelUuid(BleServerService.ADV_SERVICE_UUID)).build());
ScanSettings setting = new ScanSettings.Builder()
- .setScanMode(ScanSettings.SCAN_MODE_LOW_POWER).build();
+ .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
mScanner.startScan(filter, setting, mScanCallback);
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientStartActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientStartActivity.java
new file mode 100644
index 0000000..5a4e327
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientStartActivity.java
@@ -0,0 +1,147 @@
+/*
+ * 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.bluetooth;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+public class BleClientStartActivity extends PassFailButtons.Activity {
+
+ private TestAdapter mTestAdapter;
+ private int mAllPassed;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.ble_server_start);
+ setPassFailButtonClickListeners();
+ setInfoResources(R.string.ble_server_start_name,
+ R.string.ble_server_start_info, -1);
+ getPassButton().setEnabled(false);
+
+ mTestAdapter = new TestAdapter(this, setupTestList());
+ ListView listView = (ListView) findViewById(R.id.ble_server_tests);
+ listView.setAdapter(mTestAdapter);
+
+ mAllPassed = 0;
+ startService(new Intent(this, BleClientService.class));
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(BleClientService.BLE_BLUETOOTH_CONNECTED);
+ filter.addAction(BleClientService.BLE_BLUETOOTH_DISCONNECTED);
+ filter.addAction(BleClientService.BLE_SERVICES_DISCOVERED);
+ filter.addAction(BleClientService.BLE_CHARACTERISTIC_READ);
+ filter.addAction(BleClientService.BLE_CHARACTERISTIC_WRITE);
+ filter.addAction(BleClientService.BLE_CHARACTERISTIC_CHANGED);
+ filter.addAction(BleClientService.BLE_DESCRIPTOR_READ);
+ filter.addAction(BleClientService.BLE_DESCRIPTOR_WRITE);
+ filter.addAction(BleClientService.BLE_RELIABLE_WRITE_COMPLETED);
+ filter.addAction(BleClientService.BLE_READ_REMOTE_RSSI);
+ registerReceiver(onBroadcast, filter);
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ unregisterReceiver(onBroadcast);
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ stopService(new Intent(this, BleClientService.class));
+ }
+
+ private List<Integer> setupTestList() {
+ ArrayList<Integer> testList = new ArrayList<Integer>();
+ testList.add(R.string.ble_client_connect_name);
+ testList.add(R.string.ble_discover_service_name);
+ testList.add(R.string.ble_read_characteristic_name);
+ testList.add(R.string.ble_write_characteristic_name);
+ testList.add(R.string.ble_reliable_write_name);
+ testList.add(R.string.ble_notify_characteristic_name);
+ testList.add(R.string.ble_read_descriptor_name);
+ testList.add(R.string.ble_write_descriptor_name);
+ testList.add(R.string.ble_read_rssi_name);
+ testList.add(R.string.ble_client_disconnect_name);
+ return testList;
+ }
+
+ private BroadcastReceiver onBroadcast = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action == BleClientService.BLE_BLUETOOTH_CONNECTED) {
+ mTestAdapter.setTestPass(0);
+ mAllPassed |= 0x01;
+ } else if (action == BleClientService.BLE_SERVICES_DISCOVERED) {
+ mTestAdapter.setTestPass(1);
+ mAllPassed |= 0x02;
+ } else if (action == BleClientService.BLE_CHARACTERISTIC_READ) {
+ mTestAdapter.setTestPass(2);
+ mAllPassed |= 0x04;
+ } else if (action == BleClientService.BLE_CHARACTERISTIC_WRITE) {
+ mTestAdapter.setTestPass(3);
+ mAllPassed |= 0x08;
+ } else if (action == BleClientService.BLE_RELIABLE_WRITE_COMPLETED) {
+ mTestAdapter.setTestPass(4);
+ mAllPassed |= 0x10;
+ } else if (action == BleClientService.BLE_CHARACTERISTIC_CHANGED) {
+ mTestAdapter.setTestPass(5);
+ mAllPassed |= 0x20;
+ } else if (action == BleClientService.BLE_DESCRIPTOR_READ) {
+ mTestAdapter.setTestPass(6);
+ mAllPassed |= 0x40;
+ } else if (action == BleClientService.BLE_DESCRIPTOR_WRITE) {
+ mTestAdapter.setTestPass(7);
+ mAllPassed |= 0x80;
+ } else if (action == BleClientService.BLE_READ_REMOTE_RSSI) {
+ mTestAdapter.setTestPass(8);
+ mAllPassed |= 0x100;
+ } else if (action == BleClientService.BLE_BLUETOOTH_DISCONNECTED) {
+ mTestAdapter.setTestPass(9);
+ mAllPassed |= 0x200;
+ }
+ mTestAdapter.notifyDataSetChanged();
+ if (mAllPassed == 0x3FF) getPassButton().setEnabled(true);
+ }
+ };
+
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientTestActivity.java
deleted file mode 100644
index a13d934..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientTestActivity.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.verifier.bluetooth;
-
-import com.android.cts.verifier.ManifestTestListAdapter;
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-import android.os.Bundle;
-
-public class BleClientTestActivity extends PassFailButtons.TestListActivity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.pass_fail_list);
- setPassFailButtonClickListeners();
- setInfoResources(R.string.ble_client_test_name, R.string.ble_client_test_info, -1);
-
- setTestListAdapter(new ManifestTestListAdapter(this, getClass().getName()));
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleDiscoverServiceActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleDiscoverServiceActivity.java
deleted file mode 100644
index 6896b04..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleDiscoverServiceActivity.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.verifier.bluetooth;
-
-public class BleDiscoverServiceActivity extends BleButtonActivity {
- public BleDiscoverServiceActivity() {
- super(BleButtonActivity.DISCOVER_SERVICE);
- }
-}
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleNotifyCharacteristicActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleNotifyCharacteristicActivity.java
deleted file mode 100644
index e0c79bf..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleNotifyCharacteristicActivity.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.verifier.bluetooth;
-
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Bundle;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.TextView;
-import android.widget.Toast;
-
-public class BleNotifyCharacteristicActivity extends PassFailButtons.Activity {
-
- private boolean mEnable;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.ble_notify_characteristic);
- setPassFailButtonClickListeners();
- setInfoResources(R.string.ble_notify_characteristic_name,
- R.string.ble_notify_characteristic_info, -1);
-
- mEnable = false;
-
- ((Button) findViewById(R.id.ble_notify)).setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- mEnable = !mEnable;
- if (mEnable) ((Button) v).setText(getString(R.string.ble_stop_notification));
- else ((Button) v).setText(getString(R.string.ble_begin_notification));
-
- Intent intent = new Intent(BleNotifyCharacteristicActivity.this,
- BleClientService.class);
- intent.putExtra(BleClientService.EXTRA_COMMAND,
- BleClientService.COMMAND_SET_NOTIFICATION);
- intent.putExtra(BleClientService.EXTRA_BOOL, mEnable);
- startService(intent);
- }
- });
- }
-
- @Override
- public void onResume() {
- super.onResume();
- IntentFilter filter = new IntentFilter();
- filter.addAction(BleClientService.BLE_CHARACTERISTIC_CHANGED);
- registerReceiver(onBroadcast, filter);
- }
-
- @Override
- public void onPause() {
- super.onPause();
- unregisterReceiver(onBroadcast);
- mEnable = false;
- Intent intent = new Intent(BleNotifyCharacteristicActivity.this,
- BleClientService.class);
- intent.putExtra(BleClientService.EXTRA_COMMAND,
- BleClientService.COMMAND_SET_NOTIFICATION);
- intent.putExtra(BleClientService.EXTRA_BOOL, mEnable);
- startService(intent);
- }
-
- private BroadcastReceiver onBroadcast = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String value = intent.getStringExtra(BleClientService.EXTRA_CHARACTERISTIC_VALUE);
- ((TextView) findViewById(R.id.ble_notify_text)).setText(value);
- }
- };
-}
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleReadRssiActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleReadRssiActivity.java
deleted file mode 100644
index 800499c..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleReadRssiActivity.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.verifier.bluetooth;
-
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Bundle;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.TextView;
-import android.widget.Toast;
-
-public class BleReadRssiActivity extends PassFailButtons.Activity {
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.ble_read_rssi);
- setPassFailButtonClickListeners();
- setInfoResources(R.string.ble_read_rssi_name,
- R.string.ble_read_rssi_info, -1);
-
- ((Button) findViewById(R.id.ble_read_rssi)).setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(BleReadRssiActivity.this, BleClientService.class);
- intent.putExtra(BleClientService.EXTRA_COMMAND,
- BleClientService.COMMAND_READ_RSSI);
- startService(intent);
- }
- });
- }
-
- @Override
- public void onResume() {
- super.onResume();
- IntentFilter filter = new IntentFilter();
- filter.addAction(BleClientService.BLE_READ_REMOTE_RSSI);
- registerReceiver(onBroadcast, filter);
- }
-
- @Override
- public void onPause() {
- super.onPause();
- unregisterReceiver(onBroadcast);
- }
-
- private BroadcastReceiver onBroadcast = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- int rssi = intent.getIntExtra(BleClientService.EXTRA_RSSI_VALUE, 128);
- ((TextView) findViewById(R.id.ble_rssi_text)).setText(Integer.toString(rssi));
- }
- };
-}
\ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleReadWriteActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleReadWriteActivity.java
deleted file mode 100644
index 8041ce0..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleReadWriteActivity.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.verifier.bluetooth;
-
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Bundle;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.TextView;
-import android.widget.Toast;
-
-class BleReadWriteActivity extends PassFailButtons.Activity {
-
- static final int CHARACTERISTIC = 0;
- static final int DESCRIPTOR = 1;
-
- private int mWriteCommand;
- private int mReadCommand;
- private String mWriteFilter;
- private String mReadFilter;
- private String mExtraValue;
- private int mName;
- private EditText mEditText;
-
- BleReadWriteActivity(int target) {
- if (target == CHARACTERISTIC) {
- mWriteCommand = BleClientService.COMMAND_WRITE_CHARACTERISTIC;
- mReadCommand = BleClientService.COMMAND_READ_CHARACTERISTIC;
- mWriteFilter = BleClientService.BLE_CHARACTERISTIC_WRITE;
- mReadFilter = BleClientService.BLE_CHARACTERISTIC_READ;
- mExtraValue = BleClientService.EXTRA_CHARACTERISTIC_VALUE;
- mName = R.string.ble_client_characteristic_name;
- } else if (target == DESCRIPTOR) {
- mWriteCommand = BleClientService.COMMAND_WRITE_DESCRIPTOR;
- mReadCommand = BleClientService.COMMAND_READ_DESCRIPTOR;
- mWriteFilter = BleClientService.BLE_DESCRIPTOR_WRITE;
- mReadFilter = BleClientService.BLE_DESCRIPTOR_READ;
- mExtraValue = BleClientService.EXTRA_DESCRIPTOR_VALUE;
- mName = R.string.ble_client_descriptor_name;
- }
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.ble_client_read_write);
- setPassFailButtonClickListeners();
- setInfoResources(mName, R.string.ble_read_write_info, -1);
-
- mEditText = (EditText) findViewById(R.id.write_text);
-
- ((Button) findViewById(R.id.ble_write)).setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- String writeValue = mEditText.getText().toString();
- Intent intent = new Intent(BleReadWriteActivity.this, BleClientService.class);
- intent.putExtra(BleClientService.EXTRA_COMMAND, mWriteCommand);
- intent.putExtra(BleClientService.EXTRA_WRITE_VALUE, writeValue);
- startService(intent);
- mEditText.setText("");
- }
- });
-
- ((Button) findViewById(R.id.ble_read)).setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(BleReadWriteActivity.this, BleClientService.class);
- intent.putExtra(BleClientService.EXTRA_COMMAND, mReadCommand);
- startService(intent);
- }
- });
- }
-
- @Override
- public void onResume() {
- super.onResume();
- IntentFilter filter = new IntentFilter();
- filter.addAction(mReadFilter);
- filter.addAction(mWriteFilter);
- registerReceiver(onBroadcast, filter);
- }
-
- @Override
- public void onPause() {
- super.onPause();
- unregisterReceiver(onBroadcast);
- }
-
- private void showMessage(String msg) {
- Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
- }
-
- private BroadcastReceiver onBroadcast = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (action == mWriteFilter)
- showMessage("Write successful callback");
- else if (action == mReadFilter) {
- String value = intent.getStringExtra(mExtraValue);
- ((TextView) findViewById(R.id.read_text)).setText(value);
- }
- }
- };
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleReliableWriteActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleReliableWriteActivity.java
deleted file mode 100644
index 9b65bb4..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleReliableWriteActivity.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.verifier.bluetooth;
-
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Bundle;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.Toast;
-
-public class BleReliableWriteActivity extends PassFailButtons.Activity {
-
- EditText mEditText;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.ble_reliable_write);
- setPassFailButtonClickListeners();
- setInfoResources(R.string.ble_reliable_write_name, R.string.ble_reliable_write_info, -1);
- getPassButton().setEnabled(false);
- ((Button) findViewById(R.id.ble_execute)).setEnabled(false);
-
- mEditText = (EditText) findViewById(R.id.write_text);
-
- ((Button) findViewById(R.id.ble_begin)).setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(BleReliableWriteActivity.this, BleClientService.class);
- intent.putExtra(BleClientService.EXTRA_COMMAND,
- BleClientService.COMMAND_BEGIN_WRITE);
- startService(intent);
- }
- });
-
- ((Button) findViewById(R.id.ble_write)).setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- String writeValue = mEditText.getText().toString();
- Intent intent = new Intent(BleReliableWriteActivity.this, BleClientService.class);
- intent.putExtra(BleClientService.EXTRA_COMMAND,
- BleClientService.COMMAND_WRITE_CHARACTERISTIC);
- intent.putExtra(BleClientService.EXTRA_WRITE_VALUE, writeValue);
- startService(intent);
- mEditText.setText("");
- }
- });
-
- ((Button) findViewById(R.id.ble_execute)).setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(BleReliableWriteActivity.this, BleClientService.class);
- intent.putExtra(BleClientService.EXTRA_COMMAND,
- BleClientService.COMMAND_EXECUTE_WRITE);
- startService(intent);
- }
- });
- }
-
- @Override
- public void onResume() {
- super.onResume();
- IntentFilter filter = new IntentFilter();
- filter.addAction(BleClientService.BLE_CHARACTERISTIC_WRITE);
- filter.addAction(BleClientService.BLE_RELIABLE_WRITE_COMPLETED);
- registerReceiver(onBroadcast, filter);
- }
-
- @Override
- public void onPause() {
- super.onPause();
- unregisterReceiver(onBroadcast);
- Intent intent = new Intent(this, BleClientService.class);
- intent.putExtra(BleClientService.EXTRA_COMMAND, BleClientService.COMMAND_ABORT_RELIABLE);
- startService(intent);
- }
-
- private void showMessage(String msg) {
- Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
- }
-
- private BroadcastReceiver onBroadcast = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (action == BleClientService.BLE_CHARACTERISTIC_WRITE) {
- showMessage("Write value verified.");
- ((Button) findViewById(R.id.ble_execute)).setEnabled(true);
- } else if (action == BleClientService.BLE_RELIABLE_WRITE_COMPLETED) {
- showMessage("Reliable write completed.");
- getPassButton().setEnabled(true);
- }
- }
- };
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerService.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerService.java
index d3d96ac..eb71164 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerService.java
@@ -170,7 +170,7 @@
if (serviceData.get(new ParcelUuid(BleAdvertiserService.POWER_LEVEL_UUID)) != null) {
byte[] data =
serviceData.get(new ParcelUuid(BleAdvertiserService.POWER_LEVEL_UUID));
- if (data.length == 3) {
+ if (data.length == BleAdvertiserService.POWER_LEVEL_DATA.length) {
Intent powerIntent = new Intent(BLE_POWER_LEVEL);
powerIntent.putExtra(EXTRA_MAC_ADDRESS, result.getDevice().getAddress());
powerIntent.putExtra(EXTRA_POWER_LEVEL, record.getTxPowerLevel());
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerTestActivity.java
index 1f54917..52933e0 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleScannerTestActivity.java
@@ -20,8 +20,12 @@
import com.android.cts.verifier.PassFailButtons;
import com.android.cts.verifier.R;
+import android.bluetooth.BluetoothAdapter;
import android.os.Bundle;
+import java.util.ArrayList;
+import java.util.List;
+
public class BleScannerTestActivity extends PassFailButtons.TestListActivity {
@Override
@@ -31,6 +35,14 @@
setPassFailButtonClickListeners();
setInfoResources(R.string.ble_scanner_test_name,
R.string.ble_scanner_test_info, -1);
- setTestListAdapter(new ManifestTestListAdapter(this, getClass().getName()));
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ List<String> disabledTest = new ArrayList<String>();
+ if (adapter == null || !adapter.isOffloadedFilteringSupported()) {
+ disabledTest.add(
+ "com.android.cts.verifier.bluetooth.BleScannerHardwareScanFilterActivity");
+ }
+
+ setTestListAdapter(new ManifestTestListAdapter(this, getClass().getName(),
+ disabledTest.toArray(new String[disabledTest.size()])));
}
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BluetoothTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BluetoothTestActivity.java
index 56d73aa..df70984 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BluetoothTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BluetoothTestActivity.java
@@ -60,6 +60,8 @@
"com.android.cts.verifier.bluetooth.BleAdvertiserTestActivity");
disabledTestArray.add(
"com.android.cts.verifier.bluetooth.BleServerStartActivity");
+ disabledTestArray.add(
+ "com.android.cts.verifier.bluetooth.BleScannerTestActivity");
}
setTestListAdapter(new ManifestTestListAdapter(this, getClass().getName(),
disabledTestArray.toArray(new String[disabledTestArray.size()])));
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/TestAdapter.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/TestAdapter.java
index 631fe36..8f4ed56 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/TestAdapter.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/TestAdapter.java
@@ -80,7 +80,7 @@
if (convertView != null) {
vg = (ViewGroup) convertView;
} else {
- vg = (ViewGroup) inflater.inflate(R.layout.ble_server_start_item, null);
+ vg = (ViewGroup) inflater.inflate(R.layout.ble_test_item, null);
}
Test test = tests.get(position);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
index a305cd2..e3d0b6d 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
@@ -544,6 +544,8 @@
doCapture(cmdObj);
} else if ("doVibrate".equals(cmdObj.getString("cmdName"))) {
doVibrate(cmdObj);
+ } else if ("getCameraIds".equals(cmdObj.getString("cmdName"))) {
+ doGetCameraIds();
} else {
throw new ItsException("Unknown command: " + cmd);
}
@@ -729,6 +731,38 @@
mSocketRunnableObj.sendResponse(mCameraCharacteristics);
}
+ private void doGetCameraIds() throws ItsException {
+ String[] devices;
+ try {
+ devices = mCameraManager.getCameraIdList();
+ if (devices == null || devices.length == 0) {
+ throw new ItsException("No camera devices");
+ }
+ } catch (CameraAccessException e) {
+ throw new ItsException("Failed to get device ID list", e);
+ }
+
+ try {
+ JSONObject obj = new JSONObject();
+ JSONArray array = new JSONArray();
+ for (String id : devices) {
+ CameraCharacteristics characteristics = mCameraManager.getCameraCharacteristics(id);
+ // Only supply camera Id for non-legacy cameras since legacy camera does not
+ // support ITS
+ if (characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL) !=
+ CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) {
+ array.put(id);
+ }
+ }
+ obj.put("cameraIdArray", array);
+ mSocketRunnableObj.sendResponse("cameraIds", obj);
+ } catch (org.json.JSONException e) {
+ throw new ItsException("JSON error: ", e);
+ } catch (android.hardware.camera2.CameraAccessException e) {
+ throw new ItsException("Access error: ", e);
+ }
+ }
+
private void prepareCaptureReader(int[] widths, int[] heights, int formats[], int numSurfaces) {
if (mCaptureReaders != null) {
for (int i = 0; i < mCaptureReaders.length; i++) {
@@ -822,8 +856,10 @@
doAF = triggers.getBoolean(TRIGGER_AF_KEY);
}
}
- if (doAF && mCameraCharacteristics.get(
- CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE) == 0) {
+ Float minFocusDistance = mCameraCharacteristics.get(
+ CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE);
+ boolean isFixedFocusLens = minFocusDistance != null && minFocusDistance == 0.0;
+ if (doAF && isFixedFocusLens) {
// Send a dummy result back for the code that is waiting for this message to see
// that AF has converged.
Logt.i(TAG, "Ignoring request for AF on fixed-focus camera");
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java
index 12b9bfc..1fdd044 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java
@@ -27,9 +27,19 @@
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
-import java.util.HashSet;
-import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.HashMap;
+import java.util.Arrays;
+import java.util.List;
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+import com.android.compatibility.common.util.ResultType;
+import com.android.compatibility.common.util.ResultUnit;
import com.android.cts.verifier.PassFailButtons;
import com.android.cts.verifier.R;
@@ -41,7 +51,9 @@
*/
public class ItsTestActivity extends PassFailButtons.Activity {
private static final String TAG = "ItsTestActivity";
+ private static final String EXTRA_CAMERA_ID = "camera.its.extra.CAMERA_ID";
private static final String EXTRA_SUCCESS = "camera.its.extra.SUCCESS";
+ private static final String EXTRA_SUMMARY = "camera.its.extra.SUMMARY";
private static final String ACTION_ITS_RESULT =
"com.android.cts.verifier.camera.its.ACTION_ITS_RESULT";
@@ -50,20 +62,32 @@
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "Received result for Camera ITS tests");
if (ACTION_ITS_RESULT.equals(intent.getAction())) {
+ String cameraId = intent.getStringExtra(EXTRA_CAMERA_ID);
String result = intent.getStringExtra(EXTRA_SUCCESS);
- String[] parts = result.split("=");
- if (parts.length != 2) {
- Toast.makeText(ItsTestActivity.this,
- "Received unknown ITS result string: " + result,
- Toast.LENGTH_SHORT).show();
+ String summaryPath = intent.getStringExtra(EXTRA_SUMMARY);
+ if (!mNonLegacyCameraIds.contains(cameraId)) {
+ Log.e(TAG, "Unknown camera id " + cameraId + " reported to ITS");
+ return;
}
- String cameraId = parts[0];
- boolean pass = parts[1].equals("True");
+
+ Log.i(TAG, "ITS summary path is: " + summaryPath);
+ mSummaryMap.put(cameraId, summaryPath);
+ // Create summary report
+ if (mSummaryMap.keySet().containsAll(mNonLegacyCameraIds)) {
+ StringBuilder summary = new StringBuilder();
+ for (String id : mNonLegacyCameraIds) {
+ String path = mSummaryMap.get(id);
+ appendFileContentToSummary(summary, path);
+ }
+ ItsTestActivity.this.getReportLog().setSummary(
+ summary.toString(), 1.0, ResultType.NEUTRAL, ResultUnit.NONE);
+ }
+ boolean pass = result.equals("True");
if(pass) {
Log.i(TAG, "Received Camera " + cameraId + " ITS SUCCESS from host.");
mITSPassedCameraIds.add(cameraId);
- if (mCameraIds != null &&
- mITSPassedCameraIds.containsAll(Arrays.asList(mCameraIds))) {
+ if (mNonLegacyCameraIds != null && mNonLegacyCameraIds.size() != 0 &&
+ mITSPassedCameraIds.containsAll(mNonLegacyCameraIds)) {
ItsTestActivity.this.showToast(R.string.its_test_passed);
ItsTestActivity.this.getPassButton().setEnabled(true);
}
@@ -73,11 +97,40 @@
}
}
}
+
+ private void appendFileContentToSummary(StringBuilder summary, String path) {
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new FileReader(path));
+ String line = null;
+ do {
+ line = reader.readLine();
+ if (line != null) {
+ summary.append(line);
+ }
+ } while (line != null);
+ } catch (FileNotFoundException e) {
+ Log.e(TAG, "Cannot find ITS summary file at " + path);
+ summary.append("Cannot find ITS summary file at " + path);
+ } catch (IOException e) {
+ Log.e(TAG, "IO exception when trying to read " + path);
+ summary.append("IO exception when trying to read " + path);
+ } finally {
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ }
}
private final SuccessReceiver mSuccessReceiver = new SuccessReceiver();
private final HashSet<String> mITSPassedCameraIds = new HashSet<>();
- private String[] mCameraIds = null;
+ // map camera id to ITS summary report path
+ private final HashMap<String, String> mSummaryMap = new HashMap<>();
+ ArrayList<String> mNonLegacyCameraIds = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -85,6 +138,33 @@
setContentView(R.layout.its_main);
setInfoResources(R.string.camera_its_test, R.string.camera_its_test_info, -1);
setPassFailButtonClickListeners();
+
+ // Hide the test if all camera devices are legacy
+ CameraManager manager = (CameraManager) this.getSystemService(Context.CAMERA_SERVICE);
+ try {
+ String[] cameraIds = manager.getCameraIdList();
+ mNonLegacyCameraIds = new ArrayList<String>();
+ boolean allCamerasAreLegacy = true;
+ for (String id : cameraIds) {
+ CameraCharacteristics characteristics = manager.getCameraCharacteristics(id);
+ if (characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL)
+ != CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) {
+ mNonLegacyCameraIds.add(id);
+ allCamerasAreLegacy = false;
+ }
+ }
+ if (allCamerasAreLegacy) {
+ showToast(R.string.all_legacy_devices);
+ ItsTestActivity.this.getReportLog().setSummary(
+ "PASS: all cameras on this device are LEGACY"
+ , 1.0, ResultType.NEUTRAL, ResultUnit.NONE);
+ setTestResultAndFinish(true);
+ }
+ } catch (CameraAccessException e) {
+ Toast.makeText(ItsTestActivity.this,
+ "Received error from camera service while checking device capabilities: "
+ + e, Toast.LENGTH_SHORT).show();
+ }
getPassButton().setEnabled(false);
}
@@ -95,26 +175,7 @@
if (manager == null) {
showToast(R.string.no_camera_manager);
} else {
- try {
- mCameraIds = manager.getCameraIdList();
- boolean allCamerasAreLegacy = true;
- for (String id : mCameraIds) {
- CameraCharacteristics characteristics = manager.getCameraCharacteristics(id);
- if (characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL)
- != CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY) {
- allCamerasAreLegacy = false;
- break;
- }
- }
- if (allCamerasAreLegacy) {
- showToast(R.string.all_legacy_devices);
- getPassButton().setEnabled(false);
- }
- } catch (CameraAccessException e) {
- Toast.makeText(ItsTestActivity.this,
- "Received error from camera service while checking device capabilities: "
- + e, Toast.LENGTH_SHORT).show();
- }
+ Log.d(TAG, "register ITS result receiver");
IntentFilter filter = new IntentFilter(ACTION_ITS_RESULT);
registerReceiver(mSuccessReceiver, filter);
}
@@ -123,6 +184,7 @@
@Override
protected void onPause() {
super.onPause();
+ Log.d(TAG, "unregister ITS result receiver");
unregisterReceiver(mSuccessReceiver);
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureSummaryActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureSummaryActivity.java
index 105e92b..36acf42 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureSummaryActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureSummaryActivity.java
@@ -221,7 +221,7 @@
new Feature(PackageManager.FEATURE_VERIFIED_BOOT, false),
// Features explicitly made optional in L
- new Feature("PackageManager.FEATURE_LOCATION_NETWORK", false),
+ new Feature(PackageManager.FEATURE_LOCATION_NETWORK, false),
// New hidden features in L
new Feature("android.hardware.ethernet", false),
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
index 057d00d..c1cc1f9 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
@@ -17,14 +17,12 @@
package com.android.cts.verifier.managedprovisioning;
import android.app.AlertDialog;
-import android.app.Dialog;
import android.app.admin.DevicePolicyManager;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.provider.Settings;
@@ -64,20 +62,26 @@
private ComponentName mAdminReceiverComponent;
- private TestAdapter mAdapter;
+ private TestAdapter mTestListAdapter;
private View mStartProvisioningButton;
private List<TestItem> mTests = new ArrayList<TestItem>();
protected DevicePolicyManager mDevicePolicyManager;
private TestItem mProfileOwnerInstalled;
- private TestItem mProfileVisibleTest;
+ private TestItem mProfileAccountVisibleTest;
private TestItem mDeviceAdminVisibleTest;
private TestItem mWorkAppVisibleTest;
private TestItem mCrossProfileIntentFiltersTest;
private TestItem mDisableNonMarketTest;
private TestItem mEnableNonMarketTest;
private TestItem mWorkNotificationBadgedTest;
+ private TestItem mAppSettingsVisibleTest;
+ private TestItem mLocationSettingsVisibleTest;
+ private TestItem mCredSettingsVisibleTest;
+ private TestItem mPrintSettingsVisibleTest;
+
+ private int mCurrentTestPosition;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -94,9 +98,11 @@
setupTests();
- mAdapter = new TestAdapter(this);
- setListAdapter(mAdapter);
- mAdapter.addAll(mTests);
+ mTestListAdapter = new TestAdapter(this);
+ setListAdapter(mTestListAdapter);
+ mTestListAdapter.addAll(mTests);
+
+ mCurrentTestPosition = 0;
mStartProvisioningButton = findViewById(R.id.byod_start);
mStartProvisioningButton.setOnClickListener(new OnClickListener() {
@@ -159,21 +165,13 @@
}
};
- mProfileVisibleTest = new TestItem(this, R.string.provisioning_byod_profile_visible,
- R.string.provisioning_byod_profile_visible_instruction,
- new Intent(Settings.ACTION_SETTINGS));
-
- mDeviceAdminVisibleTest = new TestItem(this, R.string.provisioning_byod_admin_visible,
- R.string.provisioning_byod_admin_visible_instruction,
- new Intent(Settings.ACTION_SECURITY_SETTINGS));
-
/*
* To keep the image in this test up to date, use the instructions in
* {@link ByodIconSamplerActivity}.
*/
mWorkAppVisibleTest = new TestItemWithIcon(this,
R.string.provisioning_byod_workapps_visible,
- R.string.provisioning_byod_profile_visible_instruction,
+ R.string.provisioning_byod_workapps_visible_instruction,
new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME),
R.drawable.badged_icon);
@@ -193,18 +191,53 @@
new Intent(ByodHelperActivity.ACTION_INSTALL_APK)
.putExtra(ByodHelperActivity.EXTRA_ALLOW_NON_MARKET_APPS, true));
+ mProfileAccountVisibleTest = new TestItem(this, R.string.provisioning_byod_profile_visible,
+ R.string.provisioning_byod_profile_visible_instruction,
+ new Intent(Settings.ACTION_SETTINGS));
+
+ mAppSettingsVisibleTest = new TestItem(this, R.string.provisioning_byod_app_settings,
+ R.string.provisioning_byod_app_settings_instruction,
+ new Intent(Settings.ACTION_APPLICATION_SETTINGS));
+
+ mDeviceAdminVisibleTest = new TestItem(this, R.string.provisioning_byod_admin_visible,
+ R.string.provisioning_byod_admin_visible_instruction,
+ new Intent(Settings.ACTION_SECURITY_SETTINGS));
+
+ mCredSettingsVisibleTest = new TestItem(this, R.string.provisioning_byod_cred_settings,
+ R.string.provisioning_byod_cred_settings_instruction,
+ new Intent(Settings.ACTION_SECURITY_SETTINGS));
+
+ mLocationSettingsVisibleTest = new TestItem(this,
+ R.string.provisioning_byod_location_settings,
+ R.string.provisioning_byod_location_settings_instruction,
+ new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
+
+ mPrintSettingsVisibleTest = new TestItem(this, R.string.provisioning_byod_print_settings,
+ R.string.provisioning_byod_print_settings_instruction,
+ new Intent(Settings.ACTION_PRINT_SETTINGS));
+
Intent intent = new Intent(CrossProfileTestActivity.ACTION_CROSS_PROFILE);
- Intent chooser = Intent.createChooser(intent, getResources().getString(R.string.provisioning_cross_profile_chooser));
+ Intent chooser = Intent.createChooser(intent,
+ getResources().getString(R.string.provisioning_cross_profile_chooser));
mCrossProfileIntentFiltersTest = new TestItem(this,
R.string.provisioning_byod_cross_profile,
R.string.provisioning_byod_cross_profile_instruction,
chooser);
mTests.add(mProfileOwnerInstalled);
- mTests.add(mProfileVisibleTest);
- mTests.add(mDeviceAdminVisibleTest);
+
+ // Badge related tests
mTests.add(mWorkAppVisibleTest);
mTests.add(mWorkNotificationBadgedTest);
+
+ // Settings related tests.
+ mTests.add(mProfileAccountVisibleTest);
+ mTests.add(mDeviceAdminVisibleTest);
+ mTests.add(mCredSettingsVisibleTest);
+ mTests.add(mAppSettingsVisibleTest);
+ mTests.add(mLocationSettingsVisibleTest);
+ mTests.add(mPrintSettingsVisibleTest);
+
mTests.add(mCrossProfileIntentFiltersTest);
mTests.add(mDisableNonMarketTest);
mTests.add(mEnableNonMarketTest);
@@ -213,6 +246,7 @@
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
+ mCurrentTestPosition = position;
TestItem test = (TestItem) getListAdapter().getItem(position);
test.performTest(this);
}
@@ -242,13 +276,20 @@
} else {
dialogBuilder.setMessage(test.getManualTestInstruction());
}
- AlertDialog dialog = dialogBuilder.show();
+ final AlertDialog dialog = dialogBuilder.show();
// Note: Setting the OnClickListener on the Dialog rather than the Builder, prevents the
// dialog being dismissed on onClick.
dialog.getButton(AlertDialog.BUTTON_NEUTRAL).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
- ByodFlowTestActivity.this.startActivity(test.getManualTestIntent());
+ try {
+ ByodFlowTestActivity.this.startActivity(test.getManualTestIntent());
+ } catch (ActivityNotFoundException e) {
+ Toast.makeText(ByodFlowTestActivity.this,
+ "Cannot start " + test.getManualTestIntent(), Toast.LENGTH_LONG).show();
+ setTestResult(test, TestResult.Failed);
+ dialog.dismiss();
+ }
}
});
}
@@ -256,8 +297,12 @@
private void clearRemainingState(final TestItem test) {
if (WorkNotificationTestActivity.ACTION_WORK_NOTIFICATION.equals(
test.getManualTestIntent().getAction())) {
- ByodFlowTestActivity.this.startActivity(new Intent(
- WorkNotificationTestActivity.ACTION_CLEAR_WORK_NOTIFICATION));
+ try {
+ ByodFlowTestActivity.this.startActivity(new Intent(
+ WorkNotificationTestActivity.ACTION_CLEAR_WORK_NOTIFICATION));
+ } catch (ActivityNotFoundException e) {
+ // User shouldn't run this test before work profile is set up.
+ }
}
}
@@ -269,7 +314,9 @@
testSucceeds &= (aTest.getPassFailState() == TestResult.Passed);
}
getPassButton().setEnabled(testSucceeds);
- mAdapter.notifyDataSetChanged();
+ mTestListAdapter.notifyDataSetChanged();
+
+ this.getListView().smoothScrollToPosition(mCurrentTestPosition + 1);
}
private void startByodProvisioning() {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/screenpinning/ScreenPinningTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/screenpinning/ScreenPinningTestActivity.java
new file mode 100644
index 0000000..200865e
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/screenpinning/ScreenPinningTestActivity.java
@@ -0,0 +1,242 @@
+/*
+ * 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.verifier.screenpinning;
+
+import android.app.ActivityManager;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
+public class ScreenPinningTestActivity extends PassFailButtons.Activity {
+
+ private static final String TAG = "ScreenPinningTestActivity";
+ private static final String KEY_CURRENT_TEST = "keyCurrentTest";
+
+ private Test[] mTests;
+ private int mTestIndex;
+
+ private ActivityManager mActivityManager;
+ private Button mNextButton;
+ private LinearLayout mInstructions;
+
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.screen_pinning);
+ setPassFailButtonClickListeners();
+
+ mTests = new Test[] {
+ // Verify not already pinned.
+ mCheckStartedUnpinned,
+ // Enter pinning, verify pinned, try leaving and have the user exit.
+ mCheckStartPinning,
+ mCheckIsPinned,
+ mCheckTryLeave,
+ mCheckUnpin,
+ // Enter pinning, verify pinned, and use APIs to exit.
+ mCheckStartPinning,
+ mCheckIsPinned,
+ mCheckUnpinFromCode,
+ // All done.
+ mDone,
+ };
+
+ mActivityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
+ mInstructions = (LinearLayout) findViewById(R.id.instructions_list);
+
+ mNextButton = (Button) findViewById(R.id.next_button);
+ mNextButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if ((mTestIndex >= 0) && (mTestIndex < mTests.length)) {
+ mTests[mTestIndex].onNextClick();
+ }
+ }
+ });
+
+ // Don't allow pass until all tests complete.
+ findViewById(R.id.pass_button).setVisibility(View.GONE);
+
+ // Figure out if we are in a test or starting from the beginning.
+ if (savedInstanceState != null && savedInstanceState.containsKey(KEY_CURRENT_TEST)) {
+ mTestIndex = savedInstanceState.getInt(KEY_CURRENT_TEST);
+ } else {
+ mTestIndex = 0;
+ }
+ // Display any pre-existing text.
+ for (int i = 0; i < mTestIndex; i++) {
+ mTests[i].showText();
+ }
+ mTests[mTestIndex].run();
+ };
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ outState.putInt(KEY_CURRENT_TEST, mTestIndex);
+ }
+
+ @Override
+ public void onBackPressed() {
+ // Block back button so we can test screen pinning exit functionality.
+ // Users can still leave by pressing fail (or when done the pass) button.
+ }
+
+ private void show(int id) {
+ TextView tv = new TextView(this);
+ tv.setPadding(10, 10, 10, 30);
+ tv.setText(id);
+ mInstructions.addView(tv);
+ }
+
+ private void succeed() {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mTestIndex++;
+ if (mTestIndex < mTests.length) {
+ mTests[mTestIndex].run();
+ } else {
+ mNextButton.setVisibility(View.GONE);
+ findViewById(R.id.pass_button).setVisibility(View.VISIBLE);
+ }
+ }
+ });
+ }
+
+ private void error(int errorId) {
+ error(errorId, new Throwable());
+ }
+
+ private void error(final int errorId, final Throwable cause) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ String error = getString(errorId);
+ Log.d(TAG, error, cause);
+ // No more instructions needed.
+ findViewById(R.id.instructions_group).setVisibility(View.GONE);
+
+ ((TextView) findViewById(R.id.error_text)).setText(error);
+ }
+ });
+ }
+
+ // Verify we don't start in screen pinning.
+ private final Test mCheckStartedUnpinned = new Test(0) {
+ public void run() {
+ if (mActivityManager.isInLockTaskMode()) {
+ error(R.string.error_screen_already_pinned);
+ } else {
+ succeed();
+ }
+ }
+ };
+
+ // Start screen pinning by having the user click next then confirm it for us.
+ private final Test mCheckStartPinning = new Test(R.string.screen_pin_instructions) {
+ protected void onNextClick() {
+ startLockTask();
+ succeed();
+ }
+ };
+
+ // Click next and check that we got pinned.
+ // Wait for the user to click next to verify that they got back from the prompt
+ // successfully.
+ private final Test mCheckIsPinned = new Test(R.string.screen_pin_check_pinned) {
+ protected void onNextClick() {
+ if (mActivityManager.isInLockTaskMode()) {
+ succeed();
+ } else {
+ error(R.string.error_screen_pinning_did_not_start);
+ }
+ }
+ };
+
+ // Tell user to try to leave.
+ private final Test mCheckTryLeave = new Test(R.string.screen_pin_no_exit) {
+ protected void onNextClick() {
+ if (mActivityManager.isInLockTaskMode()) {
+ succeed();
+ } else {
+ error(R.string.error_screen_no_longer_pinned);
+ }
+ }
+ };
+
+ // Verify that the user unpinned and it worked.
+ private final Test mCheckUnpin = new Test(R.string.screen_pin_exit) {
+ protected void onNextClick() {
+ if (!mActivityManager.isInLockTaskMode()) {
+ succeed();
+ } else {
+ error(R.string.error_screen_pinning_did_not_exit);
+ }
+ }
+ };
+
+ // Unpin from code and check that it worked.
+ private final Test mCheckUnpinFromCode = new Test(0) {
+ protected void run() {
+ if (!mActivityManager.isInLockTaskMode()) {
+ error(R.string.error_screen_pinning_did_not_start);
+ return;
+ }
+ stopLockTask();
+ if (!mActivityManager.isInLockTaskMode()) {
+ succeed();
+ } else {
+ error(R.string.error_screen_pinning_couldnt_exit);
+ }
+ };
+ };
+
+ private final Test mDone = new Test(R.string.screen_pinning_done) {
+ protected void run() {
+ showText();
+ succeed();
+ };
+ };
+
+ private abstract class Test {
+ private final int mResId;
+
+ public Test(int showId) {
+ mResId = showId;
+ }
+
+ protected void run() {
+ showText();
+ }
+
+ public void showText() {
+ if (mResId == 0) {
+ return;
+ }
+ show(mResId);
+ }
+
+ protected void onNextClick() {
+ }
+ }
+
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputService.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputService.java
new file mode 100644
index 0000000..f4460de
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputService.java
@@ -0,0 +1,325 @@
+/*
+ * 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/bluetooth/BleClientDisconnectActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputSettingsActivity.java
similarity index 68%
rename from apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientDisconnectActivity.java
rename to apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputSettingsActivity.java
index 083d327..4231db7 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleClientDisconnectActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputSettingsActivity.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * 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.
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-package com.android.cts.verifier.bluetooth;
+package com.android.cts.verifier.tv;
-public class BleClientDisconnectActivity extends BleButtonActivity {
- public BleClientDisconnectActivity() {
- super(BleButtonActivity.DISCONNECT);
- }
-}
\ No newline at end of file
+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
new file mode 100644
index 0000000..81a8edc
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/MockTvInputSetupActivity.java
@@ -0,0 +1,82 @@
+/*
+ * 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
new file mode 100644
index 0000000..66af4c6
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/MultipleTracksTestActivity.java
@@ -0,0 +1,154 @@
+/*
+ * 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
new file mode 100644
index 0000000..284b485
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/ParentalControlTestActivity.java
@@ -0,0 +1,149 @@
+/*
+ * 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
new file mode 100644
index 0000000..3529237
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvAppVerifierActivity.java
@@ -0,0 +1,113 @@
+/*
+ * 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
new file mode 100644
index 0000000..3d17a1a
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/TvInputDiscoveryTestActivity.java
@@ -0,0 +1,123 @@
+/*
+ * 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/build/test_host_java_library.mk b/build/test_host_java_library.mk
index baf9e75..8e071e4 100644
--- a/build/test_host_java_library.mk
+++ b/build/test_host_java_library.mk
@@ -21,14 +21,18 @@
cts_library_xml := $(CTS_TESTCASES_OUT)/$(LOCAL_MODULE).xml
-$(cts_library_xml): PRIVATE_PATH := $(LOCAL_PATH)/src
+cts_src_dirs := $(LOCAL_PATH)/src
+cts_src_dirs += $(sort $(dir $(LOCAL_GENERATED_SOURCES)))
+cts_src_dirs := $(addprefix -s , $(cts_src_dirs))
+
+$(cts_library_xml): PRIVATE_SRC_DIRS := $(cts_src_dirs)
$(cts_library_xml): PRIVATE_TEST_PACKAGE := $(LOCAL_CTS_TEST_PACKAGE)
$(cts_library_xml): PRIVATE_LIBRARY := $(LOCAL_MODULE)
$(cts_library_xml): PRIVATE_JAR_PATH := $(LOCAL_MODULE).jar
$(cts_library_xml): $(HOST_OUT_JAVA_LIBRARIES)/$(LOCAL_MODULE).jar $(CTS_EXPECTATIONS) $(CTS_UNSUPPORTED_ABIS) $(CTS_JAVA_TEST_SCANNER_DOCLET) $(CTS_JAVA_TEST_SCANNER) $(CTS_XML_GENERATOR)
$(hide) echo Generating test description for host library $(PRIVATE_LIBRARY)
$(hide) mkdir -p $(CTS_TESTCASES_OUT)
- $(hide) $(CTS_JAVA_TEST_SCANNER) -s $(PRIVATE_PATH) \
+ $(hide) $(CTS_JAVA_TEST_SCANNER) $(PRIVATE_SRC_DIRS) \
-d $(CTS_JAVA_TEST_SCANNER_DOCLET) | \
$(CTS_XML_GENERATOR) -t hostSideOnly \
-j $(PRIVATE_JAR_PATH) \
diff --git a/build/test_package.mk b/build/test_package.mk
index 353ae07..72972b2 100644
--- a/build/test_package.mk
+++ b/build/test_package.mk
@@ -28,12 +28,16 @@
cts_package_apk := $(CTS_TESTCASES_OUT)/$(LOCAL_PACKAGE_NAME).apk
cts_package_xml := $(CTS_TESTCASES_OUT)/$(LOCAL_PACKAGE_NAME).xml
+cts_src_dirs := $(LOCAL_PATH)
+cts_src_dirs += $(sort $(dir $(LOCAL_GENERATED_SOURCES)))
+cts_src_dirs := $(addprefix -s , $(cts_src_dirs))
+
$(cts_package_apk): PRIVATE_PACKAGE := $(LOCAL_PACKAGE_NAME)
$(cts_package_apk): $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME))/package.apk | $(ACP)
$(hide) mkdir -p $(CTS_TESTCASES_OUT)
$(hide) $(ACP) -fp $(call intermediates-dir-for,APPS,$(PRIVATE_PACKAGE))/package.apk $@
-$(cts_package_xml): PRIVATE_PATH := $(LOCAL_PATH)
+$(cts_package_xml): PRIVATE_SRC_DIRS := $(cts_src_dirs)
$(cts_package_xml): PRIVATE_INSTRUMENTATION := $(LOCAL_INSTRUMENTATION_FOR)
$(cts_package_xml): PRIVATE_PACKAGE := $(LOCAL_PACKAGE_NAME)
ifneq ($(filter cts/suite/cts/%, $(LOCAL_PATH)),)
@@ -48,7 +52,7 @@
$(hide) echo Generating test description for java package $(PRIVATE_PACKAGE)
$(hide) mkdir -p $(CTS_TESTCASES_OUT)
$(hide) $(CTS_JAVA_TEST_SCANNER) \
- -s $(PRIVATE_PATH) \
+ $(PRIVATE_SRC_DIRS) \
-d $(CTS_JAVA_TEST_SCANNER_DOCLET) | \
$(CTS_XML_GENERATOR) \
-t $(PRIVATE_TEST_TYPE) \
diff --git a/build/test_uiautomator.mk b/build/test_uiautomator.mk
index 5e2f07a..085d672 100644
--- a/build/test_uiautomator.mk
+++ b/build/test_uiautomator.mk
@@ -24,12 +24,16 @@
cts_library_xml := $(CTS_TESTCASES_OUT)/$(LOCAL_MODULE).xml
cts_library_jar := $(CTS_TESTCASES_OUT)/$(LOCAL_MODULE).jar
+cts_src_dirs := $(LOCAL_PATH)/src
+cts_src_dirs += $(sort $(dir $(LOCAL_GENERATED_SOURCES)))
+cts_src_dirs := $(addprefix -s , $(cts_src_dirs))
+
$(cts_library_jar): PRIVATE_MODULE := $(LOCAL_MODULE)
$(cts_library_jar): $(call intermediates-dir-for,JAVA_LIBRARIES,$(LOCAL_MODULE))/javalib.jar | $(ACP)
$(hide) mkdir -p $(CTS_TESTCASES_OUT)
$(hide) $(ACP) -fp $(call intermediates-dir-for,JAVA_LIBRARIES,$(PRIVATE_MODULE))/javalib.jar $@
-$(cts_library_xml): PRIVATE_PATH := $(LOCAL_PATH)/src
+$(cts_library_xml): PRIVATE_SRC_DIRS := $(cts_src_dirs)
$(cts_library_xml): PRIVATE_TEST_APP_PACKAGE := $(LOCAL_CTS_TEST_APP_PACKAGE)
$(cts_library_xml): PRIVATE_TEST_PACKAGE := $(LOCAL_CTS_TEST_PACKAGE)
$(cts_library_xml): PRIVATE_TEST_APK := $(LOCAL_CTS_TEST_APK)
@@ -38,7 +42,7 @@
$(cts_library_xml): $(call intermediates-dir-for,JAVA_LIBRARIES,$(LOCAL_MODULE))/javalib.jar $(CTS_EXPECTATIONS) $(CTS_UNSUPPORTED_ABIS) $(CTS_JAVA_TEST_SCANNER_DOCLET) $(CTS_JAVA_TEST_SCANNER) $(CTS_XML_GENERATOR)
$(hide) echo Generating test description for uiautomator library $(PRIVATE_LIBRARY)
$(hide) mkdir -p $(CTS_TESTCASES_OUT)
- $(hide) $(CTS_JAVA_TEST_SCANNER) -s $(PRIVATE_PATH) \
+ $(hide) $(CTS_JAVA_TEST_SCANNER) $(PRIVATE_SRC_DIRS) \
-d $(CTS_JAVA_TEST_SCANNER_DOCLET) | \
$(CTS_XML_GENERATOR) -t uiAutomator \
-i $(PRIVATE_TEST_APK) \
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
index baaa14c..5149a74 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -54,12 +54,9 @@
private static final String RUNNER = "android.test.InstrumentationTestRunner";
- private static final String[] REQUIRED_DEVICE_FEATURES = new String[] {
- "android.software.managed_users",
- "android.software.device_admin" };
-
private CtsBuildHelper mCtsBuild;
+ private HashSet<String> mAvailableFeatures;
protected boolean mHasFeature;
@Override
@@ -72,7 +69,7 @@
super.setUp();
assertNotNull(mCtsBuild); // ensure build has been set before test is run.
mHasFeature = getDevice().getApiLevel() >= 21 /* Build.VERSION_CODES.L */
- && hasDeviceFeatures(REQUIRED_DEVICE_FEATURES);
+ && hasDeviceFeature("android.software.device_admin");
}
protected void installApp(String fileName)
@@ -247,32 +244,30 @@
}
}
- private boolean hasDeviceFeatures(String[] requiredFeatures)
- throws DeviceNotAvailableException {
- // TODO: Move this logic to ITestDevice.
- String command = "pm list features";
- String commandOutput = getDevice().executeShellCommand(command);
- CLog.i("Output for command " + command + ": " + commandOutput);
+ protected boolean hasDeviceFeature(String requiredFeature) throws DeviceNotAvailableException {
+ if (mAvailableFeatures == null) {
+ // TODO: Move this logic to ITestDevice.
+ String command = "pm list features";
+ String commandOutput = getDevice().executeShellCommand(command);
+ CLog.i("Output for command " + command + ": " + commandOutput);
- // Extract the id of the new user.
- HashSet<String> availableFeatures = new HashSet<String>();
- for (String feature: commandOutput.split("\\s+")) {
- // Each line in the output of the command has the format "feature:{FEATURE_VALUE}".
- String[] tokens = feature.split(":");
- assertTrue("\"" + feature + "\" expected to have format feature:{FEATURE_VALUE}",
- tokens.length > 1);
- assertEquals(feature, "feature", tokens[0]);
- availableFeatures.add(tokens[1]);
- }
-
- for (String requiredFeature : requiredFeatures) {
- if(!availableFeatures.contains(requiredFeature)) {
- CLog.logAndDisplay(LogLevel.INFO, "Device doesn't have required feature "
- + requiredFeature + ". Tests won't run.");
- return false;
+ // Extract the id of the new user.
+ mAvailableFeatures = new HashSet<>();
+ for (String feature: commandOutput.split("\\s+")) {
+ // Each line in the output of the command has the format "feature:{FEATURE_VALUE}".
+ String[] tokens = feature.split(":");
+ assertTrue("\"" + feature + "\" expected to have format feature:{FEATURE_VALUE}",
+ tokens.length > 1);
+ assertEquals(feature, "feature", tokens[0]);
+ mAvailableFeatures.add(tokens[1]);
}
}
- return true;
+ boolean result = mAvailableFeatures.contains(requiredFeature);
+ if (!result) {
+ CLog.logAndDisplay(LogLevel.INFO, "Device doesn't have required feature "
+ + requiredFeature + ". Test won't run.");
+ }
+ return result;
}
protected int createUser() throws Exception {
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
index 815a453..7da4228 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
@@ -44,7 +44,8 @@
super.setUp();
// We need multi user to be supported in order to create a profile of the user owner.
- mHasFeature = mHasFeature && (getMaxNumberOfUsersSupported() > 1);
+ mHasFeature = mHasFeature && (getMaxNumberOfUsersSupported() > 1) && hasDeviceFeature(
+ "android.software.managed_users");
if (mHasFeature) {
mUserId = createManagedProfile();
@@ -87,6 +88,14 @@
assertFalse(listUsers().contains(mUserId));
}
+ public void testMaxUsersStrictlyMoreThanOne() throws Exception {
+ if (hasDeviceFeature("android.software.managed_users")) {
+ assertTrue("Device must support more than 1 user "
+ + "if android.software.managed_users feature is available",
+ getMaxNumberOfUsersSupported() > 1);
+ }
+ }
+
public void testCrossProfileIntentFilters() throws Exception {
if (!mHasFeature) {
return;
diff --git a/hostsidetests/monkey/test-apps/CtsMonkeyApp/AndroidManifest.xml b/hostsidetests/monkey/test-apps/CtsMonkeyApp/AndroidManifest.xml
index 849d6a4..a3dfc83 100644
--- a/hostsidetests/monkey/test-apps/CtsMonkeyApp/AndroidManifest.xml
+++ b/hostsidetests/monkey/test-apps/CtsMonkeyApp/AndroidManifest.xml
@@ -18,14 +18,14 @@
<application android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
- <activity android:name=".MonkeyActivity" android:screenOrientation="portrait">
+ <activity android:name=".MonkeyActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
- <activity android:name=".BaboonActivity" android:screenOrientation="portrait">
+ <activity android:name=".BaboonActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.MONKEY" />
diff --git a/hostsidetests/security/Android.mk b/hostsidetests/security/Android.mk
index a42ee8a..0c976a3 100644
--- a/hostsidetests/security/Android.mk
+++ b/hostsidetests/security/Android.mk
@@ -23,12 +23,27 @@
# Must match the package name in CtsTestCaseList.mk
LOCAL_MODULE := CtsSecurityHostTestCases
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt
LOCAL_CTS_TEST_PACKAGE := android.host.security
LOCAL_JAVA_RESOURCE_FILES := $(HOST_OUT_EXECUTABLES)/sepolicy-analyze
+selinux_general_policy := $(call intermediates-dir-for,ETC,general_sepolicy.conf)/general_sepolicy.conf
+
+selinux_neverallow_gen := cts/tools/selinux/SELinuxNeverallowTestGen.py
+
+selinux_neverallow_gen_data := cts/tools/selinux/SELinuxNeverallowTestFrame.py
+
+LOCAL_GENERATED_SOURCES := $(call local-generated-sources-dir)/android/cts/security/SELinuxNeverallowRulesTest.java
+
+$(LOCAL_GENERATED_SOURCES) : PRIVATE_SELINUX_GENERAL_POLICY := $(selinux_general_policy)
+$(LOCAL_GENERATED_SOURCES) : $(selinux_neverallow_gen) $(selinux_general_policy) $(selinux_neverallow_gen_data)
+ mkdir -p $(dir $@)
+ $< $(PRIVATE_SELINUX_GENERAL_POLICY) $@
+
include $(BUILD_CTS_HOST_JAVA_LIBRARY)
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java b/hostsidetests/security/src/android/cts/security/SELinuxHostTest.java
similarity index 76%
rename from hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
rename to hostsidetests/security/src/android/cts/security/SELinuxHostTest.java
index e2c98fe..96845b1 100644
--- a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
+++ b/hostsidetests/security/src/android/cts/security/SELinuxHostTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.security.cts;
+package android.cts.security;
import com.android.cts.tradefed.build.CtsBuildHelper;
import com.android.ddmlib.Log;
@@ -26,9 +26,10 @@
import java.io.BufferedReader;
import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.io.FileOutputStream;
import java.lang.String;
import java.net.URL;
import java.util.Scanner;
@@ -42,15 +43,42 @@
*/
public class SELinuxHostTest extends DeviceTestCase {
+ private File sepolicyAnalyze;
+ private File devicePolicyFile;
+
/**
* A reference to the device under test.
*/
private ITestDevice mDevice;
+ private File copyResourceToTempFile(String resName) throws IOException {
+ InputStream is = this.getClass().getResourceAsStream(resName);
+ File tempFile = File.createTempFile("SELinuxHostTest", ".tmp");
+ FileOutputStream os = new FileOutputStream(tempFile);
+ int rByte = 0;
+ while ((rByte = is.read()) != -1) {
+ os.write(rByte);
+ }
+ os.flush();
+ os.close();
+ tempFile.deleteOnExit();
+ return tempFile;
+ }
+
@Override
protected void setUp() throws Exception {
super.setUp();
mDevice = getDevice();
+
+ /* retrieve the sepolicy-analyze executable from jar */
+ sepolicyAnalyze = copyResourceToTempFile("/sepolicy-analyze");
+ sepolicyAnalyze.setExecutable(true);
+
+ /* obtain sepolicy file from running device */
+ devicePolicyFile = File.createTempFile("sepolicy", ".tmp");
+ devicePolicyFile.deleteOnExit();
+ mDevice.executeAdbCommand("pull", "/sys/fs/selinux/policy",
+ devicePolicyFile.getAbsolutePath());
}
/**
@@ -60,25 +88,9 @@
*/
public void testAllEnforcing() throws Exception {
- /* retrieve the sepolicy-analyze executable from jar */
- InputStream is = this.getClass().getResourceAsStream("/sepolicy-analyze");
- File execFile = File.createTempFile("sepolicy-analyze", ".tmp");
- FileOutputStream os = new FileOutputStream(execFile);
- int rByte = 0;
- while ((rByte = is.read()) != -1) {
- os.write(rByte);
- }
- os.flush();
- os.close();
- execFile.setExecutable(true);
-
- /* obtain sepolicy file from running device */
- File policyFile = File.createTempFile("sepolicy", ".tmp");
- mDevice.executeAdbCommand("pull", "/sys/fs/selinux/policy", policyFile.getAbsolutePath());
-
/* run sepolicy-analyze permissive check on policy file */
- ProcessBuilder pb = new ProcessBuilder(execFile.getAbsolutePath(), "-p", "-P",
- policyFile.getAbsolutePath());
+ ProcessBuilder pb = new ProcessBuilder(sepolicyAnalyze.getAbsolutePath(),
+ devicePolicyFile.getAbsolutePath(), "permissive");
pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
pb.redirectErrorStream(true);
Process p = pb.start();
@@ -90,10 +102,6 @@
errorString.append(line);
errorString.append("\n");
}
-
- /* clean up and check condition */
- execFile.delete();
- policyFile.delete();
assertTrue("The following SELinux domains were found to be in permissive mode:\n"
+ errorString, errorString.length() == 0);
}
diff --git a/tests/core/runner/src/com/android/cts/runner/CtsTestRunListener.java b/tests/core/runner/src/com/android/cts/runner/CtsTestRunListener.java
index 57945f8..080c08e 100644
--- a/tests/core/runner/src/com/android/cts/runner/CtsTestRunListener.java
+++ b/tests/core/runner/src/com/android/cts/runner/CtsTestRunListener.java
@@ -58,7 +58,7 @@
@Override
public void testRunStarted(Description description) throws Exception {
- mEnvironment = new TestEnvironment(getInstrumentation().getContext());
+ mEnvironment = new TestEnvironment(getInstrumentation().getTargetContext());
// We might want to move this to /sdcard, if is is mounted/writable.
File cacheDir = getInstrumentation().getTargetContext().getCacheDir();
diff --git a/tests/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index 48e5194..3abb1f7 100644
--- a/tests/expectations/knownfailures.txt
+++ b/tests/expectations/knownfailures.txt
@@ -1,5 +1,12 @@
[
{
+ description: "testWindowContentFrameStats is flaky without 75b55d0846159543aafc1b7420915497fce9b3f1",
+ names: [
+ "android.app.uiautomation.cts.UiAutomationTest#testWindowContentFrameStats"
+ ],
+ bug: 18039218
+},
+{
description: "the UsageStats is not yet stable enough",
names: [
"android.app.usage.cts.UsageStatsTest"
diff --git a/tests/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java b/tests/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
index d0255f3..1f61b27 100644
--- a/tests/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
+++ b/tests/tests/admin/src/android/admin/cts/DevicePolicyManagerTest.java
@@ -21,7 +21,11 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.os.Build;
import android.os.UserManager;
import android.provider.Settings;
import android.test.AndroidTestCase;
@@ -44,6 +48,8 @@
private ComponentName mComponent;
private ComponentName mSecondComponent;
private boolean mDeviceAdmin;
+ private boolean mManagedProfiles;
+ private PackageManager mPackageManager;
private static final String TEST_CA_STRING1 =
"-----BEGIN CERTIFICATE-----\n" +
@@ -68,9 +74,11 @@
mDevicePolicyManager = (DevicePolicyManager)
mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
mComponent = DeviceAdminInfoTest.getReceiverComponent();
+ mPackageManager = mContext.getPackageManager();
mSecondComponent = DeviceAdminInfoTest.getSecondReceiverComponent();
- mDeviceAdmin =
- mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN);
+ mDeviceAdmin = mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN);
+ mManagedProfiles = mDeviceAdmin
+ && mPackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS);
setBlankPassword();
}
@@ -894,6 +902,32 @@
}
}
+ /**
+ * Test whether the version of the pre-installed launcher is at least L. This is needed for
+ * managed profile support.
+ */
+ public void testLauncherVersionAtLeastL() throws Exception {
+ if (!mManagedProfiles) {
+ return;
+ }
+
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.addCategory(Intent.CATEGORY_HOME);
+ List<ResolveInfo> resolveInfos = mPackageManager.queryIntentActivities(intent,
+ 0 /* default flags */);
+ assertFalse("No launcher present", resolveInfos.isEmpty());
+
+ for (ResolveInfo resolveInfo : resolveInfos) {
+ ApplicationInfo launcherAppInfo = mPackageManager.getApplicationInfo(
+ resolveInfo.activityInfo.packageName, 0 /* default flags */);
+ if ((launcherAppInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0 &&
+ launcherAppInfo.targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {
+ return;
+ }
+ }
+ fail("No system launcher with version L+ present present on device.");
+ }
+
private void assertDeviceOwnerMessage(String message) {
assertTrue("message is: "+ message, message.contains("does not own the device")
|| message.contains("can only be called by the device owner"));
diff --git a/tests/tests/app/src/android/app/cts/ActivityManagerMemoryClassTest.java b/tests/tests/app/src/android/app/cts/ActivityManagerMemoryClassTest.java
index 7d3fc5e..904a056 100644
--- a/tests/tests/app/src/android/app/cts/ActivityManagerMemoryClassTest.java
+++ b/tests/tests/app/src/android/app/cts/ActivityManagerMemoryClassTest.java
@@ -24,6 +24,8 @@
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.WindowManager;
+import java.util.HashMap;
+import java.util.Map;
/**
* {@link ActivityInstrumentationTestCase2} that tests {@link ActivityManager#getMemoryClass()}
@@ -37,6 +39,66 @@
super(ActivityManagerMemoryClassLaunchActivity.class);
}
+ public static class ExpectedMemorySizesClass {
+ private static final Map<Integer, Integer> expectedMemorySizeForSmallNormalScreen
+ = new HashMap<Integer, Integer>();
+ private static final Map<Integer, Integer> expectedMemorySizeForLargeScreen
+ = new HashMap<Integer, Integer>();
+ private static final Map<Integer, Integer> expectedMemorySizeForXLargeScreen
+ = new HashMap<Integer, Integer>();
+
+ static {
+ expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_LOW, 32);
+ expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_MEDIUM, 32);
+ expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_TV, 48);
+ expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_HIGH, 48);
+ expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_XHIGH, 48);
+ expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_400, 96);
+ expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_XXHIGH, 128);
+ expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_560, 192);
+ expectedMemorySizeForSmallNormalScreen.put(DisplayMetrics.DENSITY_XXXHIGH, 256);
+ }
+
+ static {
+ expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_LOW, 32);
+ expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_MEDIUM, 64);
+ expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_TV, 80);
+ expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_HIGH, 80);
+ expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_XHIGH, 128);
+ expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_400, 192);
+ expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_XXHIGH, 256);
+ expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_560, 384);
+ expectedMemorySizeForLargeScreen.put(DisplayMetrics.DENSITY_XXXHIGH, 512);
+ }
+
+ static {
+ expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_LOW, 48);
+ expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_MEDIUM, 80);
+ expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_TV, 96);
+ expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_HIGH, 96);
+ expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_XHIGH, 192);
+ expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_400, 288);
+ expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_XXHIGH, 384);
+ expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_560, 576);
+ expectedMemorySizeForXLargeScreen.put(DisplayMetrics.DENSITY_XXXHIGH, 768);
+ }
+
+ public static Integer getExpectedMemorySize(int screenSize, int screenDensity) {
+ switch (screenSize) {
+ case Configuration.SCREENLAYOUT_SIZE_SMALL:
+ case Configuration.SCREENLAYOUT_SIZE_NORMAL:
+ return expectedMemorySizeForSmallNormalScreen.get(screenDensity);
+ case Configuration.SCREENLAYOUT_SIZE_LARGE:
+ return expectedMemorySizeForLargeScreen.get(screenDensity);
+ case Configuration.SCREENLAYOUT_SIZE_XLARGE:
+ return expectedMemorySizeForXLargeScreen.get(screenDensity);
+ default:
+ throw new IllegalArgumentException("No memory requirement specified "
+ + " for screen layout size " + screenSize);
+ }
+ }
+ }
+
public void testGetMemoryClass() throws Exception {
int memoryClass = getMemoryClass();
int screenDensity = getScreenDensity();
@@ -70,46 +132,8 @@
}
private void assertMemoryForScreenDensity(int memoryClass, int screenDensity, int screenSize) {
- int expectedMinimumMemory = -1;
- boolean isXLarge = screenSize == Configuration.SCREENLAYOUT_SIZE_XLARGE;
- switch (screenDensity) {
- case DisplayMetrics.DENSITY_LOW:
- expectedMinimumMemory = 16;
- break;
-
- case DisplayMetrics.DENSITY_MEDIUM:
- expectedMinimumMemory = isXLarge ? 32 : 16;
- break;
-
- case DisplayMetrics.DENSITY_HIGH:
- case DisplayMetrics.DENSITY_TV:
- expectedMinimumMemory = isXLarge ? 64 : 32;
- break;
-
- case DisplayMetrics.DENSITY_XHIGH:
- expectedMinimumMemory = isXLarge ? 128 : 64;
- break;
-
- case DisplayMetrics.DENSITY_400:
- expectedMinimumMemory = isXLarge ? 192 : 128;
- break;
-
- case DisplayMetrics.DENSITY_XXHIGH:
- expectedMinimumMemory = isXLarge ? 256 : 128;
- break;
-
- case DisplayMetrics.DENSITY_560:
- expectedMinimumMemory = isXLarge ? 512 : 256;
- break;
-
- case DisplayMetrics.DENSITY_XXXHIGH:
- expectedMinimumMemory = isXLarge ? 512 : 256;
- break;
-
- default:
- throw new IllegalArgumentException("No memory requirement specified "
- + " for screen density " + screenDensity);
- }
+ int expectedMinimumMemory = ExpectedMemorySizesClass.getExpectedMemorySize(screenSize,
+ screenDensity);
assertTrue("Expected to have at least " + expectedMinimumMemory
+ "mb of memory for screen density " + screenDensity,
diff --git a/tests/tests/hardware/AndroidManifest.xml b/tests/tests/hardware/AndroidManifest.xml
index 1a02d0a..ab81162 100644
--- a/tests/tests/hardware/AndroidManifest.xml
+++ b/tests/tests/hardware/AndroidManifest.xml
@@ -24,6 +24,7 @@
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.BODY_SENSORS" />
+ <uses-permission android:name="android.permission.TRANSMIT_IR" />
<application>
<uses-library android:name="android.test.runner" />
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java
index ec2f95b..f7d95f6 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java
@@ -2069,6 +2069,16 @@
*/
private void verifyFpsNotSlowDown(CaptureRequest.Builder requestBuilder,
int numFramesVerified) throws Exception {
+ boolean frameDurationAvailable = true;
+ // Allow a few frames for AE to settle on target FPS range
+ final int NUM_FRAME_TO_SKIP = 6;
+ float frameDurationErrorMargin = FRAME_DURATION_ERROR_MARGIN;
+ if (!mStaticInfo.areKeysAvailable(CaptureResult.SENSOR_FRAME_DURATION)) {
+ frameDurationAvailable = false;
+ // Allow a larger error margin (1.5%) for timestamps
+ frameDurationErrorMargin = 0.015f;
+ }
+
Range<Integer>[] fpsRanges = mStaticInfo.getAeAvailableTargetFpsRangesChecked();
boolean antiBandingOffIsSupported = mStaticInfo.isAntiBandingOffModeSupported();
Range<Integer> fpsRange;
@@ -2108,18 +2118,33 @@
resultListener = new SimpleCaptureCallback();
startPreview(requestBuilder, previewSz, resultListener);
- long[] frameDurationRange =
- new long[]{(long) (1e9 / fpsRange.getUpper()), (long) (1e9 / fpsRange.getLower())};
+ waitForSettingsApplied(resultListener, NUM_FRAMES_WAITED_FOR_UNKNOWN_LATENCY);
+ // Wait several more frames for AE to settle on target FPS range
+ waitForNumResults(resultListener, NUM_FRAME_TO_SKIP);
+
+ long[] frameDurationRange = new long[]{
+ (long) (1e9 / fpsRange.getUpper()), (long) (1e9 / fpsRange.getLower())};
+ long captureTime = 0, prevCaptureTime = 0;
for (int j = 0; j < numFramesVerified; j++) {
+ long frameDuration = frameDurationRange[0];
CaptureResult result =
resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
validatePipelineDepth(result);
- long frameDuration = getValueNotNull(result, CaptureResult.SENSOR_FRAME_DURATION);
+ if (frameDurationAvailable) {
+ frameDuration = getValueNotNull(result, CaptureResult.SENSOR_FRAME_DURATION);
+ } else {
+ // if frame duration is not available, check timestamp instead
+ captureTime = getValueNotNull(result, CaptureResult.SENSOR_TIMESTAMP);
+ if (j > 0) {
+ frameDuration = captureTime - prevCaptureTime;
+ }
+ prevCaptureTime = captureTime;
+ }
mCollector.expectInRange(
"Frame duration must be in the range of " + Arrays.toString(frameDurationRange),
frameDuration,
- (long) (frameDurationRange[0] * (1 - FRAME_DURATION_ERROR_MARGIN)),
- (long) (frameDurationRange[1] * (1 + FRAME_DURATION_ERROR_MARGIN)));
+ (long) (frameDurationRange[0] * (1 - frameDurationErrorMargin)),
+ (long) (frameDurationRange[1] * (1 + frameDurationErrorMargin)));
}
}
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 37302dc..21920b7 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java
@@ -59,7 +59,7 @@
private static final boolean DEBUG_DUMP = Log.isLoggable(TAG, Log.DEBUG);
private static final int RECORDING_DURATION_MS = 3000;
private static final int DURATION_MARGIN_MS = 600;
- private static final int FRAME_DURATION_ERROR_TOLERANCE_MS = 3;
+ private static final double FRAME_DURATION_ERROR_TOLERANCE_MS = 3.0;
private static final int BIT_RATE_1080P = 16000000;
private static final int BIT_RATE_MIN = 64000;
private static final int BIT_RATE_MAX = 40000000;
@@ -79,6 +79,7 @@
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_INTERVAL_ALLOWED = 4;
private List<Size> mSupportedVideoSizes;
private Surface mRecordingSurface;
private MediaRecorder mMediaRecorder;
@@ -385,6 +386,7 @@
* given camera. preview size is set to the video size.
*/
private void basicRecordingTestByCamera() throws Exception {
+ Size maxPreviewSize = mOrderedPreviewSizes.get(0);
for (int profileId : mCamcorderProfileList) {
int cameraId = Integer.valueOf(mCamera.getId());
if (!CamcorderProfile.hasProfile(cameraId, profileId) ||
@@ -394,6 +396,12 @@
CamcorderProfile profile = CamcorderProfile.get(cameraId, profileId);
Size videoSz = new Size(profile.videoFrameWidth, profile.videoFrameHeight);
+ if (mStaticInfo.isHardwareLevelLegacy() &&
+ (videoSz.getWidth() > maxPreviewSize.getWidth() ||
+ videoSz.getHeight() > maxPreviewSize.getHeight())) {
+ // Skip. Legacy mode can only do recording up to max preview size
+ continue;
+ }
assertTrue("Video size " + videoSz.toString() + " for profile ID " + profileId +
" must be one of the camera device supported video size!",
mSupportedVideoSizes.contains(videoSz));
@@ -892,7 +900,7 @@
*/
private int validateFrameDropAroundVideoSnapshot(
SimpleCaptureCallback resultListener, long imageTimeStamp) {
- int expectedDurationMs = 1000 / mVideoFrameRate;
+ double expectedDurationMs = 1000.0 / mVideoFrameRate;
CaptureResult prevResult = resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
long prevTS = getValueNotNull(prevResult, CaptureResult.SENSOR_TIMESTAMP);
while (!resultListener.hasMoreResults()) {
@@ -904,23 +912,41 @@
CaptureResult nextResult =
resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
long nextTS = getValueNotNull(nextResult, CaptureResult.SENSOR_TIMESTAMP);
- int durationMs = (int) (currentTS - prevTS) / 1000000;
+ double durationMs = (currentTS - prevTS) / 1000000.0;
int totalFramesDropped = 0;
// 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 %.2fms (expected %.2fms)",
+ mVideoSize.getWidth(), mVideoSize.getHeight(),
+ durationMs, expectedDurationMs
+ ),
+ durationMs <= (expectedDurationMs * MAX_NUM_FRAME_DROP_INTERVAL_ALLOWED)
+ );
// Log a warning is there is any frame drop detected.
if (durationMs >= expectedDurationMs * 2) {
Log.w(TAG, String.format(
"Video %dx%d Frame drop detected before video snapshot: " +
- "duration %dms (expected %dms)",
+ "duration %.2fms (expected %.2fms)",
mVideoSize.getWidth(), mVideoSize.getHeight(),
durationMs, expectedDurationMs
));
}
durationMs = (int) (nextTS - currentTS) / 1000000;
+ mCollector.expectTrue(
+ String.format(
+ "Video %dx%d Frame drop detected after video snapshot: " +
+ "duration %.2fms (expected %.2fms)",
+ mVideoSize.getWidth(), mVideoSize.getHeight(),
+ durationMs, expectedDurationMs
+ ),
+ durationMs <= (expectedDurationMs * MAX_NUM_FRAME_DROP_INTERVAL_ALLOWED)
+ );
// Log a warning is there is any frame drop detected.
if (durationMs >= expectedDurationMs * 2) {
Log.w(TAG, String.format(
@@ -931,10 +957,9 @@
));
}
- int totalDurationMs = (int) (nextTS - prevTS) / 1000000;
- // Rounding and minus 2 for the expected 2 frames interval
- totalFramesDropped =
- (totalDurationMs + expectedDurationMs / 2) /expectedDurationMs - 2;
+ double totalDurationMs = (nextTS - prevTS) / 1000000.0;
+ // Minus 2 for the expected 2 frames interval
+ totalFramesDropped = (int) (totalDurationMs / expectedDurationMs) - 2;
if (totalFramesDropped < 0) {
Log.w(TAG, "totalFrameDropped is " + totalFramesDropped +
". Video frame rate might be too fast.");
@@ -953,19 +978,19 @@
* Validate frame jittering from the input simple listener's buffered results
*/
private void validateJittering(SimpleCaptureCallback resultListener) {
- int expectedDurationMs = 1000 / mVideoFrameRate;
+ double expectedDurationMs = 1000.0 / mVideoFrameRate;
CaptureResult prevResult = resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
long prevTS = getValueNotNull(prevResult, CaptureResult.SENSOR_TIMESTAMP);
while (!resultListener.hasMoreResults()) {
CaptureResult currentResult =
resultListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
long currentTS = getValueNotNull(currentResult, CaptureResult.SENSOR_TIMESTAMP);
- int durationMs = (int) (currentTS - prevTS) / 1000000;
- int durationError = Math.abs(durationMs - expectedDurationMs);
+ double durationMs = (currentTS - prevTS) / 1000000.0;
+ double durationError = Math.abs(durationMs - expectedDurationMs);
long frameNumber = currentResult.getFrameNumber();
mCollector.expectTrue(
String.format(
- "Resolution %dx%d Frame %d: jittering (%dms) exceeds bound [%dms,%dms]",
+ "Resolution %dx%d Frame %d: jittering (%.2fms) exceeds bound [%.2fms,%.2fms]",
mVideoSize.getWidth(), mVideoSize.getHeight(),
frameNumber, durationMs,
expectedDurationMs - FRAME_DURATION_ERROR_TOLERANCE_MS,
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/StaticMetadataTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/StaticMetadataTest.java
index ec7ecf8..dd1882e 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/StaticMetadataTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/StaticMetadataTest.java
@@ -19,12 +19,15 @@
import static android.hardware.camera2.CameraCharacteristics.*;
import android.graphics.ImageFormat;
+import android.graphics.Rect;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.CameraCharacteristics.Key;
import android.hardware.camera2.cts.helpers.StaticMetadata;
import android.hardware.camera2.cts.helpers.StaticMetadata.CheckLevel;
import android.hardware.camera2.cts.testcases.Camera2AndroidTestCase;
+import android.hardware.camera2.params.StreamConfigurationMap;
import android.util.Log;
import android.util.Size;
@@ -56,8 +59,14 @@
* Test the available capability for different hardware support level devices.
*/
public void testHwSupportedLevel() throws Exception {
+ Key<StreamConfigurationMap> key =
+ CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP;
+ final float SIZE_ERROR_MARGIN = 0.03f;
for (String id : mCameraIds) {
initStaticMetadata(id);
+ StreamConfigurationMap configs = mStaticInfo.getValueFromKeyNonNull(key);
+ Rect activeRect = mStaticInfo.getActiveArraySizeChecked();
+ Size sensorSize = new Size(activeRect.width(), activeRect.height());
List<Integer> availableCaps = mStaticInfo.getAvailableCapabilitiesChecked();
mCollector.expectTrue("All device must contains BACKWARD_COMPATIBLE capability",
@@ -71,6 +80,13 @@
availableCaps.contains(
REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING));
+ // Max yuv resolution must be very close to sensor resolution
+ Size[] yuvSizes = configs.getOutputSizes(ImageFormat.YUV_420_888);
+ Size maxYuvSize = CameraTestUtils.getMaxSize(yuvSizes);
+ mCollector.expectSizesAreSimilar(
+ "Active array size and max YUV size should be similar",
+ sensorSize, maxYuvSize, SIZE_ERROR_MARGIN);
+
// Max resolution fps must be >= 20.
mCollector.expectTrue("Full device must support at least 20fps for max resolution",
getFpsForMaxSize(id) >= MIN_FPS_FOR_FULL_DEVICE);
@@ -80,6 +96,13 @@
mStaticInfo.isPerFrameControlSupported());
}
+ // Max jpeg resolution must be very close to sensor resolution
+ Size[] jpegSizes = configs.getOutputSizes(ImageFormat.JPEG);
+ Size maxJpegSize = CameraTestUtils.getMaxSize(jpegSizes);
+ mCollector.expectSizesAreSimilar(
+ "Active array size and max JPEG size should be similar",
+ sensorSize, maxJpegSize, SIZE_ERROR_MARGIN);
+
// TODO: test all the keys mandatory for all capability devices.
}
}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/StillCaptureTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/StillCaptureTest.java
index e816659..37eff10 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/StillCaptureTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/StillCaptureTest.java
@@ -440,6 +440,10 @@
waitForNumResults(resultListener, NUM_FRAMES_WAITED);
stopPreview();
+
+ // Free image resources
+ image.close();
+ closeImageReader();
return;
}
@@ -609,6 +613,9 @@
Image image = imageListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
validateJpegCapture(image, maxStillSz);
+ // Free image resources
+ image.close();
+
stopPreview();
}
@@ -654,6 +661,10 @@
mSession.capture(stillRequest.build(), resultListener, mHandler);
Image image = imageListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
validateJpegCapture(image, stillSz);
+
+ // Free image resources
+ image.close();
+
// stopPreview must be called here to make sure next time a preview stream
// is created with new size.
stopPreview();
@@ -704,6 +715,9 @@
dumpFile(rawFileName, rawBuffer);
}
+ // Free image resources
+ image.close();
+
stopPreview();
}
@@ -1021,6 +1035,9 @@
if (!mStaticInfo.isHardwareLevelLegacy()) {
jpegTestExifExtraTags(exif, maxStillSz, stillResult);
}
+
+ // Free image resources
+ image.close();
}
}
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/CameraErrorCollector.java b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/CameraErrorCollector.java
index 7cf4089..f4859e5 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/CameraErrorCollector.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/CameraErrorCollector.java
@@ -520,6 +520,37 @@
}
/**
+ * Check that two sizes are similar enough by ensuring that their width and height
+ * are within {@code errorPercent} of each other.
+ *
+ * <p>Only the first error is collected, to avoid spamming several error messages when
+ * the rectangle is hugely dissimilar.</p>
+ *
+ * @param msg Message to be logged
+ * @param expected The reference 'expected' value to be used to check against
+ * @param actual The actual value that was received
+ * @param errorPercent Within how many percent the components should be
+ *
+ * @return {@code true} if all expects passed, {@code false} otherwise
+ */
+ public boolean expectSizesAreSimilar(String msg, Size expected, Size actual,
+ float errorPercent) {
+ String formattedMsg = String.format("%s: rects are not similar enough; expected (%s), " +
+ "actual (%s), error percent (%s), reason: ",
+ msg, expected, actual, errorPercent);
+
+ if (!expectSimilarValues(
+ formattedMsg, "too wide", "too narrow", actual.getWidth(), expected.getWidth(),
+ errorPercent)) return false;
+
+ if (!expectSimilarValues(
+ formattedMsg, "too tall", "too short", actual.getHeight(), expected.getHeight(),
+ errorPercent)) return false;
+
+ return true;
+ }
+
+ /**
* Check that the rectangle is centered within a certain tolerance of {@code errorPercent},
* with respect to the {@code bounds} bounding rectangle.
*
diff --git a/tests/tests/hardware/src/android/hardware/cts/LowRamDeviceTest.java b/tests/tests/hardware/src/android/hardware/cts/LowRamDeviceTest.java
index 7c711a2..0e09e8c 100644
--- a/tests/tests/hardware/src/android/hardware/cts/LowRamDeviceTest.java
+++ b/tests/tests/hardware/src/android/hardware/cts/LowRamDeviceTest.java
@@ -16,9 +16,28 @@
package android.hardware.cts;
+import static android.content.res.Configuration.SCREENLAYOUT_SIZE_LARGE;
+import static android.content.res.Configuration.SCREENLAYOUT_SIZE_NORMAL;
+import static android.content.res.Configuration.SCREENLAYOUT_SIZE_SMALL;
+import static android.content.res.Configuration.SCREENLAYOUT_SIZE_XLARGE;
+
+import static android.util.DisplayMetrics.DENSITY_400;
+import static android.util.DisplayMetrics.DENSITY_560;
+import static android.util.DisplayMetrics.DENSITY_HIGH;
+import static android.util.DisplayMetrics.DENSITY_LOW;
+import static android.util.DisplayMetrics.DENSITY_MEDIUM;
+import static android.util.DisplayMetrics.DENSITY_TV;
+import static android.util.DisplayMetrics.DENSITY_XHIGH;
+
import android.app.ActivityManager;
import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+import android.os.Build;
import android.test.AndroidTestCase;
+import android.util.DisplayMetrics;
+import android.view.WindowManager;
+import android.util.Log;
import java.io.FileInputStream;
import java.io.IOException;
@@ -31,45 +50,142 @@
*/
public class LowRamDeviceTest extends AndroidTestCase {
- private static final int LOW_RAM_DEVICE_MEMORY_THRESHOLD_KB = 512 * 1024;
+ private static final long ONE_MEGABYTE = 1048576L;
+ private static final String TAG = "LowRamDeviceTest";
- public void testLowRamProductProperty() throws Exception {
- ActivityManager am =
+ private PackageManager mPackageManager;
+ private ActivityManager mActivityManager;
+ private DisplayMetrics mDisplayMetrics;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mPackageManager = getContext().getPackageManager();
+ mActivityManager =
(ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE);
- if (totalAvailableSystemMemory() <= LOW_RAM_DEVICE_MEMORY_THRESHOLD_KB) {
- assertTrue("Device must specify low RAM property: ro.config.low_ram=true",
- am.isLowRamDevice());
+ mDisplayMetrics = new DisplayMetrics();
+ WindowManager windowManager =
+ (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
+ windowManager.getDefaultDisplay().getMetrics(mDisplayMetrics);
+ }
+
+ /**
+ * Test the devices reported memory to ensure it meets the minimum values described
+ * in CDD 7.6.1.
+ */
+ public void testMinimumMemory() {
+ int density = mDisplayMetrics.densityDpi;
+ Boolean supports64Bit = supportsSixtyFourBit();
+ int screenSize = getScreenSize();
+ Boolean lowRamDevice = mActivityManager.isLowRamDevice();
+ Boolean watch = mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH);
+
+ Log.i(TAG, String.format("density=%d, supports64Bit=%s, screenSize=%d, watch=%s",
+ density, supports64Bit, screenSize, watch));
+
+ if (watch) {
+ assertFalse("Device is not expected to be 64-bit", supports64Bit);
+ assertMinMemoryMb(416);
+ } else if (lessThanDpi(density, DENSITY_HIGH, screenSize,
+ SCREENLAYOUT_SIZE_NORMAL, SCREENLAYOUT_SIZE_SMALL) ||
+ lessThanDpi(density, DENSITY_MEDIUM, screenSize, SCREENLAYOUT_SIZE_LARGE) ||
+ lessThanDpi(density, DENSITY_LOW, screenSize, SCREENLAYOUT_SIZE_XLARGE)) {
+
+ assertFalse("Device is not expected to be 64-bit", supports64Bit);
+ assertMinMemoryMb(424);
+ } else if (greaterThanDpi(density, DENSITY_XHIGH, screenSize,
+ SCREENLAYOUT_SIZE_NORMAL, SCREENLAYOUT_SIZE_SMALL) ||
+ greaterThanDpi(density, DENSITY_TV, screenSize, SCREENLAYOUT_SIZE_LARGE) ||
+ greaterThanDpi(density, DENSITY_MEDIUM, screenSize, SCREENLAYOUT_SIZE_XLARGE)) {
+
+ if (supports64Bit) {
+ assertMinMemoryMb(832);
+ } else {
+ assertMinMemoryMb(512);
+ }
+ } else if (greaterThanDpi(density, DENSITY_400, screenSize,
+ SCREENLAYOUT_SIZE_NORMAL, SCREENLAYOUT_SIZE_SMALL) ||
+ greaterThanDpi(density, DENSITY_XHIGH, screenSize, SCREENLAYOUT_SIZE_LARGE) ||
+ greaterThanDpi(density, DENSITY_TV, screenSize, SCREENLAYOUT_SIZE_XLARGE)) {
+
+ if (supports64Bit) {
+ assertMinMemoryMb(1280);
+ } else {
+ assertMinMemoryMb(896);
+ }
+ } else if (greaterThanDpi(density, DENSITY_560, screenSize,
+ SCREENLAYOUT_SIZE_NORMAL, SCREENLAYOUT_SIZE_SMALL) ||
+ greaterThanDpi(density, DENSITY_400, screenSize, SCREENLAYOUT_SIZE_LARGE) ||
+ greaterThanDpi(density, DENSITY_XHIGH, screenSize, SCREENLAYOUT_SIZE_XLARGE)) {
+
+ if (supports64Bit) {
+ assertMinMemoryMb(1824);
+ } else {
+ assertMinMemoryMb(1344);
+ }
}
}
/**
- * Returns the total amount of memory in kilobytes available to the system.
+ * @return the total memory accessible by the kernel as defined by
+ * {@code ActivityManager.MemoryInfo}.
*/
- private int totalAvailableSystemMemory() throws IOException {
- final String property = "MemTotal";
- InputStream is = new FileInputStream("/proc/meminfo");
- try {
- Scanner scanner = new Scanner(is);
- while (scanner.hasNextLine()) {
- String line = scanner.nextLine();
- if (line.startsWith(property)) {
- StringTokenizer tokenizer = new StringTokenizer(line);
- if (tokenizer.countTokens() != 3) {
- throw new IOException("Malformed " + property + " line");
- }
-
- // Skips over "MemTotal:"
- tokenizer.nextToken();
-
- return Integer.parseInt(tokenizer.nextToken());
- }
- }
- throw new IOException(property + " could not be found");
-
- } finally {
- is.close();
- }
+ private long getTotalMemory() {
+ ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
+ mActivityManager.getMemoryInfo(memoryInfo);
+ return memoryInfo.totalMem;
}
+ /** @return the screen size as defined in {@Configuration}. */
+ private int getScreenSize() {
+ Configuration config = getContext().getResources().getConfiguration();
+ return config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;
+ }
+
+ /** @return true iff this device supports 64 bit ABIs */
+ private static boolean supportsSixtyFourBit() {
+ return Build.SUPPORTED_64_BIT_ABIS.length > 0;
+ }
+
+ /** Asserts that the given values conform to the specs in CDD 7.6.1 */
+ private void assertMinMemoryMb(long minMb) {
+
+ long totalMemoryMb = getTotalMemory() / ONE_MEGABYTE;
+ boolean lowRam = totalMemoryMb <= minMb * 1.5;
+ boolean lowRamDevice = mActivityManager.isLowRamDevice();
+
+ Log.i(TAG, String.format("minMb=%,d", minMb));
+ Log.i(TAG, String.format("totalMemoryMb=%,d", totalMemoryMb));
+ Log.i(TAG, "lowRam=" + lowRam);
+ Log.i(TAG, "lowRamDevice=" + lowRamDevice);
+
+ assertTrue(String.format("Does not meet minimum memory requirements (CDD 7.6.1)."
+ + "Found = %d, Minimum = %d", totalMemoryMb, minMb), totalMemoryMb >= minMb);
+
+ assertTrue("Device must specify low RAM property: ro.config.low_ram=true",
+ !lowRam || (lowRam && lowRamDevice));
+ }
+
+ private static boolean lessThanDpi(int actualDensityDpi, int expectedDensityDpi,
+ int actualScreenSize, int... expectedScreenSizes) {
+ return actualDensityDpi <= expectedDensityDpi &&
+ contains(expectedScreenSizes, actualScreenSize);
+ }
+
+ private static boolean greaterThanDpi(int actualDensityDpi, int expectedDensityDpi,
+ int actualScreenSize, int... expectedScreenSizes) {
+ return actualDensityDpi >= expectedDensityDpi &&
+ contains(expectedScreenSizes, actualScreenSize);
+ }
+
+ /** @return true iff the {@code array} contains the {@code target} */
+ private static boolean contains(int [] array, int target) {
+ for(int a : array) {
+ if (a == target) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEventListener.java b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEventListener.java
index 9b3a5e4..6567be2 100644
--- a/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEventListener.java
+++ b/tests/tests/hardware/src/android/hardware/cts/helpers/TestSensorEventListener.java
@@ -118,7 +118,7 @@
@Override
public void onFlushCompleted(Sensor sensor) {
CountDownLatch latch = mFlushLatch;
- mFlushLatch = new CountDownLatch(1);
+ mFlushLatch = null;
if(latch != null) {
latch.countDown();
}
diff --git a/tests/tests/media/res/raw/video_640x360_webm_vp9_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm b/tests/tests/media/res/raw/video_640x360_webm_vp9_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm
new file mode 100644
index 0000000..3f02f9a
--- /dev/null
+++ b/tests/tests/media/res/raw/video_640x360_webm_vp9_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm
Binary files differ
diff --git a/tests/tests/media/res/raw/video_640x360_webm_vp9_1638kbps_30fps_vorbis_stereo_128kbps_48000hz.webm b/tests/tests/media/res/raw/video_640x360_webm_vp9_1638kbps_30fps_vorbis_stereo_128kbps_48000hz.webm
deleted file mode 100644
index 418cc91..0000000
--- a/tests/tests/media/res/raw/video_640x360_webm_vp9_1638kbps_30fps_vorbis_stereo_128kbps_48000hz.webm
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/src/android/media/cts/DecoderTest.java b/tests/tests/media/src/android/media/cts/DecoderTest.java
index c8f2064..c1855b7 100644
--- a/tests/tests/media/src/android/media/cts/DecoderTest.java
+++ b/tests/tests/media/src/android/media/cts/DecoderTest.java
@@ -996,7 +996,7 @@
}
public void testVP9Decode640x360() throws Exception {
- testDecode(R.raw.video_640x360_webm_vp9_1638kbps_30fps_vorbis_stereo_128kbps_48000hz, 249);
+ testDecode(R.raw.video_640x360_webm_vp9_1600kbps_30fps_vorbis_stereo_128kbps_48000hz, 249);
}
public void testVP9Decode30fps1280x720Tv() 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 ba67a42..d65bbf6 100755
--- a/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayTest.java
+++ b/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayTest.java
@@ -86,7 +86,8 @@
// Encoder parameters. We use the same width/height as the virtual display.
private static final String MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC;
private static int sFrameRate = 15; // 15fps
- private static final int IFRAME_INTERVAL = 10; // 10 seconds between I-frames
+ // 100 days between I-frames
+ private static final int IFRAME_INTERVAL = 60 * 60 * 24 * 100;
private static int sBitRate = 6000000; // 6Mbps
// Colors to test (RGB). These must convert cleanly to and from BT.601 YUV.
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecTest.java b/tests/tests/media/src/android/media/cts/MediaCodecTest.java
index 1ff5048..937eee6 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecTest.java
@@ -19,6 +19,7 @@
import com.android.cts.media.R;
import android.content.res.AssetFileDescriptor;
+import android.cts.util.MediaUtils;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaCodecList;
@@ -80,27 +81,28 @@
* methods when called in incorrect operational states.
*/
public void testException() throws Exception {
- String mimeType = MediaFormat.MIMETYPE_AUDIO_AMR_WB;
- if (!supportsCodec(mimeType, false)) {
- Log.i(TAG, "No decoder found for mimeType= " + mimeType);
- return;
- }
+ boolean tested = false;
+ // audio decoder (MP3 should be present on all Android devices)
+ MediaFormat format = MediaFormat.createAudioFormat(
+ MediaFormat.MIMETYPE_AUDIO_MPEG, 44100 /* sampleRate */, 2 /* channelCount */);
+ tested = verifyException(format, false /* isEncoder */) || tested;
- MediaFormat[] formatList = new MediaFormat[2];
+ // audio encoder (AMR-WB may not be present on some Android devices)
+ format = MediaFormat.createAudioFormat(
+ MediaFormat.MIMETYPE_AUDIO_AMR_WB, 16000 /* sampleRate */, 1 /* channelCount */);
+ format.setInteger(MediaFormat.KEY_BIT_RATE, 19850);
+ tested = verifyException(format, true /* isEncoder */) || tested;
- // use audio format
- formatList[0] = new MediaFormat();
- formatList[0].setString(MediaFormat.KEY_MIME, mimeType);
- formatList[0].setInteger(MediaFormat.KEY_SAMPLE_RATE, 16000);
- formatList[0].setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
- formatList[0].setInteger(MediaFormat.KEY_BIT_RATE, 19850);
+ // video decoder (H.264/AVC may not be present on some Android devices)
+ format = createMediaFormat();
+ tested = verifyException(format, false /* isEncoder */) || tested;
- // use video format
- formatList[1] = createMediaFormat();
+ // video encoder (H.264/AVC may not be present on some Android devices)
+ tested = verifyException(format, true /* isEncoder */) || tested;
- for (MediaFormat format : formatList) {
- verifyIllegalStateException(format, false);
- verifyIllegalStateException(format, true);
+ // signal test is skipped due to no device media codecs.
+ if (!tested) {
+ MediaUtils.skipTest(TAG, "cannot find any compatible device codecs");
}
}
@@ -123,11 +125,17 @@
}
}
- private static void verifyIllegalStateException(MediaFormat format, boolean isEncoder)
+ private static boolean verifyException(MediaFormat format, boolean isEncoder)
throws IOException {
- MediaCodec codec;
+ String mimeType = format.getString(MediaFormat.KEY_MIME);
+ if (!supportsCodec(mimeType, isEncoder)) {
+ Log.i(TAG, "No " + (isEncoder ? "encoder" : "decoder")
+ + " found for mimeType= " + mimeType);
+ return false;
+ }
// create codec (enter Initialized State)
+ MediaCodec codec;
// create improperly
final String methodName = isEncoder ? "createEncoderByType" : "createDecoderByType";
@@ -270,6 +278,7 @@
fail("stop should not return MediaCodec.CodecException on wrong state");
} catch (IllegalStateException e) { // expected
}
+ return true;
}
/**
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/H263QcifLongPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/H263QcifLongPlayerTest.java
index 93dbdbd..482aec9 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/H263QcifLongPlayerTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/H263QcifLongPlayerTest.java
@@ -16,10 +16,6 @@
package android.mediastress.cts;
-import android.media.CamcorderProfile;
-import android.media.MediaRecorder.AudioEncoder;
-import android.media.MediaRecorder.VideoEncoder;
-
import com.android.cts.util.TimeoutReq;
public class H263QcifLongPlayerTest extends MediaPlayerStressTest {
@@ -28,10 +24,6 @@
"bbb_full.ffmpeg.176x144.3gp.h263_56kbps_12fps.libfaac_mono_24kbps_11025Hz.3gp"
};
- public H263QcifLongPlayerTest() {
- super(CamcorderProfile.QUALITY_QCIF, VideoEncoder.H263, AudioEncoder.AAC);
- }
-
@TimeoutReq(minutes = 11)
public void testPlay00() throws Exception {
doTestVideoPlaybackLong(0);
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/H263QcifShortPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/H263QcifShortPlayerTest.java
index 392a2c8..2035869 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/H263QcifShortPlayerTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/H263QcifShortPlayerTest.java
@@ -16,10 +16,6 @@
package android.mediastress.cts;
-import android.media.CamcorderProfile;
-import android.media.MediaRecorder.AudioEncoder;
-import android.media.MediaRecorder.VideoEncoder;
-
public class H263QcifShortPlayerTest extends MediaPlayerStressTest {
private final static String VIDEO_PATH_MIDDLE = "bbb_short/176x144/3gp_h263_libfaac/";
private final String[] mMedias = {
@@ -49,10 +45,6 @@
"bbb_short.ffmpeg.176x144.3gp.h263_56kbps_25fps.libfaac_stereo_24kbps_22050Hz.3gp"
};
- public H263QcifShortPlayerTest() {
- super(CamcorderProfile.QUALITY_QCIF, VideoEncoder.H263, AudioEncoder.AAC);
- }
-
public void testPlay00() throws Exception {
doTestVideoPlaybackShort(0);
}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/H264R1080pAacLongPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/H264R1080pAacLongPlayerTest.java
index b7f7564..7216871 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/H264R1080pAacLongPlayerTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/H264R1080pAacLongPlayerTest.java
@@ -16,20 +16,12 @@
package android.mediastress.cts;
-import android.media.CamcorderProfile;
-import android.media.MediaRecorder.AudioEncoder;
-import android.media.MediaRecorder.VideoEncoder;
-
public class H264R1080pAacLongPlayerTest extends MediaPlayerStressTest {
private static final String VIDEO_PATH_MIDDLE = "bbb_full/1920x1080/mp4_libx264_libfaac/";
private final String[] mMedias = {
"bbb_full.ffmpeg.1920x1080.mp4.libx264_10000kbps_30fps.libfaac_stereo_192kbps_48000Hz.mp4"
};
- public H264R1080pAacLongPlayerTest() {
- super(CamcorderProfile.QUALITY_1080P, VideoEncoder.H264, AudioEncoder.AAC);
- }
-
public void testPlay00() throws Exception {
doTestVideoPlaybackLong(0);
}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/H264R1080pAacRepeatedPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/H264R1080pAacRepeatedPlayerTest.java
index db5d732..28e1158 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/H264R1080pAacRepeatedPlayerTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/H264R1080pAacRepeatedPlayerTest.java
@@ -16,20 +16,12 @@
package android.mediastress.cts;
-import android.media.CamcorderProfile;
-import android.media.MediaRecorder.AudioEncoder;
-import android.media.MediaRecorder.VideoEncoder;
-
public class H264R1080pAacRepeatedPlayerTest extends MediaPlayerStressTest {
private static final String VIDEO_PATH_MIDDLE = "bbb_short/1920x1080/mp4_libx264_libfaac/";
private final String[] mMedias = {
"bbb_short.ffmpeg.1920x1080.mp4.libx264_10000kbps_30fps.libfaac_stereo_192kbps_48000Hz.mp4",
};
- public H264R1080pAacRepeatedPlayerTest() {
- super(CamcorderProfile.QUALITY_1080P, VideoEncoder.H264, AudioEncoder.AAC);
- }
-
public void testPlay00() throws Exception {
doTestVideoPlaybackRepeated(0);
}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/H264R1080pAacShortPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/H264R1080pAacShortPlayerTest.java
index 3b7da57..2e7d7ec 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/H264R1080pAacShortPlayerTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/H264R1080pAacShortPlayerTest.java
@@ -16,10 +16,6 @@
package android.mediastress.cts;
-import android.media.CamcorderProfile;
-import android.media.MediaRecorder.AudioEncoder;
-import android.media.MediaRecorder.VideoEncoder;
-
public class H264R1080pAacShortPlayerTest extends MediaPlayerStressTest {
private static final String VIDEO_PATH_MIDDLE = "bbb_short/1920x1080/mp4_libx264_libfaac/";
private final String[] mMedias = {
@@ -28,10 +24,6 @@
"bbb_short.ffmpeg.1920x1080.mp4.libx264_5000kbps_30fps.libfaac_stereo_192kbps_48000Hz.mp4"
};
- public H264R1080pAacShortPlayerTest() {
- super(CamcorderProfile.QUALITY_1080P, VideoEncoder.H264, AudioEncoder.AAC);
- }
-
public void testPlay00() throws Exception {
doTestVideoPlaybackShort(0);
}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/H264R480pAacLongPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/H264R480pAacLongPlayerTest.java
index f01aa75..3628d99 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/H264R480pAacLongPlayerTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/H264R480pAacLongPlayerTest.java
@@ -16,20 +16,12 @@
package android.mediastress.cts;
-import android.media.CamcorderProfile;
-import android.media.MediaRecorder.AudioEncoder;
-import android.media.MediaRecorder.VideoEncoder;
-
public class H264R480pAacLongPlayerTest extends MediaPlayerStressTest {
private static final String VIDEO_PATH_MIDDLE = "bbb_full/720x480/mp4_libx264_libfaac/";
private final String[] mMedias = {
"bbb_full.ffmpeg.720x480.mp4.libx264_500kbps_25fps.libfaac_stereo_128kbps_44100Hz.mp4"
};
- public H264R480pAacLongPlayerTest() {
- super(CamcorderProfile.QUALITY_480P, VideoEncoder.H264, AudioEncoder.AAC);
- }
-
public void testPlay00() throws Exception {
doTestVideoPlaybackLong(0);
}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/H264R480pAacShortPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/H264R480pAacShortPlayerTest.java
index 81b80e5..ef01327 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/H264R480pAacShortPlayerTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/H264R480pAacShortPlayerTest.java
@@ -16,10 +16,6 @@
package android.mediastress.cts;
-import android.media.CamcorderProfile;
-import android.media.MediaRecorder.AudioEncoder;
-import android.media.MediaRecorder.VideoEncoder;
-
public class H264R480pAacShortPlayerTest extends MediaPlayerStressTest {
private static final String VIDEO_PATH_MIDDLE = "bbb_short/720x480/mp4_libx264_libfaac/";
private final String[] mMedias = {
@@ -37,10 +33,6 @@
"bbb_short.ffmpeg.720x480.mp4.libx264_500kbps_30fps.libfaac_stereo_192kbps_44100Hz.mp4"
};
- public H264R480pAacShortPlayerTest() {
- super(CamcorderProfile.QUALITY_480P, VideoEncoder.H264, AudioEncoder.AAC);
- }
-
public void testPlay00() throws Exception {
doTestVideoPlaybackShort(0);
}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/H264R480x360AacShortPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/H264R480x360AacShortPlayerTest.java
index 6d0afea..12e8f6d 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/H264R480x360AacShortPlayerTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/H264R480x360AacShortPlayerTest.java
@@ -16,10 +16,6 @@
package android.mediastress.cts;
-import android.media.CamcorderProfile;
-import android.media.MediaRecorder.AudioEncoder;
-import android.media.MediaRecorder.VideoEncoder;
-
public class H264R480x360AacShortPlayerTest extends MediaPlayerStressTest {
private static final String VIDEO_PATH_MIDDLE = "bbb_short/480x360/mp4_libx264_libfaac/";
private final String[] mMedias = {
@@ -37,10 +33,6 @@
"bbb_short.ffmpeg.480x360.mp4.libx264_500kbps_30fps.libfaac_stereo_192kbps_44100Hz.mp4"
};
- public H264R480x360AacShortPlayerTest() {
- super(CamcorderProfile.QUALITY_480P, VideoEncoder.H264, AudioEncoder.AAC);
- }
-
public void testPlay00() throws Exception {
doTestVideoPlaybackShort(0);
}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/H264R720pAacLongPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/H264R720pAacLongPlayerTest.java
index 3efec62..6a126fa 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/H264R720pAacLongPlayerTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/H264R720pAacLongPlayerTest.java
@@ -16,10 +16,6 @@
package android.mediastress.cts;
-import android.media.CamcorderProfile;
-import android.media.MediaRecorder.AudioEncoder;
-import android.media.MediaRecorder.VideoEncoder;
-
public class H264R720pAacLongPlayerTest extends MediaPlayerStressTest {
private static final String VIDEO_PATH_MIDDLE = "bbb_full/1280x720/mp4_libx264_libfaac/";
private final String[] mMedias = {
@@ -27,10 +23,6 @@
"bbb_full.ffmpeg.1280x720.mp4.libx264_1750kbps_30fps.libfaac_stereo_192kbps_48000Hz.mp4"
};
- public H264R720pAacLongPlayerTest() {
- super(CamcorderProfile.QUALITY_720P, VideoEncoder.H264, AudioEncoder.AAC);
- }
-
public void testPlay00() throws Exception {
doTestVideoPlaybackLong(0);
}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/H264R720pAacShortPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/H264R720pAacShortPlayerTest.java
index a6f162d..0fba0f3 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/H264R720pAacShortPlayerTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/H264R720pAacShortPlayerTest.java
@@ -16,10 +16,6 @@
package android.mediastress.cts;
-import android.media.CamcorderProfile;
-import android.media.MediaRecorder.AudioEncoder;
-import android.media.MediaRecorder.VideoEncoder;
-
public class H264R720pAacShortPlayerTest extends MediaPlayerStressTest {
private static final String VIDEO_PATH_MIDDLE = "bbb_short/1280x720/mp4_libx264_libfaac/";
private final String[] mMedias = {
@@ -38,10 +34,6 @@
"bbb_short.ffmpeg.1280x720.mp4.libx264_500kbps_30fps.libfaac_stereo_192kbps_44100Hz.mp4"
};
- public H264R720pAacShortPlayerTest() {
- super(CamcorderProfile.QUALITY_720P, VideoEncoder.H264, AudioEncoder.AAC);
- }
-
public void testPlay00() throws Exception {
doTestVideoPlaybackShort(0);
}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/HEVCR1080pAacLongPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR1080pAacLongPlayerTest.java
index e8a92e0..f396706 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/HEVCR1080pAacLongPlayerTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR1080pAacLongPlayerTest.java
@@ -16,20 +16,12 @@
package android.mediastress.cts;
-import android.media.CamcorderProfile;
-import android.media.MediaRecorder.AudioEncoder;
-import android.media.MediaRecorder.VideoEncoder;
-
public class HEVCR1080pAacLongPlayerTest extends MediaPlayerStressTest {
private static final String VIDEO_PATH_MIDDLE = "bbb_full/1920x1080/mp4_libx265_libfaac/";
private final String[] mMedias = {
"bbb_full.ffmpeg.1920x1080.mp4.libx265_6500kbps_30fps.libfaac_stereo_128kbps_48000Hz.mp4"
};
- public HEVCR1080pAacLongPlayerTest() {
- super(CamcorderProfile.QUALITY_1080P, VideoEncoder.H264, AudioEncoder.AAC);
- }
-
public void testPlay00() throws Exception {
doTestVideoPlaybackLong(0);
}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/HEVCR1080pAacRepeatedPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR1080pAacRepeatedPlayerTest.java
index 7ce3c3a..879ac6e 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/HEVCR1080pAacRepeatedPlayerTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR1080pAacRepeatedPlayerTest.java
@@ -16,20 +16,12 @@
package android.mediastress.cts;
-import android.media.CamcorderProfile;
-import android.media.MediaRecorder.AudioEncoder;
-import android.media.MediaRecorder.VideoEncoder;
-
public class HEVCR1080pAacRepeatedPlayerTest extends MediaPlayerStressTest {
private static final String VIDEO_PATH_MIDDLE = "bbb_short/1920x1080/mp4_libx265_libfaac/";
private final String[] mMedias = {
"bbb_short.fmpeg.1920x1080.mp4.libx265_6500kbps_30fps.libfaac_stereo_128kbps_48000hz.mp4",
};
- public HEVCR1080pAacRepeatedPlayerTest() {
- super(CamcorderProfile.QUALITY_1080P, VideoEncoder.H264, AudioEncoder.AAC);
- }
-
public void testPlay00() throws Exception {
doTestVideoPlaybackRepeated(0);
}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/HEVCR1080pAacShortPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR1080pAacShortPlayerTest.java
index 1d12b8c..eebe643 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/HEVCR1080pAacShortPlayerTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR1080pAacShortPlayerTest.java
@@ -16,10 +16,6 @@
package android.mediastress.cts;
-import android.media.CamcorderProfile;
-import android.media.MediaRecorder.AudioEncoder;
-import android.media.MediaRecorder.VideoEncoder;
-
public class HEVCR1080pAacShortPlayerTest extends MediaPlayerStressTest {
private static final String VIDEO_PATH_MIDDLE = "bbb_short/1920x1080/mp4_libx265_libfaac/";
private final String[] mMedias = {
@@ -28,10 +24,6 @@
"bbb_short.fmpeg.1920x1080.mp4.libx265_3250kbps_30fps.libfaac_stereo_128kbps_48000hz.mp4"
};
- public HEVCR1080pAacShortPlayerTest() {
- super(CamcorderProfile.QUALITY_1080P, VideoEncoder.H264, AudioEncoder.AAC);
- }
-
public void testPlay00() throws Exception {
doTestVideoPlaybackShort(0);
}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/HEVCR480pAacLongPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR480pAacLongPlayerTest.java
index e54c51f..704a0d0 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/HEVCR480pAacLongPlayerTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR480pAacLongPlayerTest.java
@@ -16,20 +16,12 @@
package android.mediastress.cts;
-import android.media.CamcorderProfile;
-import android.media.MediaRecorder.AudioEncoder;
-import android.media.MediaRecorder.VideoEncoder;
-
public class HEVCR480pAacLongPlayerTest extends MediaPlayerStressTest {
private static final String VIDEO_PATH_MIDDLE = "bbb_full/720x480/mp4_libx265_libfaac/";
private final String[] mMedias = {
"bbb_full.ffmpeg.720x480.mp4.libx265_325kbps_24fps.libfaac_stereo_128kbps_48000Hz.mp4"
};
- public HEVCR480pAacLongPlayerTest() {
- super(CamcorderProfile.QUALITY_480P, VideoEncoder.H264, AudioEncoder.AAC);
- }
-
public void testPlay00() throws Exception {
doTestVideoPlaybackLong(0);
}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/HEVCR480pAacShortPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR480pAacShortPlayerTest.java
index 2b64abd..d1ab245 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/HEVCR480pAacShortPlayerTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR480pAacShortPlayerTest.java
@@ -16,10 +16,6 @@
package android.mediastress.cts;
-import android.media.CamcorderProfile;
-import android.media.MediaRecorder.AudioEncoder;
-import android.media.MediaRecorder.VideoEncoder;
-
public class HEVCR480pAacShortPlayerTest extends MediaPlayerStressTest {
private static final String VIDEO_PATH_MIDDLE = "bbb_short/720x480/mp4_libx265_libfaac/";
private final String[] mMedias = {
@@ -31,10 +27,6 @@
"bbb_short.fmpeg.720x480.mp4.libx265_325kbps_30fps.libfaac_stereo_128kbps_48000hz.mp4"
};
- public HEVCR480pAacShortPlayerTest() {
- super(CamcorderProfile.QUALITY_480P, VideoEncoder.H264, AudioEncoder.AAC);
- }
-
public void testPlay00() throws Exception {
doTestVideoPlaybackShort(0);
}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/HEVCR480x360AacShortPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR480x360AacShortPlayerTest.java
index 2099916..78139ce 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/HEVCR480x360AacShortPlayerTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR480x360AacShortPlayerTest.java
@@ -16,10 +16,6 @@
package android.mediastress.cts;
-import android.media.CamcorderProfile;
-import android.media.MediaRecorder.AudioEncoder;
-import android.media.MediaRecorder.VideoEncoder;
-
public class HEVCR480x360AacShortPlayerTest extends MediaPlayerStressTest {
private static final String VIDEO_PATH_MIDDLE = "bbb_short/480x360/mp4_libx265_libfaac/";
private final String[] mMedias = {
@@ -31,10 +27,6 @@
"bbb_short.fmpeg.480x360.mp4.libx265_325kbps_30fps.libfaac_stereo_128kbps_48000hz.mp4"
};
- public HEVCR480x360AacShortPlayerTest() {
- super(CamcorderProfile.QUALITY_480P, VideoEncoder.H264, AudioEncoder.AAC);
- }
-
public void testPlay00() throws Exception {
doTestVideoPlaybackShort(0);
}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/HEVCR720pAacLongPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR720pAacLongPlayerTest.java
index 540f78a..bf6b787 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/HEVCR720pAacLongPlayerTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR720pAacLongPlayerTest.java
@@ -16,10 +16,6 @@
package android.mediastress.cts;
-import android.media.CamcorderProfile;
-import android.media.MediaRecorder.AudioEncoder;
-import android.media.MediaRecorder.VideoEncoder;
-
public class HEVCR720pAacLongPlayerTest extends MediaPlayerStressTest {
private static final String VIDEO_PATH_MIDDLE = "bbb_full/1280x720/mp4_libx265_libfaac/";
private final String[] mMedias = {
@@ -27,10 +23,6 @@
"bbb_full.ffmpeg.1280x720.mp4.libx265_1140kbps_30fps.libfaac_stereo_128kbps_48000Hz.mp4"
};
- public HEVCR720pAacLongPlayerTest() {
- super(CamcorderProfile.QUALITY_720P, VideoEncoder.H264, AudioEncoder.AAC);
- }
-
public void testPlay00() throws Exception {
doTestVideoPlaybackLong(0);
}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/HEVCR720pAacShortPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR720pAacShortPlayerTest.java
index dd93dfc..7c42e83 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/HEVCR720pAacShortPlayerTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/HEVCR720pAacShortPlayerTest.java
@@ -16,10 +16,6 @@
package android.mediastress.cts;
-import android.media.CamcorderProfile;
-import android.media.MediaRecorder.AudioEncoder;
-import android.media.MediaRecorder.VideoEncoder;
-
public class HEVCR720pAacShortPlayerTest extends MediaPlayerStressTest {
private static final String VIDEO_PATH_MIDDLE = "bbb_short/1280x720/mp4_libx265_libfaac/";
private final String[] mMedias = {
@@ -34,10 +30,6 @@
"bbb_short.fmpeg.1280x720.mp4.libx265_6500kbps_30fps.libfaac_stereo_128kbps_48000hz.mp4"
};
- public HEVCR720pAacShortPlayerTest() {
- super(CamcorderProfile.QUALITY_720P, VideoEncoder.H264, AudioEncoder.AAC);
- }
-
public void testPlay00() throws Exception {
doTestVideoPlaybackShort(0);
}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/MediaPlayerStressTest.java b/tests/tests/mediastress/src/android/mediastress/cts/MediaPlayerStressTest.java
index 05bfb42..7c65824 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/MediaPlayerStressTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/MediaPlayerStressTest.java
@@ -20,6 +20,7 @@
import android.app.Instrumentation;
import android.content.Intent;
import android.media.CamcorderProfile;
+import android.cts.util.MediaUtils;
import android.media.MediaRecorder.AudioEncoder;
import android.media.MediaRecorder.VideoEncoder;
import android.os.Environment;
@@ -42,22 +43,6 @@
protected static final int REPEAT_NUMBER_FOR_LONG_CLIPS = 1;
protected static final int REPEAT_NUMBER_FOR_REPEATED_PLAYBACK = 20;
private static final String TAG = "MediaPlayerStressTest";
- // whether a video format is supported or not.
- private final boolean mSupported;
-
- /**
- * construct a test case with check of whether the format is supported or not.
- * @param quality
- * @param videoCodec
- * @param audioCodec
- */
- protected MediaPlayerStressTest(int quality, int videoCodec, int audioCodec) {
- mSupported = VideoPlayerCapability.formatSupported(quality, videoCodec, audioCodec);
- }
-
- protected MediaPlayerStressTest() {
- mSupported = true; // supported if nothing specified
- }
/**
* provides full path name of video clip for the given media number
@@ -120,11 +105,6 @@
* @throws Exception
*/
protected void doTestVideoPlayback(int mediaNumber, int repeatCounter) throws Exception {
- if (!mSupported) {
- Log.i(TAG, "Not supported!");
- return;
- }
-
File playbackOutput = new File(WorkDir.getTopDir(), "PlaybackTestResult.txt");
Writer output = new BufferedWriter(new FileWriter(playbackOutput, true));
@@ -140,6 +120,9 @@
Activity act = inst.startActivitySync(intent);
String mediaName = getFullVideoClipName(mediaNumber);
+ if (!MediaUtils.checkCodecsForPath(inst.getTargetContext(), mediaName)) {
+ return; // not supported, message is already logged
+ }
for (int i = 0; i < repeatCounter; i++) {
Log.v(TAG, "start playing " + mediaName);
onCompleteSuccess =
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/VideoPlayerCapability.java b/tests/tests/mediastress/src/android/mediastress/cts/VideoPlayerCapability.java
deleted file mode 100644
index f8dd2aa..0000000
--- a/tests/tests/mediastress/src/android/mediastress/cts/VideoPlayerCapability.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.mediastress.cts;
-
-import android.media.CamcorderProfile;
-import android.util.Log;
-
-import junit.framework.Assert;
-
-public class VideoPlayerCapability {
- private static final String TAG = "VideoPlayCapability";
-
- static boolean formatSupported(int quality, int videoCodec, int audioCodec) {
- if (!CamcorderProfile.hasProfile(quality)) {
- Log.i(TAG, "quality " + quality + " not supported");
- return false;
- }
- CamcorderProfile profile = CamcorderProfile.get(quality);
- Assert.assertNotNull(profile);
- if ((profile.videoCodec == videoCodec) && (profile.audioCodec == audioCodec)) {
- Log.i(TAG, "quality " + quality + " video codec " + videoCodec + " audio codec " +
- audioCodec + " supproted");
- return true;
- }
- return false;
- }
-
-}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/Vp8R480x360LongPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/Vp8R480x360LongPlayerTest.java
index 6b43558..372f034 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/Vp8R480x360LongPlayerTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/Vp8R480x360LongPlayerTest.java
@@ -16,20 +16,12 @@
package android.mediastress.cts;
-import android.media.CamcorderProfile;
-import android.media.MediaRecorder.AudioEncoder;
-import android.media.MediaRecorder.VideoEncoder;
-
public class Vp8R480x360LongPlayerTest extends MediaPlayerStressTest {
private static final String VIDEO_PATH_MIDDLE = "bbb_full/480x360/webm_libvpx_libvorbis/";
private final String[] mMedias = {
"bbb_full.ffmpeg.480x360.webm.libvpx_500kbps_25fps.libvorbis_stereo_128kbps_44100Hz.webm"
};
- public Vp8R480x360LongPlayerTest() {
- super(CamcorderProfile.QUALITY_480P, VideoEncoder.VP8, AudioEncoder.VORBIS);
- }
-
public void testPlay00() throws Exception {
doTestVideoPlaybackLong(0);
}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/Vp8R480x360ShortPlayerTest.java b/tests/tests/mediastress/src/android/mediastress/cts/Vp8R480x360ShortPlayerTest.java
index 737032b..30b4d2e 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/Vp8R480x360ShortPlayerTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/Vp8R480x360ShortPlayerTest.java
@@ -16,10 +16,6 @@
package android.mediastress.cts;
-import android.media.CamcorderProfile;
-import android.media.MediaRecorder.AudioEncoder;
-import android.media.MediaRecorder.VideoEncoder;
-
public class Vp8R480x360ShortPlayerTest extends MediaPlayerStressTest {
private static final String VIDEO_PATH_MIDDLE = "bbb_short/480x360/webm_libvpx_libvorbis/";
private final String[] mMedias = {
@@ -37,10 +33,6 @@
"bbb_short.ffmpeg.480x360.webm.libvpx_500kbps_30fps.libvorbis_stereo_192kbps_44100Hz.webm"
};
- public Vp8R480x360ShortPlayerTest() {
- super(CamcorderProfile.QUALITY_480P, VideoEncoder.VP8, AudioEncoder.VORBIS);
- }
-
public void testPlay00() throws Exception {
doTestVideoPlaybackShort(0);
}
diff --git a/tests/tests/os/src/android/os/cts/BuildVersionTest.java b/tests/tests/os/src/android/os/cts/BuildVersionTest.java
index e335901..3002ca3 100644
--- a/tests/tests/os/src/android/os/cts/BuildVersionTest.java
+++ b/tests/tests/os/src/android/os/cts/BuildVersionTest.java
@@ -29,7 +29,7 @@
private static final String LOG_TAG = "BuildVersionTest";
private static final Set<String> EXPECTED_RELEASES =
- new HashSet<String>(Arrays.asList("5.0", "5.0.1", "5.0.2"));
+ new HashSet<String>(Arrays.asList("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/Android.mk b/tests/tests/security/Android.mk
index de58783..c41ee58 100644
--- a/tests/tests/security/Android.mk
+++ b/tests/tests/security/Android.mk
@@ -34,22 +34,6 @@
LOCAL_SDK_VERSION := current
-intermediates.COMMON := $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),,COMMON)
-
-sepolicy_asset_dir := $(intermediates.COMMON)/assets
-
-LOCAL_ASSET_DIR := $(sepolicy_asset_dir)
-
include $(BUILD_CTS_PACKAGE)
-selinux_policy.xml := $(sepolicy_asset_dir)/selinux_policy.xml
-selinux_policy_parser := cts/tools/selinux/src/gen_SELinux_CTS.py
-general_sepolicy_policy.conf := $(call intermediates-dir-for,ETC,general_sepolicy.conf)/general_sepolicy.conf
-$(selinux_policy.xml): PRIVATE_POLICY_PARSER := $(selinux_policy_parser)
-$(selinux_policy.xml): $(general_sepolicy_policy.conf) $(selinux_policy_parser)
- mkdir -p $(dir $@)
- $(PRIVATE_POLICY_PARSER) $< $@ neverallow_only=t
-
-$(R_file_stamp): $(selinux_policy.xml)
-
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/security/jni/Android.mk b/tests/tests/security/jni/Android.mk
index 336b09d..69ccdf0 100644
--- a/tests/tests/security/jni/Android.mk
+++ b/tests/tests/security/jni/Android.mk
@@ -33,8 +33,7 @@
android_security_cts_MMapExecutableTest.cpp \
android_security_cts_NetlinkSocket.cpp \
android_security_cts_AudioPolicyBinderTest.cpp \
- android_security_cts_AudioflingerBinderTest.cpp \
- android_security_cts_MediaPlayerInfoLeakTest.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 0d2e6e7..22e0997 100644
--- a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
+++ b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
@@ -28,7 +28,6 @@
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);
-extern int register_android_security_cts_MediaPlayerInfoLeakTest(JNIEnv* env);
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *env = NULL;
@@ -81,9 +80,5 @@
return JNI_ERR;
}
- if (register_android_security_cts_MediaPlayerInfoLeakTest(env)) {
- return JNI_ERR;
- }
-
return JNI_VERSION_1_4;
}
diff --git a/tests/tests/security/jni/android_security_cts_AudioPolicyBinderTest.cpp b/tests/tests/security/jni/android_security_cts_AudioPolicyBinderTest.cpp
index fd93387..9daa2cb 100644
--- a/tests/tests/security/jni/android_security_cts_AudioPolicyBinderTest.cpp
+++ b/tests/tests/security/jni/android_security_cts_AudioPolicyBinderTest.cpp
@@ -18,7 +18,6 @@
#include <jni.h>
#include <binder/IServiceManager.h>
-#include <binder/Parcel.h>
#include <media/IAudioPolicyService.h>
#include <media/AudioSystem.h>
#include <system/audio.h>
@@ -154,32 +153,6 @@
return true;
}
-jint android_security_cts_AudioPolicy_test_getStreamVolumeLeak(JNIEnv* env __unused,
- jobject thiz __unused)
-{
- sp<IAudioPolicyService> aps;
-
- if (!init(aps, NULL, NULL)) {
- return -1;
- }
-
- // Keep synchronized with IAudioPolicyService.cpp!
- enum {
- GET_STREAM_VOLUME = 17,
- };
-
- Parcel data, reply;
- status_t err;
- data.writeInterfaceToken(aps->getInterfaceDescriptor());
- data.writeInt32(-1); // stream type
- data.writeInt32(-1); // device
- aps->asBinder()->transact(GET_STREAM_VOLUME, data, &reply);
- int index = reply.readInt32();
- err = reply.readInt32();
-
- return index;
-}
-
static JNINativeMethod gMethods[] = {
{ "native_test_startOutput", "()Z",
(void *) android_security_cts_AudioPolicy_test_startOutput },
@@ -187,8 +160,6 @@
(void *) android_security_cts_AudioPolicy_test_stopOutput },
{ "native_test_isStreamActive", "()Z",
(void *) android_security_cts_AudioPolicy_test_isStreamActive },
- { "native_test_getStreamVolumeLeak", "()I",
- (void *) android_security_cts_AudioPolicy_test_getStreamVolumeLeak },
};
int register_android_security_cts_AudioPolicyBinderTest(JNIEnv* env)
diff --git a/tests/tests/security/jni/android_security_cts_MediaPlayerInfoLeakTest.cpp b/tests/tests/security/jni/android_security_cts_MediaPlayerInfoLeakTest.cpp
deleted file mode 100644
index 41262ac..0000000
--- a/tests/tests/security/jni/android_security_cts_MediaPlayerInfoLeakTest.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * 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 "MediaPlayerInfoLeakTest-JNI"
-
-#include <jni.h>
-
-#include <binder/Parcel.h>
-#include <binder/IServiceManager.h>
-
-#include <media/IMediaPlayer.h>
-#include <media/IMediaPlayerService.h>
-#include <media/IMediaPlayerClient.h>
-
-#include <sys/stat.h>
-
-using namespace android;
-
-static status_t connectMediaPlayer(sp<IMediaPlayer>& iMP)
-{
- sp<IServiceManager> sm = defaultServiceManager();
- sp<IBinder> mediaPlayerService = sm->checkService(String16("media.player"));
-
- sp<IMediaPlayerService> iMPService = IMediaPlayerService::asInterface(mediaPlayerService);
- sp<IMediaPlayerClient> client;
- Parcel data, reply;
- int dummyAudioSessionId = 1;
- data.writeInterfaceToken(iMPService->getInterfaceDescriptor());
- data.writeStrongBinder(client->asBinder());
- data.writeInt32(dummyAudioSessionId);
-
- // Keep synchronized with IMediaPlayerService.cpp!
- enum {
- CREATE = IBinder::FIRST_CALL_TRANSACTION,
- };
- status_t err = iMPService->asBinder()->transact(CREATE, data, &reply);
-
- if (err == NO_ERROR) {
- iMP = interface_cast<IMediaPlayer>(reply.readStrongBinder());
- }
- return err;
-}
-
-int testMediaPlayerInfoLeak(int command)
-{
- sp<IMediaPlayer> iMP;
- if (NO_ERROR != connectMediaPlayer(iMP)) {
- return false;
- }
-
-
- Parcel data, reply;
- data.writeInterfaceToken(iMP->getInterfaceDescriptor());
- iMP->asBinder()->transact(command, data, &reply);
-
- int leak = reply.readInt32();
- status_t err = reply.readInt32();
- return leak;
-}
-
-jint android_security_cts_MediaPlayer_test_getCurrentPositionLeak(JNIEnv* env __unused,
- jobject thiz __unused)
-{
- // Keep synchronized with IMediaPlayer.cpp!
- enum {
- GET_CURRENT_POSITION = 11,
- };
- return testMediaPlayerInfoLeak(GET_CURRENT_POSITION);
-}
-
-jint android_security_cts_MediaPlayer_test_getDurationLeak(JNIEnv* env __unused,
- jobject thiz __unused)
-{
- // Keep synchronized with IMediaPlayer.cpp!
- enum {
- GET_DURATION = 12,
- };
- return testMediaPlayerInfoLeak(GET_DURATION);
-}
-
-static JNINativeMethod gMethods[] = {
- { "native_test_getCurrentPositionLeak", "()I",
- (void *) android_security_cts_MediaPlayer_test_getCurrentPositionLeak },
- { "native_test_getDurationLeak", "()I",
- (void *) android_security_cts_MediaPlayer_test_getDurationLeak },
-};
-
-int register_android_security_cts_MediaPlayerInfoLeakTest(JNIEnv* env)
-{
- jclass clazz = env->FindClass("android/security/cts/MediaPlayerInfoLeakTest");
- return env->RegisterNatives(clazz, gMethods,
- sizeof(gMethods) / sizeof(JNINativeMethod));
-}
diff --git a/tests/tests/security/src/android/security/cts/AudioPolicyBinderTest.java b/tests/tests/security/src/android/security/cts/AudioPolicyBinderTest.java
index daa7c83..399d8bb 100644
--- a/tests/tests/security/src/android/security/cts/AudioPolicyBinderTest.java
+++ b/tests/tests/security/src/android/security/cts/AudioPolicyBinderTest.java
@@ -48,17 +48,7 @@
assertTrue(native_test_isStreamActive());
}
- /**
- * Checks that IAudioPolicyService::getStreamVolumeIndex() does not leak information
- * when called with an invalid stream/device type.
- */
- public void test_getStreamVolumeLeak() throws Exception {
- int volume = native_test_getStreamVolumeLeak();
- assertTrue(String.format("Leaked volume 0x%08X", volume), volume == 0);
- }
-
private static native boolean native_test_startOutput();
private static native boolean native_test_stopOutput();
private static native boolean native_test_isStreamActive();
- private static native int native_test_getStreamVolumeLeak();
}
diff --git a/tests/tests/security/src/android/security/cts/MediaPlayerInfoLeakTest.java b/tests/tests/security/src/android/security/cts/MediaPlayerInfoLeakTest.java
deleted file mode 100644
index e34fc05..0000000
--- a/tests/tests/security/src/android/security/cts/MediaPlayerInfoLeakTest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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 MediaPlayerInfoLeakTest extends TestCase {
-
- static {
- System.loadLibrary("ctssecurity_jni");
- }
-
-
- /**
- * Checks that IMediaPlayer::getCurrentPosition() does not leak info in error case
- */
- public void test_getCurrentPositionLeak() throws Exception {
- int pos = native_test_getCurrentPositionLeak();
- assertTrue(String.format("Leaked pos 0x%08X", pos), pos == 0);
- }
-
- /**
- * Checks that IMediaPlayer::getDuration() does not leak info in error case
- */
- public void test_getDurationLeak() throws Exception {
- int dur = native_test_getDurationLeak();
- assertTrue(String.format("Leaked dur 0x%08X", dur), dur == 0);
- }
-
- private static native int native_test_getCurrentPositionLeak();
- private static native int native_test_getDurationLeak();
-}
diff --git a/tests/tests/security/src/android/security/cts/SELinuxPolicyRule.java b/tests/tests/security/src/android/security/cts/SELinuxPolicyRule.java
deleted file mode 100644
index d06fd75..0000000
--- a/tests/tests/security/src/android/security/cts/SELinuxPolicyRule.java
+++ /dev/null
@@ -1,162 +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 android.security.cts;
-
-import android.util.Xml;
-
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.InputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.HashMap;
-
-
-/**
- * A class for generating representations of SELinux avc rules parsed from an xml file.
- */
-public class SELinuxPolicyRule {
- public final List<String> source_types;
- public final List<String> target_types;
- public final Multimap<String, String> obj_classes;
- public final String name;
- public final String type;
-
- private SELinuxPolicyRule(List<String> source_types, List<String> target_types,
- Multimap<String, String> obj_classes, String name, String type) {
- this.source_types = source_types;
- this.target_types = target_types;
- this.obj_classes = obj_classes;
- this.name = name;
- this.type = type;
- }
-
- public static SELinuxPolicyRule readRule(XmlPullParser xpp) throws IOException, XmlPullParserException {
- List<String> source_types = new ArrayList<String>();
- List<String> target_types = new ArrayList<String>();
- Multimap<String, String> obj_classes = HashMultimap.create();
- xpp.require(XmlPullParser.START_TAG, null, "avc_rule");
- String ruleName = xpp.getAttributeValue(null, "name");
- String ruleType = xpp.getAttributeValue(null, "type");
- while (xpp.next() != XmlPullParser.END_TAG) {
- if (xpp.getEventType() != XmlPullParser.START_TAG) {
- continue;
- }
- String name = xpp.getName();
- if (name.equals("type")) {
- if (xpp.getAttributeValue(null, "type").equals("source")) {
- source_types.add(readType(xpp));
- } else if (xpp.getAttributeValue(null, "type").equals("target")) {
- target_types.add(readType(xpp));
- } else {
- skip(xpp);
- }
- } else if (name.equals("obj_class")) {
- String obj_name = xpp.getAttributeValue(null, "name");
- List<String> perms = readObjClass(xpp);
- obj_classes.putAll(obj_name, perms);
- } else {
- skip(xpp);
- }
- }
- return new SELinuxPolicyRule(source_types, target_types, obj_classes, ruleName, ruleType);
- }
-
- public static List<SELinuxPolicyRule> readRulesFile(InputStream in) throws IOException, XmlPullParserException {
- List<SELinuxPolicyRule> rules = new ArrayList<SELinuxPolicyRule>();
- XmlPullParser xpp = Xml.newPullParser();
- xpp.setInput(in, null);
- xpp.nextTag();
- xpp.require(XmlPullParser.START_TAG, null, "SELinux_AVC_Rules");
-
- /* read rules */
- while (xpp.next() != XmlPullParser.END_TAG) {
- if (xpp.getEventType() != XmlPullParser.START_TAG) {
- continue;
- }
- String name = xpp.getName();
- if (name.equals("avc_rule")) {
- SELinuxPolicyRule r = readRule(xpp);
- rules.add(r);
- } else {
- skip(xpp);
- }
- }
- return rules;
- }
-
- private static List<String> readObjClass(XmlPullParser xpp) throws IOException, XmlPullParserException {
- List<String> perms = new ArrayList<String>();
- xpp.require(XmlPullParser.START_TAG, null, "obj_class");
- while (xpp.next() != XmlPullParser.END_TAG) {
- if (xpp.getEventType() != XmlPullParser.START_TAG) {
- continue;
- }
- String name = xpp.getName();
- if (name.equals("permission")) {
- perms.add(readPermission(xpp));
- } else {
- skip(xpp);
- }
- }
- return perms;
- }
-
- private static String readType(XmlPullParser xpp) throws IOException, XmlPullParserException {
- xpp.require(XmlPullParser.START_TAG, null, "type");
- String type = readText(xpp);
- xpp.require(XmlPullParser.END_TAG, null, "type");
- return type;
- }
-
- private static String readPermission(XmlPullParser xpp) throws IOException, XmlPullParserException {
- xpp.require(XmlPullParser.START_TAG, null, "permission");
- String permission = readText(xpp);
- xpp.require(XmlPullParser.END_TAG, null, "permission");
- return permission;
- }
-
- private static String readText(XmlPullParser xpp) throws IOException, XmlPullParserException {
- String result = "";
- if (xpp.next() == XmlPullParser.TEXT) {
- result = xpp.getText();
- xpp.nextTag();
- }
- return result;
- }
-
- public static void skip(XmlPullParser xpp) throws XmlPullParserException, IOException {
- if (xpp.getEventType() != XmlPullParser.START_TAG) {
- throw new IllegalStateException();
- }
- int depth = 1;
- while (depth != 0) {
- switch (xpp.next()) {
- case XmlPullParser.END_TAG:
- depth--;
- break;
- case XmlPullParser.START_TAG:
- depth++;
- break;
- }
- }
- }
-}
diff --git a/tests/tests/security/src/android/security/cts/SELinuxTest.java b/tests/tests/security/src/android/security/cts/SELinuxTest.java
index 8e57037..711cb91 100644
--- a/tests/tests/security/src/android/security/cts/SELinuxTest.java
+++ b/tests/tests/security/src/android/security/cts/SELinuxTest.java
@@ -18,7 +18,6 @@
import android.content.Context;
import android.content.res.AssetManager;
-import android.security.cts.SELinuxPolicyRule;
import android.test.AndroidTestCase;
import junit.framework.TestCase;
@@ -82,130 +81,6 @@
assertEquals(0, files.length);
}
- /**
- * Verify all of the rules described by the selinux_policy.xml file are in effect. Allow rules
- * should return access granted, and Neverallow should return access denied. All checks are run
- * and then a list of specific failed checks is printed.
- */
- public void testSELinuxPolicyFile() throws IOException, XmlPullParserException {
- List<String> failedChecks = new ArrayList<String>();
- Map<String, Boolean> contextsCache = new HashMap<String, Boolean>();
- int invalidContextsCount = 0;
- int totalChecks = 0;
- int totalFailedChecks = 0;
- AssetManager assets = mContext.getAssets();
- InputStream in = assets.open("selinux_policy.xml");
- Collection<SELinuxPolicyRule> rules = SELinuxPolicyRule.readRulesFile(in);
- for (SELinuxPolicyRule r : rules) {
- PolicyFileTestResult result = runRuleChecks(r, contextsCache);
- totalChecks += result.numTotalChecks;
- if (result.numFailedChecks != 0) {
- totalFailedChecks += result.numFailedChecks;
-
- /* print failures to log, so as not to run OOM in the event of large policy mismatch,
- but record actual rule type and number */
- failedChecks.add("SELinux avc rule " + r.type + r.name + " failed " + result.numFailedChecks +
- " out of " + result.numTotalChecks + " checks.");
- for (String k : result.failedChecks) {
- System.out.println(r.type + r.name + " failed " + k);
- }
- }
- }
- if (totalFailedChecks != 0) {
-
- /* print out failed rules, just the rule number and type */
- for (String k : failedChecks) {
- System.out.println(k);
- }
- System.out.println("Failed SELinux Policy Test: " + totalFailedChecks + " failed out of " + totalChecks);
- }
- for (String k : contextsCache.keySet()) {
- if (!contextsCache.get(k)) {
- invalidContextsCount++;
- System.out.println("Invalid SELinux context encountered: " + k);
- }
- }
- System.out.println("SELinuxPolicy Test Encountered: " + invalidContextsCount + " missing contexts out of " + contextsCache.size());
- assertTrue(totalFailedChecks == 0);
- }
-
- /**
- * A class for containing all of the results we care to know from checking each SELinux rule
- */
- private class PolicyFileTestResult {
- private int numTotalChecks;
- private int numFailedChecks;
- private List<String> failedChecks = new ArrayList<String>();
- }
-
- private PolicyFileTestResult runRuleChecks(SELinuxPolicyRule r, Map<String, Boolean> contextsCache) {
- PolicyFileTestResult result = new PolicyFileTestResult();
-
- /* run checks by going through every possible 4-tuple specified by rule. Start with class
- and perm to allow early-exit based on context. */
- for (String c : r.obj_classes.keySet()) {
- for (String p : r.obj_classes.get(c)) {
- for (String s : r.source_types) {
-
- /* check source context */
- String source_context = createAvcContext(s, false, c, p);
- if (!contextsCache.containsKey(source_context)) {
- contextsCache.put(source_context, checkSELinuxContext(source_context));
- }
- if (!contextsCache.get(source_context)) {
- continue;
- }
- for (String t : r.target_types) {
- if (t.equals("self")) {
- t = s;
- }
-
- /* check target context */
- String target_context = createAvcContext(t, true, c, p);
- if (!contextsCache.containsKey(target_context)) {
- contextsCache.put(target_context, checkSELinuxContext(target_context));
- }
- if (!contextsCache.get(target_context)) {
- continue;
- }
- boolean canAccess = checkSELinuxAccess(source_context, target_context,
- c, p, "");
- result.numTotalChecks++;
- if ((r.type.equals("allow") && !canAccess)
- || (r.type.equals("neverallow") && canAccess)) {
- String failureNotice = s + ", " + t + ", " + c + ", " + p;
- result.numFailedChecks++;
- result.failedChecks.add(failureNotice);
- }
- }
- }
- }
- }
- return result;
- }
-
- /* createAvcContext - currently uses class type and perm to determine user, role and mls values.
- *
- * @param target - false if source domain, true if target.
- */
- private String createAvcContext(String domain, boolean target,
- String obj_class, String perm) {
- String usr = "u";
- String role;
-
- /* understand role labeling better */
- if (obj_class.equals("filesystem") && perm.equals("associate")) {
- role = "object_r";
- } else if(obj_class.equals("process") || obj_class.endsWith("socket")) {
- role = "r";
- } else if (target) {
- role = "object_r";
- } else {
- role = "r";
- }
- return String.format("%s:%s:%s:s0", usr, role, domain);
- }
-
private static native boolean checkSELinuxAccess(String scon, String tcon, String tclass, String perm, String extra);
private static native boolean checkSELinuxContext(String con);
diff --git a/tests/tests/text/src/android/text/format/cts/TimeTest.java b/tests/tests/text/src/android/text/format/cts/TimeTest.java
index 2d623e3..cc73272 100644
--- a/tests/tests/text/src/android/text/format/cts/TimeTest.java
+++ b/tests/tests/text/src/android/text/format/cts/TimeTest.java
@@ -36,16 +36,20 @@
private Locale originalLocale;
+ private static List<Locale> sSystemLocales;
+
@Override
protected void setUp() throws Exception {
super.setUp();
originalLocale = Locale.getDefault();
+
+ maybeInitializeSystemLocales();
}
@Override
public void tearDown() throws Exception {
// The Locale may be changed by tests. Revert to the original.
- changeJavaAndAndroidLocale(originalLocale);
+ changeJavaAndAndroidLocale(originalLocale, true /* force */);
super.tearDown();
}
@@ -771,7 +775,10 @@
}
public void testFormat_tokensUkLocale() throws Exception {
- changeJavaAndAndroidLocale(Locale.UK);
+ if (!changeJavaAndAndroidLocale(Locale.UK, false /* force */)) {
+ Log.w(TAG, "Skipping testFormat_tokensUkLocale: no assets found");
+ return;
+ }
Time t = new Time("Europe/London");
Fields.setDateTime(t, 2005, 5, 1, 12, 30, 15);
@@ -863,7 +870,10 @@
}
public void testFormat_tokensUsLocale() throws Exception {
- changeJavaAndAndroidLocale(Locale.US);
+ if (!changeJavaAndAndroidLocale(Locale.US, false /* force */)) {
+ Log.w(TAG, "Skipping testFormat_tokensUSLocale: no assets found");
+ return;
+ }
Time t = new Time("America/New_York");
Fields.setDateTime(t, 2005, 5, 1, 12, 30, 15);
@@ -955,7 +965,10 @@
}
public void testFormat_tokensFranceLocale() throws Exception {
- changeJavaAndAndroidLocale(Locale.FRANCE);
+ if (!changeJavaAndAndroidLocale(Locale.FRANCE, false /* force */)) {
+ Log.w(TAG, "Skipping testFormat_tokensFranceLocale: no assets found");
+ return;
+ }
Time t = new Time("Europe/Paris");
Fields.setDateTime(t, 2005, 5, 1, 12, 30, 15);
@@ -1047,7 +1060,10 @@
}
public void testFormat_tokensJapanLocale() throws Exception {
- changeJavaAndAndroidLocale(Locale.JAPAN);
+ if (!changeJavaAndAndroidLocale(Locale.JAPAN, false /* force */)) {
+ Log.w(TAG, "Skipping testFormat_tokensJapanLocale: no assets found");
+ return;
+ }
Time t = new Time("Asia/Tokyo");
Fields.setDateTime(t, 2005, 5, 1, 12, 30, 15);
@@ -2843,7 +2859,19 @@
}
}
- private static void changeJavaAndAndroidLocale(Locale locale) {
+ private static void maybeInitializeSystemLocales() {
+ if (sSystemLocales == null) {
+ String[] locales = Resources.getSystem().getAssets().getLocales();
+ List<Locale> systemLocales = new ArrayList<Locale>(locales.length);
+ for (String localeStr : locales) {
+ systemLocales.add(Locale.forLanguageTag(localeStr));
+ }
+
+ sSystemLocales = systemLocales;
+ }
+ }
+
+ private static boolean changeJavaAndAndroidLocale(Locale locale, boolean force) {
// The Time class uses the Android-managed locale for string resources containing format
// patterns and the Java-managed locale for other things (e.g. month names, week days names)
// that are placed into those patterns. For example the format "%c" expands to include
@@ -2856,6 +2884,10 @@
// locales agree), when the Java-managed locale is changed during this test the locale in
// the runtime-local copy of the system resources is modified as well.
+ if (!force && !sSystemLocales.contains(locale)) {
+ return false;
+ }
+
// Change the Java-managed locale.
Locale.setDefault(locale);
@@ -2864,5 +2896,6 @@
Configuration configuration = Resources.getSystem().getConfiguration();
configuration.locale = locale;
Resources.getSystem().updateConfiguration(configuration, null);
+ return true;
}
}
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
index 1e22acc..b381d72 100755
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
@@ -1557,6 +1557,37 @@
assertEquals(1, handler.getMsgArg1());
}
+ private static void waitForFlingDone(WebViewOnUiThread webview) {
+ class ScrollDiffPollingCheck extends PollingCheck {
+ private static final long TIME_SLICE = 50;
+ WebViewOnUiThread mWebView;
+ private int mScrollX;
+ private int mScrollY;
+
+ ScrollDiffPollingCheck(WebViewOnUiThread webview) {
+ mWebView = webview;
+ mScrollX = mWebView.getScrollX();
+ mScrollY = mWebView.getScrollY();
+ }
+
+ @Override
+ protected boolean check() {
+ try {
+ Thread.sleep(TIME_SLICE);
+ } catch (InterruptedException e) {
+ // Intentionally ignored.
+ }
+ int newScrollX = mWebView.getScrollX();
+ int newScrollY = mWebView.getScrollY();
+ boolean flingDone = newScrollX == mScrollX && newScrollY == mScrollY;
+ mScrollX = newScrollX;
+ mScrollY = newScrollY;
+ return flingDone;
+ }
+ }
+ new ScrollDiffPollingCheck(webview).run();
+ }
+
public void testPageScroll() throws Throwable {
if (!NullWebViewUtils.isWebViewAvailable()) {
return;
@@ -1578,29 +1609,29 @@
}.run();
do {
- getInstrumentation().waitForIdleSync();
+ waitForFlingDone(mOnUiThread);
} while (mOnUiThread.pageDown(false));
- getInstrumentation().waitForIdleSync();
+ waitForFlingDone(mOnUiThread);
int bottomScrollY = mOnUiThread.getScrollY();
assertTrue(mOnUiThread.pageUp(false));
do {
- getInstrumentation().waitForIdleSync();
+ waitForFlingDone(mOnUiThread);
} while (mOnUiThread.pageUp(false));
- getInstrumentation().waitForIdleSync();
+ waitForFlingDone(mOnUiThread);
int topScrollY = mOnUiThread.getScrollY();
// jump to the bottom
assertTrue(mOnUiThread.pageDown(true));
- getInstrumentation().waitForIdleSync();
+ waitForFlingDone(mOnUiThread);
assertEquals(bottomScrollY, mOnUiThread.getScrollY());
// jump to the top
assertTrue(mOnUiThread.pageUp(true));
- getInstrumentation().waitForIdleSync();
+ waitForFlingDone(mOnUiThread);
assertEquals(topScrollY, mOnUiThread.getScrollY());
}
diff --git a/tools/cts-java-scanner/src/com/android/cts/javascanner/CtsJavaScanner.java b/tools/cts-java-scanner/src/com/android/cts/javascanner/CtsJavaScanner.java
index a843fc6..fc774e9 100644
--- a/tools/cts-java-scanner/src/com/android/cts/javascanner/CtsJavaScanner.java
+++ b/tools/cts-java-scanner/src/com/android/cts/javascanner/CtsJavaScanner.java
@@ -16,7 +16,9 @@
package com.android.cts.javascanner;
import java.io.File;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
/**
* Class that searches a source directory for native gTests and outputs a
@@ -31,12 +33,12 @@
}
public static void main(String[] args) throws Exception {
- File sourceDir = null;
+ List<File> sourceDirs = new ArrayList<File>();
File docletPath = null;
for (int i = 0; i < args.length; i++) {
if ("-s".equals(args[i])) {
- sourceDir = new File(getArg(args, ++i, "Missing value for source directory"));
+ sourceDirs.add(new File(getArg(args, ++i, "Missing value for source directory")));
} else if ("-d".equals(args[i])) {
docletPath = new File(getArg(args, ++i, "Missing value for docletPath"));
} else {
@@ -45,7 +47,7 @@
}
}
- if (sourceDir == null) {
+ if (sourceDirs.isEmpty()) {
System.err.println("Source directory is required");
usage(args);
}
@@ -55,7 +57,7 @@
usage(args);
}
- DocletRunner runner = new DocletRunner(sourceDir, docletPath);
+ DocletRunner runner = new DocletRunner(sourceDirs, docletPath);
System.exit(runner.runJavaDoc());
}
diff --git a/tools/cts-java-scanner/src/com/android/cts/javascanner/DocletRunner.java b/tools/cts-java-scanner/src/com/android/cts/javascanner/DocletRunner.java
index 06951b9..94761fb 100644
--- a/tools/cts-java-scanner/src/com/android/cts/javascanner/DocletRunner.java
+++ b/tools/cts-java-scanner/src/com/android/cts/javascanner/DocletRunner.java
@@ -25,11 +25,11 @@
class DocletRunner {
- private final File mSourceDir;
+ private final List<File> mSourceDirs;
private final File mDocletPath;
- DocletRunner(File sourceDir, File docletPath) {
- mSourceDir = sourceDir;
+ DocletRunner(List<File> sourceDirs, File docletPath) {
+ mSourceDirs = sourceDirs;
mDocletPath = docletPath;
}
@@ -41,10 +41,12 @@
args.add("-docletpath");
args.add(mDocletPath.toString());
args.add("-sourcepath");
- args.add(getSourcePath(mSourceDir));
+ args.add(getSourcePath(mSourceDirs));
args.add("-classpath");
args.add(getClassPath());
- args.addAll(getSourceFiles(mSourceDir));
+ for (File sourceDir : mSourceDirs) {
+ args.addAll(getSourceFiles(sourceDir));
+ }
// NOTE: We redirect the error stream to make sure the child process
@@ -67,7 +69,7 @@
return process.waitFor();
}
- private String getSourcePath(File sourceDir) {
+ private String getSourcePath(List<File> sourceDirs) {
List<String> sourcePath = new ArrayList<String>();
sourcePath.add("./frameworks/base/core/java");
sourcePath.add("./frameworks/base/test-runner/src");
@@ -77,7 +79,9 @@
sourcePath.add("./cts/tests/src");
sourcePath.add("./cts/libs/commonutil/src");
sourcePath.add("./cts/libs/deviceutil/src");
- sourcePath.add(sourceDir.toString());
+ for (File sourceDir : sourceDirs) {
+ sourcePath.add(sourceDir.toString());
+ }
return join(sourcePath, ":");
}
diff --git a/tools/selinux/SELinuxNeverallowTestFrame.py b/tools/selinux/SELinuxNeverallowTestFrame.py
new file mode 100644
index 0000000..932014a
--- /dev/null
+++ b/tools/selinux/SELinuxNeverallowTestFrame.py
@@ -0,0 +1,106 @@
+#!/usr/bin/python
+
+src_header = """/*
+ * 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.cts.security;
+
+import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.FileOutputStream;
+import java.lang.String;
+import java.net.URL;
+import java.util.Scanner;
+
+/**
+ * Neverallow Rules SELinux tests.
+ */
+public class SELinuxNeverallowRulesTest extends DeviceTestCase {
+ private File sepolicyAnalyze;
+ private File devicePolicyFile;
+
+ /**
+ * A reference to the device under test.
+ */
+ private ITestDevice mDevice;
+
+ private File copyResourceToTempFile(String resName) throws IOException {
+ InputStream is = this.getClass().getResourceAsStream(resName);
+ File tempFile = File.createTempFile("SELinuxHostTest", ".tmp");
+ FileOutputStream os = new FileOutputStream(tempFile);
+ int rByte = 0;
+ while ((rByte = is.read()) != -1) {
+ os.write(rByte);
+ }
+ os.flush();
+ os.close();
+ tempFile.deleteOnExit();
+ return tempFile;
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mDevice = getDevice();
+
+ /* retrieve the sepolicy-analyze executable from jar */
+ sepolicyAnalyze = copyResourceToTempFile("/sepolicy-analyze");
+ sepolicyAnalyze.setExecutable(true);
+
+ /* obtain sepolicy file from running device */
+ devicePolicyFile = File.createTempFile("sepolicy", ".tmp");
+ devicePolicyFile.deleteOnExit();
+ mDevice.executeAdbCommand("pull", "/sys/fs/selinux/policy",
+ devicePolicyFile.getAbsolutePath());
+ }
+"""
+src_body = ""
+src_footer = """}
+"""
+
+src_method = """
+ public void testNeverallowRules() throws Exception {
+ String neverallowRule = "$NEVERALLOW_RULE_HERE$";
+
+ /* run sepolicy-analyze neverallow check on policy file using given neverallow rules */
+ ProcessBuilder pb = new ProcessBuilder(sepolicyAnalyze.getAbsolutePath(),
+ devicePolicyFile.getAbsolutePath(), "neverallow", "-n",
+ neverallowRule);
+ pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
+ pb.redirectErrorStream(true);
+ Process p = pb.start();
+ p.waitFor();
+ BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
+ String line;
+ StringBuilder errorString = new StringBuilder();
+ while ((line = result.readLine()) != null) {
+ errorString.append(line);
+ errorString.append("\\n");
+ }
+ assertTrue("The following errors were encountered when validating the SELinux"
+ + "neverallow rule:\\n" + neverallowRule + "\\n" + errorString,
+ errorString.length() == 0);
+ }
+"""
diff --git a/tools/selinux/SELinuxNeverallowTestGen.py b/tools/selinux/SELinuxNeverallowTestGen.py
new file mode 100755
index 0000000..9cb1e24
--- /dev/null
+++ b/tools/selinux/SELinuxNeverallowTestGen.py
@@ -0,0 +1,53 @@
+#!/usr/bin/python
+
+import re
+import sys
+import SELinuxNeverallowTestFrame
+
+usage = "Usage: ./gen_SELinux_CTS_neverallows.py <input policy file> <output cts java source>"
+
+# extract_neverallow_rules - takes an intermediate policy file and pulls out the
+# neverallow rules by taking all of the non-commented text between the 'neverallow'
+# keyword and a terminating ';'
+# returns: a list of strings representing these rules
+def extract_neverallow_rules(policy_file):
+ with open(policy_file, 'r') as in_file:
+ policy_str = in_file.read()
+ # remove comments
+ no_comments = re.sub(r'#.+?$', r'', policy_str, flags = re.M)
+ # match neverallow rules
+ return re.findall(r'(^neverallow\s.+?;)', no_comments, flags = re.M |re.S);
+
+# neverallow_rule_to_test - takes a neverallow statement and transforms it into
+# the output necessary to form a cts unit test in a java source file.
+# returns: a string representing a generic test method based on this rule.
+def neverallow_rule_to_test(neverallow_rule, test_num):
+ squashed_neverallow = neverallow_rule.replace("\n", " ")
+ method = SELinuxNeverallowTestFrame.src_method
+ method = method.replace("testNeverallowRules()",
+ "testNeverallowRules" + str(test_num) + "()")
+ return method.replace("$NEVERALLOW_RULE_HERE$", squashed_neverallow)
+
+if __name__ == "__main__":
+ # check usage
+ if len(sys.argv) != 3:
+ print usage
+ exit()
+ input_file = sys.argv[1]
+ output_file = sys.argv[2]
+
+ src_header = SELinuxNeverallowTestFrame.src_header
+ src_body = SELinuxNeverallowTestFrame.src_body
+ src_footer = SELinuxNeverallowTestFrame.src_footer
+
+ # grab the neverallow rules from the policy file and transform into tests
+ neverallow_rules = extract_neverallow_rules(input_file)
+ i = 0
+ for rule in neverallow_rules:
+ src_body += neverallow_rule_to_test(rule, i)
+ i += 1
+
+ with open(output_file, 'w') as out_file:
+ out_file.write(src_header)
+ out_file.write(src_body)
+ out_file.write(src_footer)
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 25431b2..c43183a 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_r2";
+ public static final String CTS_BUILD_VERSION = "5.0_r2.5";
/**
* {@inheritDoc}