Merge "Fix construction of algorithm list" into pi-dev
diff --git a/apps/CameraITS/tests/scene1/test_auto_vs_manual.py b/apps/CameraITS/tests/scene1/test_auto_vs_manual.py
index 9c49575..a7b5add 100644
--- a/apps/CameraITS/tests/scene1/test_auto_vs_manual.py
+++ b/apps/CameraITS/tests/scene1/test_auto_vs_manual.py
@@ -18,6 +18,7 @@
import its.objects
import os.path
import math
+import numpy as np
def main():
"""Capture auto and manual shots that should look the same.
@@ -93,10 +94,14 @@
# Check that the WB gains and transform reported in each capture
# result match with the original AWB estimate from do_3a.
- for g,x in [(gains_a,xform_a),(gains_m1,xform_m1),(gains_m2,xform_m2)]:
+ for g,x in [(gains_m1,xform_m1),(gains_m2,xform_m2)]:
assert(all([abs(xform[i] - x[i]) < 0.05 for i in range(9)]))
assert(all([abs(gains[i] - g[i]) < 0.05 for i in range(4)]))
+ # Check that auto AWB settings are close
+ assert(all([np.isclose(xform_a[i], xform[i], rtol=0.25, atol=0.1) for i in range(9)]))
+ assert(all([np.isclose(gains_a[i], gains[i], rtol=0.25, atol=0.1) for i in range(4)]))
+
if __name__ == '__main__':
main()
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 002af37..e8cf2ef 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
@@ -186,7 +186,8 @@
private CaptureResult mCaptureResults[] = null;
private volatile ConditionVariable mInterlock3A = new ConditionVariable(true);
- private volatile boolean mIssuedRequest3A = false;
+
+ final Object m3AStateLock = new Object();
private volatile boolean mConvergedAE = false;
private volatile boolean mConvergedAF = false;
private volatile boolean mConvergedAWB = false;
@@ -996,6 +997,7 @@
}
private void do3A(JSONObject params) throws ItsException {
+ ThreeAResultListener threeAListener = new ThreeAResultListener();
try {
// Start a 3A action, and wait for it to converge.
// Get the converged values for each "A", and package into JSON result for caller.
@@ -1048,11 +1050,6 @@
}
}
- // If AE or AWB lock is specified, then the 3A will converge first and then lock these
- // values, waiting until the HAL has reported that the lock was successful.
- mNeedsLockedAE = params.optBoolean(LOCK_AE_KEY, false);
- mNeedsLockedAWB = params.optBoolean(LOCK_AWB_KEY, false);
-
// An EV compensation can be specified as part of AE convergence.
int evComp = params.optInt(EVCOMP_KEY, 0);
if (evComp != 0) {
@@ -1084,12 +1081,17 @@
}
mInterlock3A.open();
- mIssuedRequest3A = false;
- mConvergedAE = false;
- mConvergedAWB = false;
- mConvergedAF = false;
- mLockedAE = false;
- mLockedAWB = false;
+ synchronized(m3AStateLock) {
+ // If AE or AWB lock is specified, then the 3A will converge first and then lock these
+ // values, waiting until the HAL has reported that the lock was successful.
+ mNeedsLockedAE = params.optBoolean(LOCK_AE_KEY, false);
+ mNeedsLockedAWB = params.optBoolean(LOCK_AWB_KEY, false);
+ mConvergedAE = false;
+ mConvergedAWB = false;
+ mConvergedAF = false;
+ mLockedAE = false;
+ mLockedAWB = false;
+ }
long tstart = System.currentTimeMillis();
boolean triggeredAE = false;
boolean triggeredAF = false;
@@ -1112,71 +1114,83 @@
}
mInterlock3A.close();
- // If not converged yet, issue another capture request.
- if ( (doAE && (!triggeredAE || !mConvergedAE))
- || !mConvergedAWB
- || (doAF && (!triggeredAF || !mConvergedAF))
- || (doAE && mNeedsLockedAE && !mLockedAE)
- || (mNeedsLockedAWB && !mLockedAWB)) {
+ synchronized(m3AStateLock) {
+ // If not converged yet, issue another capture request.
+ if ( (doAE && (!triggeredAE || !mConvergedAE))
+ || !mConvergedAWB
+ || (doAF && (!triggeredAF || !mConvergedAF))
+ || (doAE && mNeedsLockedAE && !mLockedAE)
+ || (mNeedsLockedAWB && !mLockedAWB)) {
- // Baseline capture request for 3A.
- CaptureRequest.Builder req = mCamera.createCaptureRequest(
- CameraDevice.TEMPLATE_PREVIEW);
- req.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
- req.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
- req.set(CaptureRequest.CONTROL_CAPTURE_INTENT,
- CaptureRequest.CONTROL_CAPTURE_INTENT_PREVIEW);
- req.set(CaptureRequest.CONTROL_AE_MODE,
- CaptureRequest.CONTROL_AE_MODE_ON);
- req.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 0);
- req.set(CaptureRequest.CONTROL_AE_LOCK, false);
- req.set(CaptureRequest.CONTROL_AE_REGIONS, regionAE);
- req.set(CaptureRequest.CONTROL_AF_MODE,
- CaptureRequest.CONTROL_AF_MODE_AUTO);
- req.set(CaptureRequest.CONTROL_AF_REGIONS, regionAF);
- req.set(CaptureRequest.CONTROL_AWB_MODE,
- CaptureRequest.CONTROL_AWB_MODE_AUTO);
- req.set(CaptureRequest.CONTROL_AWB_LOCK, false);
- req.set(CaptureRequest.CONTROL_AWB_REGIONS, regionAWB);
- // ITS only turns OIS on when it's explicitly requested
- req.set(CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE,
- CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE_OFF);
+ // Baseline capture request for 3A.
+ CaptureRequest.Builder req = mCamera.createCaptureRequest(
+ CameraDevice.TEMPLATE_PREVIEW);
+ req.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
+ req.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
+ req.set(CaptureRequest.CONTROL_CAPTURE_INTENT,
+ CaptureRequest.CONTROL_CAPTURE_INTENT_PREVIEW);
+ req.set(CaptureRequest.CONTROL_AE_MODE,
+ CaptureRequest.CONTROL_AE_MODE_ON);
+ req.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 0);
+ req.set(CaptureRequest.CONTROL_AE_LOCK, false);
+ req.set(CaptureRequest.CONTROL_AE_REGIONS, regionAE);
+ req.set(CaptureRequest.CONTROL_AF_MODE,
+ CaptureRequest.CONTROL_AF_MODE_AUTO);
+ req.set(CaptureRequest.CONTROL_AF_REGIONS, regionAF);
+ req.set(CaptureRequest.CONTROL_AWB_MODE,
+ CaptureRequest.CONTROL_AWB_MODE_AUTO);
+ req.set(CaptureRequest.CONTROL_AWB_LOCK, false);
+ req.set(CaptureRequest.CONTROL_AWB_REGIONS, regionAWB);
+ // ITS only turns OIS on when it's explicitly requested
+ req.set(CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE,
+ CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE_OFF);
- if (evComp != 0) {
- req.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, evComp);
+ if (evComp != 0) {
+ req.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, evComp);
+ }
+
+ if (mConvergedAE && mNeedsLockedAE) {
+ req.set(CaptureRequest.CONTROL_AE_LOCK, true);
+ }
+ if (mConvergedAWB && mNeedsLockedAWB) {
+ req.set(CaptureRequest.CONTROL_AWB_LOCK, true);
+ }
+
+ boolean triggering = false;
+ // Trigger AE first.
+ if (doAE && !triggeredAE) {
+ Logt.i(TAG, "Triggering AE");
+ req.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
+ CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
+ triggeredAE = true;
+ triggering = true;
+ }
+
+ // After AE has converged, trigger AF.
+ if (doAF && !triggeredAF && (!doAE || (triggeredAE && mConvergedAE))) {
+ Logt.i(TAG, "Triggering AF");
+ req.set(CaptureRequest.CONTROL_AF_TRIGGER,
+ CaptureRequest.CONTROL_AF_TRIGGER_START);
+ triggeredAF = true;
+ triggering = true;
+ }
+
+ req.addTarget(mOutputImageReaders[0].getSurface());
+
+ if (triggering) {
+ // Send single request for AE/AF trigger
+ mSession.capture(req.build(),
+ threeAListener, mResultHandler);
+ } else {
+ // Use repeating request for non-trigger requests
+ mSession.setRepeatingRequest(req.build(),
+ threeAListener, mResultHandler);
+ }
+ } else {
+ mSocketRunnableObj.sendResponse("3aConverged", "");
+ Logt.i(TAG, "3A converged");
+ break;
}
-
- if (mConvergedAE && mNeedsLockedAE) {
- req.set(CaptureRequest.CONTROL_AE_LOCK, true);
- }
- if (mConvergedAWB && mNeedsLockedAWB) {
- req.set(CaptureRequest.CONTROL_AWB_LOCK, true);
- }
-
- // Trigger AE first.
- if (doAE && !triggeredAE) {
- Logt.i(TAG, "Triggering AE");
- req.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
- CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
- triggeredAE = true;
- }
-
- // After AE has converged, trigger AF.
- if (doAF && !triggeredAF && (!doAE || (triggeredAE && mConvergedAE))) {
- Logt.i(TAG, "Triggering AF");
- req.set(CaptureRequest.CONTROL_AF_TRIGGER,
- CaptureRequest.CONTROL_AF_TRIGGER_START);
- triggeredAF = true;
- }
-
- req.addTarget(mOutputImageReaders[0].getSurface());
-
- mIssuedRequest3A = true;
- mSession.capture(req.build(), mCaptureResultListener, mResultHandler);
- } else {
- mSocketRunnableObj.sendResponse("3aConverged", "");
- Logt.i(TAG, "3A converged");
- break;
}
}
} catch (android.hardware.camera2.CameraAccessException e) {
@@ -1185,6 +1199,11 @@
throw new ItsException("JSON error: ", e);
} finally {
mSocketRunnableObj.sendResponse("3aDone", "");
+ // stop listener from updating 3A states
+ threeAListener.stop();
+ if (mSession != null) {
+ mSession.close();
+ }
}
}
@@ -1778,6 +1797,198 @@
return (float)r.getNumerator() / (float)r.getDenominator();
}
+ private String buildLogString(CaptureResult result) throws ItsException {
+ StringBuilder logMsg = new StringBuilder();
+ logMsg.append(String.format(
+ "Capt result: AE=%d, AF=%d, AWB=%d, ",
+ result.get(CaptureResult.CONTROL_AE_STATE),
+ result.get(CaptureResult.CONTROL_AF_STATE),
+ result.get(CaptureResult.CONTROL_AWB_STATE)));
+ int[] capabilities = mCameraCharacteristics.get(
+ CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
+ if (capabilities == null) {
+ throw new ItsException("Failed to get capabilities");
+ }
+ boolean readSensorSettings = false;
+ for (int capability : capabilities) {
+ if (capability ==
+ CameraCharacteristics.
+ REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS) {
+ readSensorSettings = true;
+ break;
+ }
+ }
+ if (readSensorSettings) {
+ logMsg.append(String.format(
+ "sens=%d, exp=%.1fms, dur=%.1fms, ",
+ result.get(CaptureResult.SENSOR_SENSITIVITY),
+ result.get(CaptureResult.SENSOR_EXPOSURE_TIME).longValue() / 1000000.0f,
+ result.get(CaptureResult.SENSOR_FRAME_DURATION).longValue() /
+ 1000000.0f));
+ }
+ if (result.get(CaptureResult.COLOR_CORRECTION_GAINS) != null) {
+ logMsg.append(String.format(
+ "gains=[%.1f, %.1f, %.1f, %.1f], ",
+ result.get(CaptureResult.COLOR_CORRECTION_GAINS).getRed(),
+ result.get(CaptureResult.COLOR_CORRECTION_GAINS).getGreenEven(),
+ result.get(CaptureResult.COLOR_CORRECTION_GAINS).getGreenOdd(),
+ result.get(CaptureResult.COLOR_CORRECTION_GAINS).getBlue()));
+ } else {
+ logMsg.append("gains=[], ");
+ }
+ if (result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM) != null) {
+ logMsg.append(String.format(
+ "xform=[%.1f, %.1f, %.1f, %.1f, %.1f, %.1f, %.1f, %.1f, %.1f], ",
+ r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(0,0)),
+ r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(1,0)),
+ r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(2,0)),
+ r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(0,1)),
+ r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(1,1)),
+ r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(2,1)),
+ r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(0,2)),
+ r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(1,2)),
+ r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(2,2))));
+ } else {
+ logMsg.append("xform=[], ");
+ }
+ logMsg.append(String.format(
+ "foc=%.1f",
+ result.get(CaptureResult.LENS_FOCUS_DISTANCE)));
+ return logMsg.toString();
+ }
+
+ private class ThreeAResultListener extends CaptureResultListener {
+ private volatile boolean stopped = false;
+ private boolean aeResultSent = false;
+ private boolean awbResultSent = false;
+ private boolean afResultSent = false;
+
+ @Override
+ public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request,
+ long timestamp, long frameNumber) {
+ }
+
+ @Override
+ public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
+ TotalCaptureResult result) {
+ try {
+ if (stopped) {
+ return;
+ }
+
+ if (request == null || result == null) {
+ throw new ItsException("Request/result is invalid");
+ }
+
+ Logt.i(TAG, buildLogString(result));
+
+ synchronized(m3AStateLock) {
+ if (result.get(CaptureResult.CONTROL_AE_STATE) != null) {
+ mConvergedAE = result.get(CaptureResult.CONTROL_AE_STATE) ==
+ CaptureResult.CONTROL_AE_STATE_CONVERGED ||
+ result.get(CaptureResult.CONTROL_AE_STATE) ==
+ CaptureResult.CONTROL_AE_STATE_FLASH_REQUIRED ||
+ result.get(CaptureResult.CONTROL_AE_STATE) ==
+ CaptureResult.CONTROL_AE_STATE_LOCKED;
+ mLockedAE = result.get(CaptureResult.CONTROL_AE_STATE) ==
+ CaptureResult.CONTROL_AE_STATE_LOCKED;
+ }
+ if (result.get(CaptureResult.CONTROL_AF_STATE) != null) {
+ mConvergedAF = result.get(CaptureResult.CONTROL_AF_STATE) ==
+ CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED;
+ }
+ if (result.get(CaptureResult.CONTROL_AWB_STATE) != null) {
+ mConvergedAWB = result.get(CaptureResult.CONTROL_AWB_STATE) ==
+ CaptureResult.CONTROL_AWB_STATE_CONVERGED ||
+ result.get(CaptureResult.CONTROL_AWB_STATE) ==
+ CaptureResult.CONTROL_AWB_STATE_LOCKED;
+ mLockedAWB = result.get(CaptureResult.CONTROL_AWB_STATE) ==
+ CaptureResult.CONTROL_AWB_STATE_LOCKED;
+ }
+
+ if (mConvergedAE && (!mNeedsLockedAE || mLockedAE) && !aeResultSent) {
+ aeResultSent = true;
+ if (result.get(CaptureResult.SENSOR_SENSITIVITY) != null
+ && result.get(CaptureResult.SENSOR_EXPOSURE_TIME) != null) {
+ mSocketRunnableObj.sendResponse("aeResult", String.format("%d %d",
+ result.get(CaptureResult.SENSOR_SENSITIVITY).intValue(),
+ result.get(CaptureResult.SENSOR_EXPOSURE_TIME).intValue()
+ ));
+ } else {
+ Logt.i(TAG, String.format(
+ "AE converged but NULL exposure values, sensitivity:%b, expTime:%b",
+ result.get(CaptureResult.SENSOR_SENSITIVITY) == null,
+ result.get(CaptureResult.SENSOR_EXPOSURE_TIME) == null));
+ }
+ }
+
+ if (mConvergedAF && !afResultSent) {
+ afResultSent = true;
+ if (result.get(CaptureResult.LENS_FOCUS_DISTANCE) != null) {
+ mSocketRunnableObj.sendResponse("afResult", String.format("%f",
+ result.get(CaptureResult.LENS_FOCUS_DISTANCE)
+ ));
+ } else {
+ Logt.i(TAG, "AF converged but NULL focus distance values");
+ }
+ }
+
+ if (mConvergedAWB && (!mNeedsLockedAWB || mLockedAWB) && !awbResultSent) {
+ awbResultSent = true;
+ if (result.get(CaptureResult.COLOR_CORRECTION_GAINS) != null
+ && result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM) != null) {
+ mSocketRunnableObj.sendResponse("awbResult", String.format(
+ "%f %f %f %f %f %f %f %f %f %f %f %f %f",
+ result.get(CaptureResult.COLOR_CORRECTION_GAINS).getRed(),
+ result.get(CaptureResult.COLOR_CORRECTION_GAINS).getGreenEven(),
+ result.get(CaptureResult.COLOR_CORRECTION_GAINS).getGreenOdd(),
+ result.get(CaptureResult.COLOR_CORRECTION_GAINS).getBlue(),
+ r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).
+ getElement(0,0)),
+ r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).
+ getElement(1,0)),
+ r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).
+ getElement(2,0)),
+ r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).
+ getElement(0,1)),
+ r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).
+ getElement(1,1)),
+ r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).
+ getElement(2,1)),
+ r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).
+ getElement(0,2)),
+ r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).
+ getElement(1,2)),
+ r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).
+ getElement(2,2))));
+ } else {
+ Logt.i(TAG, String.format(
+ "AWB converged but NULL color correction values, gains:%b, ccm:%b",
+ result.get(CaptureResult.COLOR_CORRECTION_GAINS) == null,
+ result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM) == null));
+ }
+ }
+ }
+
+ mInterlock3A.open();
+ } catch (ItsException e) {
+ Logt.e(TAG, "Script error: ", e);
+ } catch (Exception e) {
+ Logt.e(TAG, "Script error: ", e);
+ }
+ }
+
+ @Override
+ public void onCaptureFailed(CameraCaptureSession session, CaptureRequest request,
+ CaptureFailure failure) {
+ Logt.e(TAG, "Script error: capture failed");
+ }
+
+ public void stop() {
+ stopped = true;
+ }
+ }
+
private final CaptureResultListener mCaptureResultListener = new CaptureResultListener() {
@Override
public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request,
@@ -1788,156 +1999,19 @@
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
TotalCaptureResult result) {
try {
- // Currently result has all 0 values.
if (request == null || result == null) {
throw new ItsException("Request/result is invalid");
}
- StringBuilder logMsg = new StringBuilder();
- logMsg.append(String.format(
- "Capt result: AE=%d, AF=%d, AWB=%d, ",
- result.get(CaptureResult.CONTROL_AE_STATE),
- result.get(CaptureResult.CONTROL_AF_STATE),
- result.get(CaptureResult.CONTROL_AWB_STATE)));
- int[] capabilities = mCameraCharacteristics.get(
- CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
- if (capabilities == null) {
- throw new ItsException("Failed to get capabilities");
- }
- boolean readSensorSettings = false;
- for (int capability : capabilities) {
- if (capability ==
- CameraCharacteristics.
- REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS) {
- readSensorSettings = true;
- break;
- }
- }
- if (readSensorSettings) {
- logMsg.append(String.format(
- "sens=%d, exp=%.1fms, dur=%.1fms, ",
- result.get(CaptureResult.SENSOR_SENSITIVITY),
- result.get(CaptureResult.SENSOR_EXPOSURE_TIME).longValue() / 1000000.0f,
- result.get(CaptureResult.SENSOR_FRAME_DURATION).longValue() /
- 1000000.0f));
- }
- if (result.get(CaptureResult.COLOR_CORRECTION_GAINS) != null) {
- logMsg.append(String.format(
- "gains=[%.1f, %.1f, %.1f, %.1f], ",
- result.get(CaptureResult.COLOR_CORRECTION_GAINS).getRed(),
- result.get(CaptureResult.COLOR_CORRECTION_GAINS).getGreenEven(),
- result.get(CaptureResult.COLOR_CORRECTION_GAINS).getGreenOdd(),
- result.get(CaptureResult.COLOR_CORRECTION_GAINS).getBlue()));
- } else {
- logMsg.append("gains=[], ");
- }
- if (result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM) != null) {
- logMsg.append(String.format(
- "xform=[%.1f, %.1f, %.1f, %.1f, %.1f, %.1f, %.1f, %.1f, %.1f], ",
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(0,0)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(1,0)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(2,0)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(0,1)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(1,1)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(2,1)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(0,2)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(1,2)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(2,2))));
- } else {
- logMsg.append("xform=[], ");
- }
- logMsg.append(String.format(
- "foc=%.1f",
- result.get(CaptureResult.LENS_FOCUS_DISTANCE)));
- Logt.i(TAG, logMsg.toString());
+ Logt.i(TAG, buildLogString(result));
- if (result.get(CaptureResult.CONTROL_AE_STATE) != null) {
- mConvergedAE = result.get(CaptureResult.CONTROL_AE_STATE) ==
- CaptureResult.CONTROL_AE_STATE_CONVERGED ||
- result.get(CaptureResult.CONTROL_AE_STATE) ==
- CaptureResult.CONTROL_AE_STATE_FLASH_REQUIRED ||
- result.get(CaptureResult.CONTROL_AE_STATE) ==
- CaptureResult.CONTROL_AE_STATE_LOCKED;
- mLockedAE = result.get(CaptureResult.CONTROL_AE_STATE) ==
- CaptureResult.CONTROL_AE_STATE_LOCKED;
- }
- if (result.get(CaptureResult.CONTROL_AF_STATE) != null) {
- mConvergedAF = result.get(CaptureResult.CONTROL_AF_STATE) ==
- CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED;
- }
- if (result.get(CaptureResult.CONTROL_AWB_STATE) != null) {
- mConvergedAWB = result.get(CaptureResult.CONTROL_AWB_STATE) ==
- CaptureResult.CONTROL_AWB_STATE_CONVERGED ||
- result.get(CaptureResult.CONTROL_AWB_STATE) ==
- CaptureResult.CONTROL_AWB_STATE_LOCKED;
- mLockedAWB = result.get(CaptureResult.CONTROL_AWB_STATE) ==
- CaptureResult.CONTROL_AWB_STATE_LOCKED;
- }
-
- if (mConvergedAE && (!mNeedsLockedAE || mLockedAE)) {
- if (result.get(CaptureResult.SENSOR_SENSITIVITY) != null
- && result.get(CaptureResult.SENSOR_EXPOSURE_TIME) != null) {
- mSocketRunnableObj.sendResponse("aeResult", String.format("%d %d",
- result.get(CaptureResult.SENSOR_SENSITIVITY).intValue(),
- result.get(CaptureResult.SENSOR_EXPOSURE_TIME).intValue()
- ));
- } else {
- Logt.i(TAG, String.format(
- "AE converged but NULL exposure values, sensitivity:%b, expTime:%b",
- result.get(CaptureResult.SENSOR_SENSITIVITY) == null,
- result.get(CaptureResult.SENSOR_EXPOSURE_TIME) == null));
- }
- }
-
- if (mConvergedAF) {
- if (result.get(CaptureResult.LENS_FOCUS_DISTANCE) != null) {
- mSocketRunnableObj.sendResponse("afResult", String.format("%f",
- result.get(CaptureResult.LENS_FOCUS_DISTANCE)
- ));
- } else {
- Logt.i(TAG, "AF converged but NULL focus distance values");
- }
- }
-
- if (mConvergedAWB && (!mNeedsLockedAWB || mLockedAWB)) {
- if (result.get(CaptureResult.COLOR_CORRECTION_GAINS) != null
- && result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM) != null) {
- mSocketRunnableObj.sendResponse("awbResult", String.format(
- "%f %f %f %f %f %f %f %f %f %f %f %f %f",
- result.get(CaptureResult.COLOR_CORRECTION_GAINS).getRed(),
- result.get(CaptureResult.COLOR_CORRECTION_GAINS).getGreenEven(),
- result.get(CaptureResult.COLOR_CORRECTION_GAINS).getGreenOdd(),
- result.get(CaptureResult.COLOR_CORRECTION_GAINS).getBlue(),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(0,0)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(1,0)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(2,0)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(0,1)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(1,1)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(2,1)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(0,2)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(1,2)),
- r2f(result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM).getElement(2,2))
- ));
- } else {
- Logt.i(TAG, String.format(
- "AWB converged but NULL color correction values, gains:%b, ccm:%b",
- result.get(CaptureResult.COLOR_CORRECTION_GAINS) == null,
- result.get(CaptureResult.COLOR_CORRECTION_TRANSFORM) == null));
- }
- }
-
- if (mIssuedRequest3A) {
- mIssuedRequest3A = false;
- mInterlock3A.open();
- } else {
- int count = mCountCapRes.getAndIncrement();
- mCaptureResults[count] = result;
- mSocketRunnableObj.sendResponseCaptureResult(mCameraCharacteristics,
- request, result, mOutputImageReaders);
- synchronized(mCountCallbacksRemaining) {
- mCountCallbacksRemaining.decrementAndGet();
- mCountCallbacksRemaining.notify();
- }
+ int count = mCountCapRes.getAndIncrement();
+ mCaptureResults[count] = result;
+ mSocketRunnableObj.sendResponseCaptureResult(mCameraCharacteristics,
+ request, result, mOutputImageReaders);
+ synchronized(mCountCallbacksRemaining) {
+ mCountCallbacksRemaining.decrementAndGet();
+ mCountCallbacksRemaining.notify();
}
} catch (ItsException e) {
Logt.e(TAG, "Script error: ", e);
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
index 8a781c6..2d1386f 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
@@ -171,7 +171,7 @@
doTest = false;
}
getDevice().waitForDeviceNotAvailable(SHUTDOWN_TIME_MS);
- getDevice().waitForDeviceOnline();
+ getDevice().waitForDeviceOnline(120000);
} else {
getDevice().rebootUntilOnline();
}
diff --git a/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java b/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java
index 263327f..65cb2a5 100644
--- a/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java
@@ -172,9 +172,11 @@
startSimpleActivity();
assertValueRange("st", "", STATE_TIME_FOREGROUND_SERVICE_INDEX, 0,
0); // No foreground service time before test
+ final long startTime = System.nanoTime();
runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".BatteryStatsProcessStateTests",
"testForegroundService");
- assertValueRange("st", "", STATE_TIME_FOREGROUND_SERVICE_INDEX, (long) (2000 * 0.8), 4000);
+ assertValueRange("st", "", STATE_TIME_FOREGROUND_SERVICE_INDEX, (long) (2000 * 0.8),
+ (System.nanoTime() - startTime) / 1000000);
batteryOffScreenOn();
}
diff --git a/hostsidetests/security/src/android/security/cts/Poc17_03.java b/hostsidetests/security/src/android/security/cts/Poc17_03.java
index 80c959c..a6f1e04 100644
--- a/hostsidetests/security/src/android/security/cts/Poc17_03.java
+++ b/hostsidetests/security/src/android/security/cts/Poc17_03.java
@@ -82,4 +82,23 @@
assertNotMatchesMultiLine(".*Fatal signal 11 \\(SIGSEGV\\).*>>> /system/bin/" +
"audioserver <<<.*", logcatOut);
}
+
+ /*
+ * b/33178389
+ */
+ @SecurityTest
+ public void testPocCVE_2017_0490() throws Exception {
+ String bootCountBefore =
+ AdbUtils.runCommandLine("settings get global boot_count", getDevice());
+ AdbUtils.runCommandLine("service call wifi 43 s16 content://settings/global/boot_count s16 "
+ + "\"application/x-wifi-config\"",
+ getDevice());
+ String bootCountAfter =
+ AdbUtils.runCommandLine("settings get global boot_count", getDevice());
+ // Poc nukes the boot_count setting, reboot to restore it to a sane value
+ AdbUtils.runCommandLine("reboot", getDevice());
+ getDevice().waitForDeviceOnline(60 * 1000);
+ updateKernelStartTime();
+ assertEquals(bootCountBefore, bootCountAfter);
+ }
}
diff --git a/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/Checkers.java b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/Checkers.java
new file mode 100644
index 0000000..40c4f03
--- /dev/null
+++ b/hostsidetests/statsd/apps/statsdapp/src/com/android/server/cts/device/statsd/Checkers.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2018 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.server.cts.device.statsd;
+
+import android.net.wifi.WifiManager;
+import android.support.test.InstrumentationRegistry;
+
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+
+/**
+ * Methods to check device properties. They pass iff the check returns true.
+ */
+public class Checkers {
+ private static final String TAG = Checkers.class.getSimpleName();
+
+ @Test
+ public void checkWifiEnhancedPowerReportingSupported() {
+ WifiManager wm = InstrumentationRegistry.getContext().getSystemService(WifiManager.class);
+ assertTrue(wm.isEnhancedPowerReportingSupported());
+ }
+}
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/AtomTestCase.java b/hostsidetests/statsd/src/android/cts/statsd/atom/AtomTestCase.java
index 2fa1ac4..225ebf5 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/AtomTestCase.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/AtomTestCase.java
@@ -15,6 +15,9 @@
*/
package android.cts.statsd.atom;
+import static android.cts.statsd.atom.DeviceAtomTestCase.DEVICE_SIDE_TEST_APK;
+import static android.cts.statsd.atom.DeviceAtomTestCase.DEVICE_SIDE_TEST_PACKAGE;
+
import android.os.BatteryStatsProto;
import android.service.batterystats.BatteryStatsServiceDumpProto;
import android.view.DisplayStateEnum;
@@ -86,11 +89,6 @@
if (statsdDisabled()) {
return;
}
- // TODO: need to do these before running real test:
- // 1. compile statsd and push to device
- // 2. make sure StatsCompanionService and incidentd is running
- // 3. start statsd
- // These should go away once we have statsd properly set up.
// Uninstall to clear the history in case it's still on the device.
removeConfig(CONFIG_ID);
@@ -100,6 +98,7 @@
@Override
protected void tearDown() throws Exception {
removeConfig(CONFIG_ID);
+ getDevice().uninstallPackage(DEVICE_SIDE_TEST_PACKAGE);
super.tearDown();
}
@@ -130,6 +129,18 @@
return log.contains(PERFETTO_STARTED_STRING);
}
+ protected boolean checkDeviceFor(String methodName) throws Exception {
+ try {
+ installPackage(DEVICE_SIDE_TEST_APK, true);
+ runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".Checkers", methodName);
+ // Test passes, meaning that the answer is true.
+ return true;
+ } catch (AssertionError e) {
+ // Method is designed to fail if the answer is false.
+ return false;
+ }
+ }
+
protected static StatsdConfig.Builder createConfigBuilder() {
return StatsdConfig.newBuilder().setId(CONFIG_ID)
.addAllowedLogSource("AID_SYSTEM")
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/BaseTestCase.java b/hostsidetests/statsd/src/android/cts/statsd/atom/BaseTestCase.java
index fc4a561..cd396ec 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/BaseTestCase.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/BaseTestCase.java
@@ -120,11 +120,11 @@
final TestRunResult result = listener.getCurrentRunResults();
if (result.isRunFailure()) {
- throw new AssertionError("Failed to successfully run device tests for "
+ throw new Error("Failed to successfully run device tests for "
+ result.getName() + ": " + result.getRunFailureMessage());
}
if (result.getNumTests() == 0) {
- throw new AssertionError("No tests were run on the device");
+ throw new Error("No tests were run on the device");
}
if (result.hasFailedTests()) {
diff --git a/hostsidetests/statsd/src/android/cts/statsd/atom/HostAtomTests.java b/hostsidetests/statsd/src/android/cts/statsd/atom/HostAtomTests.java
index eb96b83..b91ebbb 100644
--- a/hostsidetests/statsd/src/android/cts/statsd/atom/HostAtomTests.java
+++ b/hostsidetests/statsd/src/android/cts/statsd/atom/HostAtomTests.java
@@ -17,7 +17,6 @@
import android.os.BatteryPluggedStateEnum; // From os/enums.proto
import android.os.BatteryStatusEnum; // From os/enums.proto
-import android.os.TemperatureTypeEnum; // From os/enums.proto
import android.platform.test.annotations.RestrictedBuildTest;
import android.server.DeviceIdleModeEnum; // From server/enums.proto
import android.view.DisplayStateEnum; // From view/enums.proto
@@ -45,7 +44,6 @@
import com.android.os.AtomsProto.RemainingBatteryCapacity;
import com.android.os.AtomsProto.ScreenStateChanged;
import com.android.os.AtomsProto.SubsystemSleepState;
-import com.android.os.AtomsProto.Temperature;
import com.android.os.StatsLog.EventMetricData;
import com.android.tradefed.log.LogUtil.CLog;
@@ -399,44 +397,6 @@
assertTrue(atom.getFullBatteryCapacity().getCapacityUAh() > 0);
}
- @RestrictedBuildTest
- public void testTemperature() throws Exception {
- if (statsdDisabled()) {
- return;
- }
- if (!hasFeature(FEATURE_WATCH, false)) return;
- StatsdConfig.Builder config = getPulledConfig();
- FieldMatcher.Builder dimension = FieldMatcher.newBuilder()
- .setField(Atom.TEMPERATURE_FIELD_NUMBER)
- .addChild(FieldMatcher.newBuilder()
- .setField(Temperature.SENSOR_LOCATION_FIELD_NUMBER))
- .addChild(FieldMatcher.newBuilder()
- .setField(Temperature.SENSOR_NAME_FIELD_NUMBER));
- addGaugeAtom(config, Atom.TEMPERATURE_FIELD_NUMBER, dimension);
-
- uploadConfig(config);
-
- Thread.sleep(WAIT_TIME_LONG);
- setAppBreadcrumbPredicate();
- Thread.sleep(WAIT_TIME_LONG);
-
- List<Atom> data = getGaugeMetricDataList();
-
- assertTrue(data.size() >= TemperatureTypeEnum.values().length - 1);
- for (int i = 0; i < data.size(); i++) {
- Temperature temp = data.get(i).getTemperature();
- assertTrue("Temperature atom " + i + " has no type",
- temp.hasSensorLocation());
- assertTrue("Temperature reported atom " + i + " has no temperature",
- temp.hasTemperatureDC());
- assertTrue("Temperature reported atom " + i + " has an unreasonably low temperature:" +
- + temp.getTemperatureDC(), temp.getTemperatureDC() > 0);
- assertTrue("Temperature reported atom " + i + " has an unreasonably high temperature:" +
- + temp.getTemperatureDC(), temp.getTemperatureDC() < 800);
-
- }
- }
-
public void testKernelWakelock() throws Exception {
if (statsdDisabled()) {
return;
@@ -522,6 +482,8 @@
}
if (!hasFeature(FEATURE_WIFI, true)) return;
if (!hasFeature(FEATURE_WATCH, false)) return;
+ if (!checkDeviceFor("checkWifiEnhancedPowerReportingSupported")) return;
+
StatsdConfig.Builder config = getPulledConfig();
addGaugeAtom(config, Atom.WIFI_ACTIVITY_INFO_FIELD_NUMBER, null);
diff --git a/tests/app/src/android/app/cts/DisplayTest.java b/tests/app/src/android/app/cts/DisplayTest.java
index 154f41f..f845bb7 100644
--- a/tests/app/src/android/app/cts/DisplayTest.java
+++ b/tests/app/src/android/app/cts/DisplayTest.java
@@ -58,7 +58,14 @@
// Change orientation
mActivity.configurationChangeObserver.startObserving();
OrientationTestUtils.switchOrientation(mActivity);
- mActivity.configurationChangeObserver.await();
+
+ final boolean squareDisplay = (origSize.x == origSize.y);
+
+ // Don't wait for the configuration to change if the
+ // the display is square. In many cases it won't.
+ if (!squareDisplay) {
+ mActivity.configurationChangeObserver.await();
+ }
final Point newOrigSize = new Point();
origDisplay.getSize(newOrigSize);
@@ -69,7 +76,7 @@
updatedDisplay.getSize(updatedSize);
// For square screens the following assertions do not make sense and will always fail.
- if (origSize.x != origSize.y) {
+ if (!squareDisplay) {
// Ensure that the width and height of the original instance no longer are the same. Note
// that this will be false if the device width and height are identical.
// Note there are cases where width and height may not all be updated, such as on docked
diff --git a/tests/autofillservice/res/layout/duplicate_id_layout.xml b/tests/autofillservice/res/layout/duplicate_id_layout.xml
index a5643ea..4d409a2 100644
--- a/tests/autofillservice/res/layout/duplicate_id_layout.xml
+++ b/tests/autofillservice/res/layout/duplicate_id_layout.xml
@@ -17,17 +17,21 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
android:layout_width="match_parent"
android:layout_height="match_parent">
<CheckBox
android:id="@+id/duplicate_id"
android:layout_width="match_parent"
- android:layout_height="wrap_content" />
+ android:layout_height="wrap_content"
+ android:text="cb1" /> <!-- text is set just for debugging purposes -->
<CheckBox
android:id="@+id/duplicate_id"
android:layout_width="match_parent"
- android:layout_height="wrap_content" />
+ android:layout_height="wrap_content"
+ android:text="cb2"/> <!-- text is set just for debugging purposes -->
</LinearLayout>
\ No newline at end of file
diff --git a/tests/autofillservice/src/android/autofillservice/cts/DuplicateIdActivity.java b/tests/autofillservice/src/android/autofillservice/cts/DuplicateIdActivity.java
index 31ac8f7..90871ca 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/DuplicateIdActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/DuplicateIdActivity.java
@@ -20,7 +20,7 @@
import android.util.Log;
public class DuplicateIdActivity extends AbstractAutoFillActivity {
- private static final String LOG_TAG = DuplicateIdActivity.class.getSimpleName();
+ private static final String TAG = "DuplicateIdActivity";
static final String DUPLICATE_ID = "duplicate_id";
@@ -28,9 +28,7 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- if (savedInstanceState != null) {
- Log.i(LOG_TAG, "onCreate(" + savedInstanceState + ")");
- }
+ Log.v(TAG, "onCreate(" + savedInstanceState + ")");
setContentView(R.layout.duplicate_id_layout);
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/DuplicateIdActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/DuplicateIdActivityTest.java
index 29ec2b1..846dcc4 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/DuplicateIdActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/DuplicateIdActivityTest.java
@@ -89,13 +89,14 @@
// Select field to start autofill
runShellCommand("input keyevent KEYCODE_TAB");
- InstrumentedAutoFillService.FillRequest request = sReplier.getNextFillRequest();
+ final InstrumentedAutoFillService.FillRequest request1 = sReplier.getNextFillRequest();
+ Log.v(LOG_TAG, "request1: " + request1);
- AssistStructure.ViewNode[] views = findViews(request);
- AssistStructure.ViewNode view1 = views[0];
- AssistStructure.ViewNode view2 = views[1];
- AutofillId id1 = view1.getAutofillId();
- AutofillId id2 = view2.getAutofillId();
+ final AssistStructure.ViewNode[] views1 = findViews(request1);
+ final AssistStructure.ViewNode view1 = views1[0];
+ final AssistStructure.ViewNode view2 = views1[1];
+ final AutofillId id1 = view1.getAutofillId();
+ final AutofillId id2 = view2.getAutofillId();
Log.i(LOG_TAG, "view1=" + id1);
Log.i(LOG_TAG, "view2=" + id2);
@@ -106,38 +107,39 @@
// They got different autofill ids though
assertThat(id1).isNotEqualTo(id2);
+ // Because service returned a null response, rotation will trigger another request.
sReplier.addResponse(NO_RESPONSE);
-
// Force rotation to force onDestroy->onCreate cycle
mUiBot.setScreenOrientation(1);
// Wait context and Views being recreated in rotation
mUiBot.assertShownByRelativeId(DUPLICATE_ID);
+ // Ignore 2nd request.
+ final InstrumentedAutoFillService.FillRequest request2 = sReplier.getNextFillRequest();
+ Log.v(LOG_TAG, "request2: " + request2);
- // Because service returned a null response, rotation will trigger another request.
+ // Select other field to trigger new partition (because server didn't return 2nd field
+ // on 1st response)
sReplier.addResponse(NO_RESPONSE);
-
- // Select other field to trigger new partition
runShellCommand("input keyevent KEYCODE_TAB");
- request = sReplier.getNextFillRequest();
-
- // Ignore 2nd request.
- sReplier.getNextFillRequest();
-
- views = findViews(request);
- AutofillId recreatedId1 = views[0].getAutofillId();
- AutofillId recreatedId2 = views[1].getAutofillId();
+ final InstrumentedAutoFillService.FillRequest request3 = sReplier.getNextFillRequest();
+ Log.v(LOG_TAG, "request3: " + request3);
+ final AssistStructure.ViewNode[] views2 = findViews(request3);
+ final AssistStructure.ViewNode recreatedView1 = views2[0];
+ final AssistStructure.ViewNode recreatedView2 = views2[1];
+ final AutofillId recreatedId1 = recreatedView1.getAutofillId();
+ final AutofillId recreatedId2 = recreatedView2.getAutofillId();
Log.i(LOG_TAG, "restored view1=" + recreatedId1);
Log.i(LOG_TAG, "restored view2=" + recreatedId2);
// For the restoring logic the two views are the same. Hence it might happen that the first
- // view is restored with the id of the second view or the other way round.
+ // view is restored with the autofill id of the second view or the other way round.
// We just need
// - to restore as many views as we can (i.e. one)
// - make sure the autofill ids are still unique after
- boolean view1WasRestored = (recreatedId1.equals(id1) || recreatedId1.equals(id2));
- boolean view2WasRestored = (recreatedId2.equals(id1) || recreatedId2.equals(id2));
+ final boolean view1WasRestored = (recreatedId1.equals(id1) || recreatedId1.equals(id2));
+ final boolean view2WasRestored = (recreatedId2.equals(id1) || recreatedId2.equals(id2));
// One id was restored
assertThat(view1WasRestored || view2WasRestored).isTrue();
diff --git a/tests/autofillservice/src/android/autofillservice/cts/Helper.java b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
index 7934730..4e5418b 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/Helper.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
@@ -156,19 +156,37 @@
return hasHint(view.getAutofillHints(), id);
};
+ private static String toString(AssistStructure structure, StringBuilder builder) {
+ builder.append("[component=").append(structure.getActivityComponent());
+ final int nodes = structure.getWindowNodeCount();
+ for (int i = 0; i < nodes; i++) {
+ final WindowNode windowNode = structure.getWindowNodeAt(i);
+ dump(builder, windowNode.getRootViewNode(), " ", 0);
+ }
+ return builder.append(']').toString();
+ }
+
+ @NonNull
+ static String toString(@NonNull AssistStructure structure) {
+ return toString(structure, new StringBuilder());
+ }
+
+ @Nullable
+ static String toString(@Nullable AutofillValue value) {
+ if (value == null) return null;
+ if (value.isText()) {
+ // We don't care about PII...
+ final CharSequence text = value.getTextValue();
+ return text == null ? null : text.toString();
+ }
+ return value.toString();
+ }
+
/**
* Dump the assist structure on logcat.
*/
static void dumpStructure(String message, AssistStructure structure) {
- final StringBuffer buffer = new StringBuffer(message)
- .append(": component=")
- .append(structure.getActivityComponent());
- final int nodes = structure.getWindowNodeCount();
- for (int i = 0; i < nodes; i++) {
- final WindowNode windowNode = structure.getWindowNodeAt(i);
- dump(buffer, windowNode.getRootViewNode(), " ", 0);
- }
- Log.i(TAG, buffer.toString());
+ Log.i(TAG, toString(structure, new StringBuilder(message)));
}
/**
@@ -194,39 +212,69 @@
SettingsHelper.syncSet(context, USER_SETUP_COMPLETE, complete ? "1" : null);
}
- private static void dump(StringBuffer buffer, ViewNode node, String prefix, int childId) {
+ private static void dump(@NonNull StringBuilder builder, @NonNull ViewNode node,
+ @NonNull String prefix, int childId) {
final int childrenSize = node.getChildCount();
- buffer.append("\n").append(prefix)
- .append('#').append(childId).append(':')
- .append("resId=").append(node.getIdEntry())
- .append(" class=").append(node.getClassName())
- .append(" text=").append(node.getText())
- .append(" class=").append(node.getClassName())
- .append(" webDomain=").append(node.getWebDomain())
- .append(" #children=").append(childrenSize);
-
- buffer.append("\n").append(prefix)
- .append(" afId=").append(node.getAutofillId())
- .append(" afType=").append(node.getAutofillType())
- .append(" afValue=").append(node.getAutofillValue())
- .append(" checked=").append(node.isChecked())
- .append(" focused=").append(node.isFocused());
-
+ builder.append("\n").append(prefix)
+ .append("child #").append(childId).append(':');
+ append(builder, "afId", node.getAutofillId());
+ append(builder, "afType", node.getAutofillType());
+ append(builder, "afValue", toString(node.getAutofillValue()));
+ append(builder, "resId", node.getIdEntry());
+ append(builder, "class", node.getClassName());
+ append(builder, "text", node.getText());
+ append(builder, "webDomain", node.getWebDomain());
+ append(builder, "checked", node.isChecked());
+ append(builder, "focused", node.isFocused());
final HtmlInfo htmlInfo = node.getHtmlInfo();
if (htmlInfo != null) {
- buffer.append("\nHtmlInfo: tag=").append(htmlInfo.getTag())
- .append(", attrs: ").append(htmlInfo.getAttributes());
+ builder.append(", HtmlInfo[tag=").append(htmlInfo.getTag())
+ .append(", attrs: ").append(htmlInfo.getAttributes()).append(']');
}
-
- prefix += " ";
if (childrenSize > 0) {
- for (int i = 0; i < childrenSize; i++) {
- dump(buffer, node.getChildAt(i), prefix, i);
+ append(builder, "#children", childrenSize).append("\n").append(prefix);
+ prefix += " ";
+ if (childrenSize > 0) {
+ for (int i = 0; i < childrenSize; i++) {
+ dump(builder, node.getChildAt(i), prefix, i);
+ }
}
}
}
/**
+ * Appends a field value to a {@link StringBuilder} when it's not {@code null}.
+ */
+ @NonNull
+ static StringBuilder append(@NonNull StringBuilder builder, @NonNull String field,
+ @Nullable Object value) {
+ if (value == null) return builder;
+
+ if ((value instanceof Boolean) && ((Boolean) value)) {
+ return builder.append(", ").append(field);
+ }
+
+ if (value instanceof Integer && ((Integer) value) == 0
+ || value instanceof CharSequence && TextUtils.isEmpty((CharSequence) value)) {
+ return builder;
+ }
+
+ return builder.append(", ").append(field).append('=').append(value);
+ }
+
+ /**
+ * Appends a field value to a {@link StringBuilder} when it's {@code true}.
+ */
+ @NonNull
+ static StringBuilder append(@NonNull StringBuilder builder, @NonNull String field,
+ boolean value) {
+ if (value) {
+ builder.append(", ").append(field);
+ }
+ return builder;
+ }
+
+ /**
* Gets a node if it matches the filter criteria for the given id.
*/
static ViewNode findNodeByFilter(@NonNull AssistStructure structure, @NonNull Object id,
diff --git a/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java b/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
index 42b6b41..6b47c9f 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
@@ -293,12 +293,13 @@
this.cancellationSignal = cancellationSignal;
this.callback = callback;
this.flags = flags;
- structure = contexts.get(contexts.size() - 1).getStructure();
+ this.structure = contexts.get(contexts.size() - 1).getStructure();
}
@Override
public String toString() {
- return "FillRequest:" + getActivityName(contexts);
+ return "FillRequest[activity=" + getActivityName(contexts) + ", flags=" + flags
+ + ", bundle=" + data + ", structure=" + Helper.toString(structure) + "]";
}
}
diff --git a/tests/tests/location/src/android/location/cts/GnssTestCase.java b/tests/tests/location/src/android/location/cts/GnssTestCase.java
index 0258244..e1c5e88 100644
--- a/tests/tests/location/src/android/location/cts/GnssTestCase.java
+++ b/tests/tests/location/src/android/location/cts/GnssTestCase.java
@@ -15,9 +15,12 @@
*/
package android.location.cts;
+import android.os.Build;
import android.test.AndroidTestCase;
import android.util.Log;
+import com.android.compatibility.common.util.PropertyUtil;
+
/**
* Base Test Case class for all Gnss Tests.
*/
@@ -32,14 +35,15 @@
protected GnssTestCase() {
}
- // When CTS testing is run in Verifier mode access to GNSS signals is expected
// On devices using newer hardware, GNSS measurement support is required.
- // Hence when both conditions are true, we can verify stricter tests of functionality
- // availability.
protected boolean isMeasurementTestStrict() {
- return ((mTestLocationManager.getLocationManager().getGnssYearOfHardware() >=
- MIN_HARDWARE_YEAR_MEASUREMENTS_REQUIRED) &&
- isCtsVerifierTest());
+ // Enforce strict measurement test on devices with first API level at least P.
+ if (PropertyUtil.getFirstApiLevel() >= Build.VERSION_CODES.P) {
+ return true;
+ }
+
+ return (mTestLocationManager.getLocationManager().getGnssYearOfHardware() >=
+ MIN_HARDWARE_YEAR_MEASUREMENTS_REQUIRED);
}
public void setTestAsCtsVerifierTest(boolean value) {
diff --git a/tests/tests/security/src/android/security/cts/BluetoothIntentsTest.java b/tests/tests/security/src/android/security/cts/BluetoothIntentsTest.java
new file mode 100644
index 0000000..6a4990f
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/BluetoothIntentsTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2018 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 org.junit.Test;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.platform.test.annotations.SecurityTest;
+import android.test.AndroidTestCase;
+
+@SecurityTest
+public class BluetoothIntentsTest extends AndroidTestCase {
+ /**
+ * b/35258579
+ */
+ @SecurityTest
+ public void testAcceptIntent() {
+ genericIntentTest("ACCEPT");
+ }
+
+ /**
+ * b/35258579
+ */
+ @SecurityTest
+ public void testDeclineIntent() {
+ genericIntentTest("DECLINE");
+ }
+
+ private static final String prefix = "android.btopp.intent.action.";
+ private void genericIntentTest(String action) throws SecurityException {
+ try {
+ Intent should_be_protected_broadcast = new Intent();
+ should_be_protected_broadcast.setComponent(
+ new ComponentName("com.android.bluetooth",
+ "com.android.bluetooth.opp.BluetoothOppReceiver"));
+ should_be_protected_broadcast.setAction(prefix + action);
+ mContext.sendBroadcast(should_be_protected_broadcast);
+ }
+ catch (SecurityException e) {
+ return;
+ }
+
+ throw new SecurityException("An " + prefix + action +
+ " intent should not be broadcastable except by the system (declare " +
+ " as protected-broadcast in manifest)");
+ }
+}
diff --git a/tests/tests/view/src/android/view/cts/TextureViewTest.java b/tests/tests/view/src/android/view/cts/TextureViewTest.java
index f3f5318..88ac1f5 100644
--- a/tests/tests/view/src/android/view/cts/TextureViewTest.java
+++ b/tests/tests/view/src/android/view/cts/TextureViewTest.java
@@ -32,6 +32,7 @@
import android.graphics.ColorSpace;
import android.graphics.Matrix;
import android.graphics.Point;
+import android.graphics.Rect;
import android.support.test.filters.MediumTest;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
@@ -128,11 +129,93 @@
mActivityRule.runOnUiThread(() -> {
activity.getTextureView().getBitmap(bitmap);
});
+ // Verify the matrix did not rotate content of getTextureView.getBitmap().
PixelCopyTest.assertBitmapQuadColor(bitmap,
+ Color.RED, Color.GREEN, Color.BLUE, Color.BLACK);
+
+ // Remove cover and calculate TextureView position on the screen.
+ WidgetTestUtils.runOnMainAndDrawSync(mActivityRule,
+ activity.findViewById(android.R.id.content), () -> activity.removeCover());
+ final Rect viewPos = new Rect();
+ mActivityRule.runOnUiThread(() -> {
+ int[] outLocation = new int[2];
+ textureView.getLocationOnScreen(outLocation);
+ viewPos.left = outLocation[0];
+ viewPos.top = outLocation[1];
+ viewPos.right = viewPos.left + textureView.getWidth();
+ viewPos.bottom = viewPos.top + textureView.getHeight();
+ });
+
+ // Capture the portion of the screen that contains the texture view only.
+ Window window = activity.getWindow();
+ Bitmap screenshot = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
+ int result = new SynchronousPixelCopy().request(window, viewPos, screenshot);
+ assertEquals("Copy request failed", PixelCopy.SUCCESS, result);
+ // Verify the matrix rotated the TextureView content drawn on the screen.
+ PixelCopyTest.assertBitmapQuadColor(screenshot,
Color.BLACK, Color.BLUE, Color.GREEN, Color.RED);
}
@Test
+ public void testTransformScale() throws Throwable {
+ final TextureViewCtsActivity activity = mActivityRule.launchActivity(null);
+ final TextureView textureView = activity.getTextureView();
+ WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, activity.getTextureView(), null);
+ Matrix transform = new Matrix();
+ final float translateY = 100.0f;
+ final float scaleY = 0.25f;
+ float[] values = {1, 0, 0, 0, scaleY, translateY, 0, 0, 1};
+ transform.setValues(values);
+ activity.drawFrame(transform, TextureViewTest::drawGlQuad);
+ final Bitmap bitmap = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888);
+ mActivityRule.runOnUiThread(() -> {
+ activity.getTextureView().getBitmap(bitmap);
+ });
+ // Verify the matrix did not affect the content of getTextureView.getBitmap().
+ PixelCopyTest.assertBitmapQuadColor(bitmap,
+ Color.RED, Color.GREEN, Color.BLUE, Color.BLACK);
+
+ // Remove cover and calculate TextureView position on the screen.
+ WidgetTestUtils.runOnMainAndDrawSync(mActivityRule,
+ activity.findViewById(android.R.id.content), () -> activity.removeCover());
+ final Rect viewPos = new Rect();
+ mActivityRule.runOnUiThread(() -> {
+ int[] outLocation = new int[2];
+ textureView.getLocationOnScreen(outLocation);
+ viewPos.left = outLocation[0];
+ viewPos.top = outLocation[1];
+ viewPos.right = viewPos.left + textureView.getWidth();
+ viewPos.bottom = viewPos.top + textureView.getHeight();
+ });
+
+ // Capture the portion of the screen that contains the texture view only.
+ Window window = activity.getWindow();
+ Bitmap screenshot = Bitmap.createBitmap(viewPos.width(), viewPos.height(),
+ Bitmap.Config.ARGB_8888);
+ int result = new SynchronousPixelCopy().request(window, viewPos, screenshot);
+ assertEquals("Copy request failed", PixelCopy.SUCCESS, result);
+ // Verify the matrix scaled and translated the TextureView content drawn on the screen.
+ // "texturePos" has SurfaceTexture position inside the TextureView.
+ final Rect texturePos = new Rect(0, (int) translateY, viewPos.width(),
+ (int) (viewPos.height() * scaleY + translateY));
+
+ // Areas not covered by the texture are black, because FrameLayout background is set to
+ // Color.BLACK in TextureViewCtsActivity.onCreate.
+ assertEquals("above texture", Color.BLACK,
+ screenshot.getPixel(10, texturePos.top - 10));
+ assertEquals("below texture", Color.BLACK,
+ screenshot.getPixel(10, texturePos.bottom + 10));
+ assertEquals("top left", Color.RED,
+ screenshot.getPixel(texturePos.left + 10, texturePos.top + 10));
+ assertEquals("top right", Color.GREEN,
+ screenshot.getPixel(texturePos.right - 10, texturePos.top + 10));
+ assertEquals("Bottom left", Color.BLUE,
+ screenshot.getPixel(texturePos.left + 10, texturePos.bottom - 10));
+ assertEquals("Bottom right", Color.BLACK,
+ screenshot.getPixel(texturePos.right - 10, texturePos.bottom - 10));
+ }
+
+ @Test
public void testGetBitmap_8888_P3() throws Throwable {
testGetBitmap(EGL_GL_COLORSPACE_DISPLAY_P3_EXT, ColorSpace.Named.DISPLAY_P3, false,
new FP16Compare(ColorSpace.Named.EXTENDED_SRGB));