diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2018-07-20 23:43:21 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2018-07-20 23:43:21 +0000 |
commit | f3ee0f9881d1dc40a3beb1bb5133e714898995f2 (patch) | |
tree | 6842f101d7eaf591adb0d7f9d74b79ee123d8180 | |
parent | cfb7086f650860c66933a4d500e14fcbf2127d2f (diff) | |
parent | 4168bf95c63bcb26497b4356ab03f6dc8fef74d8 (diff) | |
download | cts-pie-dr1-release.tar.gz |
Snap for 4905103 from 8f363645a9d3ecfb390377454581a0e6e7e8b3c6 to pi-dr1-releaseandroid-9.0.0_r12android-9.0.0_r11pie-dr1-release
Change-Id: I481c10976e15834b699795f5fd076200dbfce5d9
16 files changed, 562 insertions, 288 deletions
diff --git a/apps/CameraITS/tests/scene1/test_auto_vs_manual.py b/apps/CameraITS/tests/scene1/test_auto_vs_manual.py index 9c49575a588..a7b5add964a 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.device 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 @@ def main(): # 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 002af377bb8..e8cf2ef1697 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 @@ public class ItsService extends Service implements SensorEventListener { 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 @@ public class ItsService extends Service implements SensorEventListener { } 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 @@ public class ItsService extends Service implements SensorEventListener { } } - // 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 @@ public class ItsService extends Service implements SensorEventListener { } 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 @@ public class ItsService extends Service implements SensorEventListener { } mInterlock3A.close(); - // 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); - - if (evComp != 0) { - req.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, evComp); - } + 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); + + 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); - } + 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; - } + 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; - } + // 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()); + req.addTarget(mOutputImageReaders[0].getSurface()); - mIssuedRequest3A = true; - mSession.capture(req.build(), mCaptureResultListener, mResultHandler); - } else { - mSocketRunnableObj.sendResponse("3aConverged", ""); - Logt.i(TAG, "3A converged"); - break; + 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; + } } } } catch (android.hardware.camera2.CameraAccessException e) { @@ -1185,6 +1199,11 @@ public class ItsService extends Service implements SensorEventListener { throw new ItsException("JSON error: ", e); } finally { mSocketRunnableObj.sendResponse("3aDone", ""); + // stop listener from updating 3A states + threeAListener.stop(); + if (mSession != null) { + mSession.close(); + } } } @@ -1778,7 +1797,72 @@ public class ItsService extends Service implements SensorEventListener { return (float)r.getNumerator() / (float)r.getDenominator(); } - private final CaptureResultListener mCaptureResultListener = new CaptureResultListener() { + 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) { @@ -1788,156 +1872,146 @@ public class ItsService extends Service implements SensorEventListener { public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) { try { - // Currently result has all 0 values. + if (stopped) { + return; + } + 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; + 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 (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()); - - 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 (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) { - 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 (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)) { - 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 (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)); + } } } - 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(); - } + 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, + long timestamp, long frameNumber) { + } + + @Override + public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, + TotalCaptureResult result) { + try { + if (request == null || result == null) { + throw new ItsException("Request/result is invalid"); + } + + Logt.i(TAG, buildLogString(result)); + + 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/incident/src/com/android/server/cts/BatteryStatsValidationTest.java b/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java index 263327f8ca9..65cb2a5f68c 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 @@ public class BatteryStatsValidationTest extends ProtoDumpTestCase { 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 80c959c87ac..a6f1e042e62 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 @@ public class Poc17_03 extends SecurityTestCase { 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 00000000000..40c4f0363e5 --- /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 2fa1ac4f723..225ebf54e7d 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 @@ public class AtomTestCase extends BaseTestCase { 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 @@ public class AtomTestCase extends BaseTestCase { @Override protected void tearDown() throws Exception { removeConfig(CONFIG_ID); + getDevice().uninstallPackage(DEVICE_SIDE_TEST_PACKAGE); super.tearDown(); } @@ -130,6 +129,18 @@ public class AtomTestCase extends BaseTestCase { 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 fc4a5619e34..cd396ecf1e9 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 @@ public class BaseTestCase extends DeviceTestCase implements IBuildReceiver { 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 eb96b8362d2..5c7d2448704 100644 --- a/hostsidetests/statsd/src/android/cts/statsd/atom/HostAtomTests.java +++ b/hostsidetests/statsd/src/android/cts/statsd/atom/HostAtomTests.java @@ -522,6 +522,8 @@ public class HostAtomTests extends AtomTestCase { } 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 154f41f3934..f845bb74399 100644 --- a/tests/app/src/android/app/cts/DisplayTest.java +++ b/tests/app/src/android/app/cts/DisplayTest.java @@ -58,7 +58,14 @@ public class DisplayTest extends ActivityInstrumentationTestCase2<DisplayTestAct // 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 @@ public class DisplayTest extends ActivityInstrumentationTestCase2<DisplayTestAct 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 a5643ea7dcc..4d409a25a2b 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 31ac8f7c013..90871cad11d 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.os.Bundle; 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 @@ public class DuplicateIdActivity extends AbstractAutoFillActivity { 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 29ec2b166d4..846dcc41bfc 100644 --- a/tests/autofillservice/src/android/autofillservice/cts/DuplicateIdActivityTest.java +++ b/tests/autofillservice/src/android/autofillservice/cts/DuplicateIdActivityTest.java @@ -89,13 +89,14 @@ public class DuplicateIdActivityTest extends AutoFillServiceTestCase { // 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 @@ public class DuplicateIdActivityTest extends AutoFillServiceTestCase { // 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 79347304610..4e5418bb299 100644 --- a/tests/autofillservice/src/android/autofillservice/cts/Helper.java +++ b/tests/autofillservice/src/android/autofillservice/cts/Helper.java @@ -156,19 +156,37 @@ final class Helper { return hasHint(view.getAutofillHints(), id); }; - /** - * Dump the assist structure on logcat. - */ - static void dumpStructure(String message, AssistStructure structure) { - final StringBuffer buffer = new StringBuffer(message) - .append(": component=") - .append(structure.getActivityComponent()); + 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(buffer, windowNode.getRootViewNode(), " ", 0); + dump(builder, windowNode.getRootViewNode(), " ", 0); } - Log.i(TAG, buffer.toString()); + 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) { + Log.i(TAG, toString(structure, new StringBuilder(message))); } /** @@ -194,39 +212,69 @@ final class Helper { 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 42b6b41ce5e..6b47c9f1839 100644 --- a/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java +++ b/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java @@ -293,12 +293,13 @@ public class InstrumentedAutoFillService extends AutofillService { 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 0258244b83e..e1c5e880c27 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 @@ public abstract class GnssTestCase extends AndroidTestCase { 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 00000000000..6a4990faab8 --- /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)"); + } +} |