Merge "Remove hardware scan filter test, and re-enable BLE advertise/scanner test." into lmp-sprout-dev
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/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/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index bf07e8f..a19bcec 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -787,7 +787,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>
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..0fda75b 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++) {
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..17df106 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) {
@@ -96,25 +149,27 @@
showToast(R.string.no_camera_manager);
} else {
try {
- mCameraIds = manager.getCameraIdList();
+ String[] cameraIds = manager.getCameraIdList();
+ mNonLegacyCameraIds = new ArrayList<String>();
boolean allCamerasAreLegacy = true;
- for (String id : mCameraIds) {
+ 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;
- break;
}
}
if (allCamerasAreLegacy) {
showToast(R.string.all_legacy_devices);
- getPassButton().setEnabled(false);
+ getPassButton().setEnabled(true);
}
} 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 +178,7 @@
@Override
protected void onPause() {
super.onPause();
+ Log.d(TAG, "unregister ITS result receiver");
unregisterReceiver(mSuccessReceiver);
}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
index e93121e..7da4228 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
@@ -88,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;