Merge "Raise the min version of sdk for CtsInputMethodServiceEventProvider"
diff --git a/common/device-side/util/src/com/android/compatibility/common/util/BusinessLogicConditionalTestCase.java b/common/device-side/util/src/com/android/compatibility/common/util/BusinessLogicConditionalTestCase.java
deleted file mode 100644
index d12caa8..0000000
--- a/common/device-side/util/src/com/android/compatibility/common/util/BusinessLogicConditionalTestCase.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2017 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.compatibility.common.util;
-
-import org.junit.Before;
-
-/**
- * Device-side base class for tests leveraging the Business Logic service for rules that are
- * conditionally added based on the device characteristics.
- */
-public class BusinessLogicConditionalTestCase extends BusinessLogicTestCase {
-
- @Override
- @Before
- public void handleBusinessLogic() {
- super.loadBusinessLogic();
- ensureAuthenticated();
- super.executeBusinessLogic();
- }
-
- protected void ensureAuthenticated() {
- if (!mCanReadBusinessLogic) {
- // super class handles the condition that the service is unavailable.
- return;
- }
-
- if (!mBusinessLogic.mConditionalTestsEnabled) {
- skipTest("Execution of device specific tests is not enabled. "
- + "Enable with '--conditional-business-logic-tests-enabled'");
- }
-
- if (mBusinessLogic.isAuthorized()) {
- // Run test as normal.
- return;
- }
- String message = mBusinessLogic.getAuthenticationStatusMessage();
-
- // Fail test since request was not authorized.
- failTest(String.format("Unable to execute because %s.", message));
- }
-}
diff --git a/common/device-side/util/src/com/android/compatibility/common/util/BusinessLogicTestCase.java b/common/device-side/util/src/com/android/compatibility/common/util/BusinessLogicTestCase.java
index 671d33b..29607c3 100644
--- a/common/device-side/util/src/com/android/compatibility/common/util/BusinessLogicTestCase.java
+++ b/common/device-side/util/src/com/android/compatibility/common/util/BusinessLogicTestCase.java
@@ -51,6 +51,7 @@
@Before
public void handleBusinessLogic() {
loadBusinessLogic();
+ ensureAuthenticated();
executeBusinessLogic();
}
@@ -79,6 +80,27 @@
}
}
+ protected void ensureAuthenticated() {
+ if (!mCanReadBusinessLogic) {
+ // super class handles the condition that the service is unavailable.
+ return;
+ }
+
+ if (!mBusinessLogic.mConditionalTestsEnabled) {
+ skipTest("Execution of device specific tests is not enabled. "
+ + "Enable with '--conditional-business-logic-tests-enabled'");
+ }
+
+ if (mBusinessLogic.isAuthorized()) {
+ // Run test as normal.
+ return;
+ }
+ String message = mBusinessLogic.getAuthenticationStatusMessage();
+
+ // Fail test since request was not authorized.
+ failTest(String.format("Unable to execute because %s.", message));
+ }
+
protected static Instrumentation getInstrumentation() {
return InstrumentationRegistry.getInstrumentation();
}
diff --git a/tests/acceleration/Android.mk b/tests/acceleration/Android.mk
index cef4379..8ae5ddc 100644
--- a/tests/acceleration/Android.mk
+++ b/tests/acceleration/Android.mk
@@ -32,7 +32,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
+LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
LOCAL_PACKAGE_NAME := CtsAccelerationTestCases
diff --git a/tests/acceleration/AndroidManifest.xml b/tests/acceleration/AndroidManifest.xml
index 1a21554..27ff97a 100644
--- a/tests/acceleration/AndroidManifest.xml
+++ b/tests/acceleration/AndroidManifest.xml
@@ -15,7 +15,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.acceleration.cts">
+ package="android.acceleration.cts"
+ android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
diff --git a/tests/acceleration/AndroidTest.xml b/tests/acceleration/AndroidTest.xml
index b28f845..68eb78f 100644
--- a/tests/acceleration/AndroidTest.xml
+++ b/tests/acceleration/AndroidTest.xml
@@ -16,6 +16,8 @@
<configuration description="Config for CTS Acceleration test cases">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="location" />
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsAccelerationTestCases.apk" />
diff --git a/tests/autofillservice/AndroidManifest.xml b/tests/autofillservice/AndroidManifest.xml
index 5955274..eee73f5 100644
--- a/tests/autofillservice/AndroidManifest.xml
+++ b/tests/autofillservice/AndroidManifest.xml
@@ -27,7 +27,8 @@
<uses-library android:name="android.test.runner" />
- <activity android:name=".LoginActivity" >
+ <activity android:name=".LoginActivity"
+ android:screenOrientation="portrait">
<intent-filter>
<!-- This intent filter is not really needed by CTS, but it makes easier to launch
this app during CTS development... -->
diff --git a/tests/camera/libctscamera2jni/native-camera-jni.cpp b/tests/camera/libctscamera2jni/native-camera-jni.cpp
index 9ab8222..7dac96f 100644
--- a/tests/camera/libctscamera2jni/native-camera-jni.cpp
+++ b/tests/camera/libctscamera2jni/native-camera-jni.cpp
@@ -653,22 +653,46 @@
}
int64_t getMinFrameDurationFor(int64_t format, int64_t width, int64_t height) {
- return getDurationFor(ACAMERA_SCALER_AVAILABLE_MIN_FRAME_DURATIONS, format, width, height);
+ int32_t minFrameDurationTag = (format == AIMAGE_FORMAT_HEIC) ?
+ ACAMERA_HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS :
+ ACAMERA_SCALER_AVAILABLE_MIN_FRAME_DURATIONS;
+ return getDurationFor(minFrameDurationTag, format, width, height);
}
int64_t getStallDurationFor(int64_t format, int64_t width, int64_t height) {
- return getDurationFor(ACAMERA_SCALER_AVAILABLE_STALL_DURATIONS, format, width, height);
+ int32_t stallDurationTag = (format == AIMAGE_FORMAT_HEIC) ?
+ ACAMERA_HEIC_AVAILABLE_HEIC_STALL_DURATIONS :
+ ACAMERA_SCALER_AVAILABLE_STALL_DURATIONS;
+ return getDurationFor(stallDurationTag, format, width, height);
}
bool getMaxSizeForFormat(int32_t format, int32_t *width, int32_t *height) {
ACameraMetadata_const_entry entry;
- ACameraMetadata_getConstEntry(mChars,
- ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &entry);
+
+ int32_t streamConfigTag, streamConfigOutputTag;
+ switch (format) {
+ case AIMAGE_FORMAT_HEIC:
+ streamConfigTag = ACAMERA_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS;
+ streamConfigOutputTag = ACAMERA_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS_OUTPUT;
+ break;
+ case AIMAGE_FORMAT_JPEG:
+ case AIMAGE_FORMAT_Y8:
+ default:
+ streamConfigTag = ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS;
+ streamConfigOutputTag = ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT;
+ break;
+ }
+
bool supported = false;
- int32_t w = 0, h = 0;
+ camera_status_t status = ACameraMetadata_getConstEntry(mChars, streamConfigTag, &entry);
+ if (status == ACAMERA_ERROR_METADATA_NOT_FOUND) {
+ return supported;
+ }
+
+ int32_t w = 0, h = 0;
for (uint32_t i = 0; i < entry.count; i += 4) {
if (entry.data.i32[i] == format &&
- entry.data.i32[i+3] == ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
+ entry.data.i32[i+3] == streamConfigOutputTag &&
entry.data.i32[i+1] * entry.data.i32[i+2] > w * h) {
w = entry.data.i32[i+1];
h = entry.data.i32[i+2];
@@ -685,11 +709,25 @@
bool isSizeSupportedForFormat(int32_t format, int32_t width, int32_t height) {
ACameraMetadata_const_entry entry;
- ACameraMetadata_getConstEntry(mChars,
- ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &entry);
+
+ int32_t streamConfigTag, streamConfigOutputTag;
+ switch (format) {
+ case AIMAGE_FORMAT_HEIC:
+ streamConfigTag = ACAMERA_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS;
+ streamConfigOutputTag = ACAMERA_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS_OUTPUT;
+ break;
+ case AIMAGE_FORMAT_JPEG:
+ case AIMAGE_FORMAT_Y8:
+ default:
+ streamConfigTag = ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS;
+ streamConfigOutputTag = ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT;
+ break;
+ }
+
+ ACameraMetadata_getConstEntry(mChars, streamConfigTag, &entry);
for (uint32_t i = 0; i < entry.count; i += 4) {
if (entry.data.i32[i] == format &&
- entry.data.i32[i+3] == ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
+ entry.data.i32[i+3] == streamConfigOutputTag &&
entry.data.i32[i+1] == width &&
entry.data.i32[i+2] == height) {
return true;
@@ -702,7 +740,9 @@
if (tag != ACAMERA_SCALER_AVAILABLE_MIN_FRAME_DURATIONS &&
tag != ACAMERA_SCALER_AVAILABLE_STALL_DURATIONS &&
tag != ACAMERA_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS &&
- tag != ACAMERA_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS) {
+ tag != ACAMERA_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS &&
+ tag != ACAMERA_HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS &&
+ tag != ACAMERA_HEIC_AVAILABLE_HEIC_STALL_DURATIONS) {
return -1;
}
ACameraMetadata_const_entry entry;
@@ -2860,6 +2900,7 @@
testHeight = TEST_HEIGHT;
break;
case AIMAGE_FORMAT_Y8:
+ case AIMAGE_FORMAT_HEIC:
if (!staticInfo.getMaxSizeForFormat(format, &testWidth, &testHeight)) {
// This isn't an error condition: device does't support this
// format.
@@ -2956,13 +2997,13 @@
}
int64_t minFrameDurationNs = staticInfo.getMinFrameDurationFor(
- AIMAGE_FORMAT_JPEG, TEST_WIDTH, TEST_HEIGHT);
+ format, testWidth, testHeight);
if (minFrameDurationNs < 0) {
LOG_ERROR(errorString, "Get camera %s minFrameDuration failed", cameraId);
goto cleanup;
}
- int64_t stallDurationNs = staticInfo.getStallDurationFor(
- AIMAGE_FORMAT_JPEG, TEST_WIDTH, TEST_HEIGHT);
+ int64_t stallDurationNs = (format == AIMAGE_FORMAT_Y8) ? 0 :
+ staticInfo.getStallDurationFor(format, testWidth, testHeight);
if (stallDurationNs < 0) {
LOG_ERROR(errorString, "Get camera %s stallDuration failed", cameraId);
goto cleanup;
@@ -3053,6 +3094,15 @@
extern "C" jboolean
Java_android_hardware_camera2_cts_NativeImageReaderTest_\
+testHeicNative(
+ JNIEnv* env, jclass /*clazz*/, jstring jOutPath) {
+ ALOGV("%s", __FUNCTION__);
+ return nativeImageReaderTestBase(env, jOutPath, AIMAGE_FORMAT_HEIC,
+ ImageReaderListener::validateImageCb);
+}
+
+extern "C" jboolean
+Java_android_hardware_camera2_cts_NativeImageReaderTest_\
testImageReaderCloseAcquiredImagesNative(
JNIEnv* env, jclass /*clazz*/) {
ALOGV("%s", __FUNCTION__);
diff --git a/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
index b095b8a..8eff888 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
@@ -187,6 +187,7 @@
boolean isMonochromeWithY8 = arrayContains(actualCapabilities, MONOCHROME)
&& arrayContains(outputFormats, ImageFormat.Y8);
+ boolean supportHeic = arrayContains(outputFormats, ImageFormat.HEIC);
assertArrayContains(
String.format("No valid YUV_420_888 preview formats found for: ID %s",
@@ -202,6 +203,7 @@
Size[] yuvSizes = config.getOutputSizes(ImageFormat.YUV_420_888);
Size[] y8Sizes = config.getOutputSizes(ImageFormat.Y8);
Size[] jpegSizes = config.getOutputSizes(ImageFormat.JPEG);
+ Size[] heicSizes = config.getOutputSizes(ImageFormat.HEIC);
Size[] privateSizes = config.getOutputSizes(ImageFormat.PRIVATE);
CameraTestUtils.assertArrayNotEmpty(yuvSizes,
@@ -224,6 +226,12 @@
"Required FULLHD size not found for format %x for: ID %s",
ImageFormat.JPEG, mIds[counter]), jpegSizes,
new Size[] {FULLHD, FULLHD_ALT});
+ if (supportHeic) {
+ assertArrayContainsAnyOf(String.format(
+ "Required FULLHD size not found for format %x for: ID %s",
+ ImageFormat.HEIC, mIds[counter]), heicSizes,
+ new Size[] {FULLHD, FULLHD_ALT});
+ }
}
if (activeArraySize.getWidth() >= HD.getWidth() &&
@@ -231,6 +239,11 @@
assertArrayContains(String.format(
"Required HD size not found for format %x for: ID %s",
ImageFormat.JPEG, mIds[counter]), jpegSizes, HD);
+ if (supportHeic) {
+ assertArrayContains(String.format(
+ "Required HD size not found for format %x for: ID %s",
+ ImageFormat.HEIC, mIds[counter]), heicSizes, HD);
+ }
}
if (activeArraySize.getWidth() >= VGA.getWidth() &&
@@ -238,6 +251,11 @@
assertArrayContains(String.format(
"Required VGA size not found for format %x for: ID %s",
ImageFormat.JPEG, mIds[counter]), jpegSizes, VGA);
+ if (supportHeic) {
+ assertArrayContains(String.format(
+ "Required VGA size not found for format %x for: ID %s",
+ ImageFormat.HEIC, mIds[counter]), heicSizes, VGA);
+ }
}
if (activeArraySize.getWidth() >= QVGA.getWidth() &&
@@ -245,6 +263,12 @@
assertArrayContains(String.format(
"Required QVGA size not found for format %x for: ID %s",
ImageFormat.JPEG, mIds[counter]), jpegSizes, QVGA);
+ if (supportHeic) {
+ assertArrayContains(String.format(
+ "Required QVGA size not found for format %x for: ID %s",
+ ImageFormat.HEIC, mIds[counter]), heicSizes, QVGA);
+ }
+
}
ArrayList<Size> jpegSizesList = new ArrayList<>(Arrays.asList(jpegSizes));
@@ -1363,6 +1387,8 @@
CameraCharacteristics.SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE);
Rect activeArray = c.get(
CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
+ float jpegAspectRatioThreshold = .01f;
+ boolean jpegSizeMatch = false;
// Verify pre-correction array encloses active array
mCollector.expectTrue("preCorrectionArray [" + precorrectionArray.left + ", " +
@@ -1392,6 +1418,7 @@
hasDepth16);
if (hasDepth16) {
Size[] depthSizes = configs.getOutputSizes(ImageFormat.DEPTH16);
+ Size[] jpegSizes = configs.getOutputSizes(ImageFormat.JPEG);
mCollector.expectTrue("Supports DEPTH_OUTPUT but no sizes for DEPTH16 supported!",
depthSizes != null && depthSizes.length > 0);
if (depthSizes != null) {
@@ -1408,6 +1435,24 @@
mCollector.expectTrue("Non-negative stall duration for depth size "
+ depthSize + " expected, got " + stallDuration,
stallDuration >= 0);
+ if ((jpegSizes != null) && (!jpegSizeMatch)) {
+ for (Size jpegSize : jpegSizes) {
+ if (jpegSize.equals(depthSize)) {
+ jpegSizeMatch = true;
+ break;
+ } else {
+ float depthAR = (float) depthSize.getWidth() /
+ (float) depthSize.getHeight();
+ float jpegAR = (float) jpegSize.getWidth() /
+ (float) jpegSize.getHeight();
+ if (Math.abs(depthAR - jpegAR) <=
+ jpegAspectRatioThreshold) {
+ jpegSizeMatch = true;
+ break;
+ }
+ }
+ }
+ }
}
}
}
@@ -1446,6 +1491,8 @@
mCollector.expectTrue("Supports DEPTH_JPEG " +
"but no sizes for DEPTH_JPEG supported!",
depthJpegSizes != null && depthJpegSizes.length > 0);
+ mCollector.expectTrue("Supports DEPTH_JPEG but there are no JPEG sizes with" +
+ " matching DEPTH16 aspect ratio", jpegSizeMatch);
if (depthJpegSizes != null) {
for (Size depthJpegSize : depthJpegSizes) {
mCollector.expectTrue("All depth jpeg sizes must be nonzero",
@@ -1462,6 +1509,11 @@
stallDuration >= 0);
}
}
+ } else {
+ boolean canSupportDynamicDepth = jpegSizeMatch && !depthIsExclusive;
+ mCollector.expectTrue("Device must support DEPTH_JPEG, please check whether " +
+ "library libdepthphoto.so is part of the device PRODUCT_PACKAGES",
+ !canSupportDynamicDepth);
}
diff --git a/tests/camera/src/android/hardware/camera2/cts/FastBasicsTest.java b/tests/camera/src/android/hardware/camera2/cts/FastBasicsTest.java
index af6e5e0..0716c24 100644
--- a/tests/camera/src/android/hardware/camera2/cts/FastBasicsTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/FastBasicsTest.java
@@ -91,7 +91,7 @@
SimpleImageReaderListener imageListener = new SimpleImageReaderListener();
prepareStillCaptureAndStartPreview(previewRequest, stillCaptureRequest,
- previewSize, stillSize, resultListener, imageListener);
+ previewSize, stillSize, resultListener, imageListener, false /*isHeic*/);
CaptureResult result = resultListener.getCaptureResult(WAIT_FOR_FRAMES_TIMEOUT_MS);
diff --git a/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java b/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java
index e275aa4..b8cf221 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ImageReaderTest.java
@@ -204,6 +204,17 @@
}
}
+ public void testHeic() throws Exception {
+ for (String id : mCameraIds) {
+ try {
+ Log.v(TAG, "Testing heic capture for Camera " + id);
+ openDevice(id);
+ bufferFormatTestByCamera(ImageFormat.HEIC, /*repeating*/false);
+ } finally {
+ closeDevice(id);
+ }
+ }
+ }
public void testRepeatingJpeg() throws Exception {
for (String id : mCameraIds) {
@@ -243,6 +254,18 @@
}
}
+ public void testRepeatingHeic() throws Exception {
+ for (String id : mCameraIds) {
+ try {
+ Log.v(TAG, "Testing repeating heic capture for Camera " + id);
+ openDevice(id);
+ bufferFormatTestByCamera(ImageFormat.HEIC, /*repeating*/true);
+ } finally {
+ closeDevice(id);
+ }
+ }
+ }
+
public void testLongProcessingRepeatingRaw() throws Exception {
for (String id : mCameraIds) {
try {
diff --git a/tests/camera/src/android/hardware/camera2/cts/NativeImageReaderTest.java b/tests/camera/src/android/hardware/camera2/cts/NativeImageReaderTest.java
index 4eee734..ce5f946 100644
--- a/tests/camera/src/android/hardware/camera2/cts/NativeImageReaderTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/NativeImageReaderTest.java
@@ -43,6 +43,11 @@
testY8Native(mDebugFileNameBase));
}
+ public void testHeic() {
+ assertTrue("testHeic fail, see log for details",
+ testHeicNative(mDebugFileNameBase));
+ }
+
public void testImageReaderCloseAcquiredImages() {
assertTrue("testImageReaderClose fail, see log for details",
testImageReaderCloseAcquiredImagesNative());
@@ -50,5 +55,6 @@
private static native boolean testJpegNative(String filePath);
private static native boolean testY8Native(String filePath);
+ private static native boolean testHeicNative(String filePath);
private static native boolean testImageReaderCloseAcquiredImagesNative();
}
diff --git a/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java b/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
index 0fa1741..fbb8cce 100644
--- a/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
@@ -363,7 +363,8 @@
readers = prepareStillCaptureAndStartPreview(previewBuilder, captureBuilder,
mOrderedPreviewSizes.get(0), imageSizes, formats,
- previewResultListener, NUM_MAX_IMAGES, imageListeners);
+ previewResultListener, NUM_MAX_IMAGES, imageListeners,
+ false /*isHeic*/);
if (addPreviewDelay) {
Thread.sleep(500);
@@ -1141,11 +1142,13 @@
* @param resultListener Capture result listener
* @param maxNumImages The max number of images set to the image reader
* @param imageListeners The single capture capture image listeners
+ * @param isHeic Capture HEIC image if true, JPEG image if false
*/
private ImageReader[] prepareStillCaptureAndStartPreview(
CaptureRequest.Builder previewRequest, CaptureRequest.Builder stillRequest,
Size previewSz, Size[] captureSizes, int[] formats, CaptureCallback resultListener,
- int maxNumImages, ImageReader.OnImageAvailableListener[] imageListeners)
+ int maxNumImages, ImageReader.OnImageAvailableListener[] imageListeners,
+ boolean isHeic)
throws Exception {
if ((captureSizes == null) || (formats == null) || (imageListeners == null) &&
diff --git a/tests/camera/src/android/hardware/camera2/cts/ReprocessCaptureTest.java b/tests/camera/src/android/hardware/camera2/cts/ReprocessCaptureTest.java
index 8fa1077..1420078 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ReprocessCaptureTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ReprocessCaptureTest.java
@@ -116,6 +116,24 @@
}
/**
+ * Test YUV_420_888 -> HEIC with maximal supported sizes
+ */
+ @Test
+ public void testBasicYuvToHeicReprocessing() throws Exception {
+ for (String id : mCameraIds) {
+ if (!isYuvReprocessSupported(id)) {
+ continue;
+ }
+ if (!mAllStaticInfo.get(id).isHeicSupported()) {
+ continue;
+ }
+
+ // YUV_420_888 -> HEIC must be supported.
+ testBasicReprocessing(id, ImageFormat.YUV_420_888, ImageFormat.HEIC);
+ }
+ }
+
+ /**
* Test OPAQUE -> YUV_420_888 with maximal supported sizes
*/
@Test
@@ -146,6 +164,24 @@
}
/**
+ * Test OPAQUE -> HEIC with maximal supported sizes
+ */
+ @Test
+ public void testBasicOpaqueToHeicReprocessing() throws Exception {
+ for (String id : mCameraIds) {
+ if (!isOpaqueReprocessSupported(id)) {
+ continue;
+ }
+ if (!mAllStaticInfo.get(id).isHeicSupported()) {
+ continue;
+ }
+
+ // OPAQUE -> HEIC must be supported.
+ testBasicReprocessing(id, ImageFormat.PRIVATE, ImageFormat.HEIC);
+ }
+ }
+
+ /**
* Test all supported size and format combinations.
*/
@Test(timeout=60*60*1000) // timeout = 60 mins for long running tests
@@ -978,7 +1014,7 @@
Image image = getReprocessOutputImageReaderListener().getImage(CAPTURE_TIMEOUT_MS);
verifyJpegKeys(image, reprocessResults[i], reprocessOutputSize,
testThumbnailSizes[i], EXIF_TEST_DATA[i], mStaticInfo, mCollector,
- mDebugFileNameBase);
+ mDebugFileNameBase, ImageFormat.JPEG);
image.close();
}
@@ -1391,6 +1427,9 @@
case ImageFormat.JPEG:
filename += ".jpg";
break;
+ case ImageFormat.HEIC:
+ filename += ".heic";
+ break;
case ImageFormat.NV16:
case ImageFormat.NV21:
case ImageFormat.YUV_420_888:
diff --git a/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java b/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
index 995a2c7..a519101 100644
--- a/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
@@ -254,8 +254,10 @@
private void setupConfigurationTargets(List<MandatoryStreamInformation> streamsInfo,
List<SurfaceTexture> privTargets, List<ImageReader> jpegTargets,
List<ImageReader> yuvTargets, List<ImageReader> y8Targets,
- List<ImageReader> rawTargets, List<OutputConfiguration> outputConfigs,
- int numBuffers, boolean substituteY8, MandatoryStreamInformation overrideStreamInfo,
+ List<ImageReader> rawTargets, List<ImageReader> heicTargets,
+ List<OutputConfiguration> outputConfigs,
+ int numBuffers, boolean substituteY8, boolean substituteHeic,
+ MandatoryStreamInformation overrideStreamInfo,
List<String> overridePhysicalCameraIds, List<Size> overridePhysicalCameraSizes) {
ImageDropperListener imageDropperListener = new ImageDropperListener();
@@ -267,6 +269,8 @@
int format = streamInfo.getFormat();
if (substituteY8 && (format == ImageFormat.YUV_420_888)) {
format = ImageFormat.Y8;
+ } else if (substituteHeic && (format == ImageFormat.JPEG)) {
+ format = ImageFormat.HEIC;
}
Surface newSurface;
Size[] availableSizes = new Size[streamInfo.getAvailableSizes().size()];
@@ -345,6 +349,18 @@
}
break;
}
+ case ImageFormat.HEIC: {
+ ImageReader target = ImageReader.newInstance(targetSize.getWidth(),
+ targetSize.getHeight(), format, numBuffers);
+ target.setOnImageAvailableListener(imageDropperListener, mHandler);
+ OutputConfiguration config = new OutputConfiguration(target.getSurface());
+ if (numConfigs > 1) {
+ config.setPhysicalCameraId(overridePhysicalCameraIds.get(j));
+ }
+ outputConfigs.add(config);
+ heicTargets.add(target);
+ break;
+ }
default:
fail("Unknown output format " + format);
}
@@ -366,13 +382,36 @@
}
}
+ // Check whether substituting JPEG format with HEIC format
+ boolean substituteHeic = false;
+ if (mStaticInfo.isHeicSupported()) {
+ List<MandatoryStreamInformation> streamsInfo = combination.getStreamsInformation();
+ for (MandatoryStreamInformation streamInfo : streamsInfo) {
+ if (streamInfo.getFormat() == ImageFormat.JPEG) {
+ substituteHeic = true;
+ break;
+ }
+ }
+ }
+
// Test camera output combination
Log.i(TAG, "Testing mandatory stream combination: " + combination.getDescription() +
" on camera: " + cameraId);
- testMandatoryStreamCombination(cameraId, combination, /*substituteY8*/false);
+ testMandatoryStreamCombination(cameraId, combination, /*substituteY8*/false,
+ /*substituteHeic*/false);
if (substituteY8) {
- testMandatoryStreamCombination(cameraId, combination, substituteY8);
+ Log.i(TAG, "Testing mandatory stream combination: " + combination.getDescription() +
+ " on camera: " + cameraId + " with Y8");
+ testMandatoryStreamCombination(cameraId, combination, /*substituteY8*/true,
+ /*substituteHeic*/false);
+ }
+
+ if (substituteHeic) {
+ Log.i(TAG, "Testing mandatory stream combination: " + combination.getDescription() +
+ " on camera: " + cameraId + " with HEIC");
+ testMandatoryStreamCombination(cameraId, combination,
+ /*substituteY8*/false, /*substituteHeic*/true);
}
// Test substituting YUV_888/RAW with physical streams for logical camera
@@ -383,7 +422,7 @@
testMultiCameraOutputCombination(cameraId, combination, /*substituteY8*/false);
if (substituteY8) {
- testMultiCameraOutputCombination(cameraId, combination, substituteY8);
+ testMultiCameraOutputCombination(cameraId, combination, /*substituteY8*/true);
}
}
}
@@ -441,10 +480,12 @@
List<ImageReader> yuvTargets = new ArrayList<ImageReader>();
List<ImageReader> y8Targets = new ArrayList<ImageReader>();
List<ImageReader> rawTargets = new ArrayList<ImageReader>();
+ List<ImageReader> heicTargets = new ArrayList<ImageReader>();
setupConfigurationTargets(streamsInfo, privTargets, jpegTargets, yuvTargets,
- y8Targets, rawTargets, outputConfigs, MIN_RESULT_COUNT, substituteY8,
- streamInfo, physicalCamerasForSize, physicalCameraSizes);
+ y8Targets, rawTargets, heicTargets, outputConfigs, MIN_RESULT_COUNT,
+ substituteY8, /*substituteHeic*/false, streamInfo, physicalCamerasForSize,
+ physicalCameraSizes);
boolean haveSession = false;
try {
@@ -516,7 +557,8 @@
}
private void testMandatoryStreamCombination(String cameraId,
- MandatoryStreamCombination combination, boolean substituteY8) throws Exception {
+ MandatoryStreamCombination combination,
+ boolean substituteY8, boolean substituteHeic) throws Exception {
// Timeout is relaxed by 1 second for LEGACY devices to reduce false positive rate in CTS
final int TIMEOUT_FOR_RESULT_MS = (mStaticInfo.isHardwareLevelLegacy()) ? 2000 : 1000;
@@ -529,9 +571,11 @@
List<ImageReader> yuvTargets = new ArrayList<ImageReader>();
List<ImageReader> y8Targets = new ArrayList<ImageReader>();
List<ImageReader> rawTargets = new ArrayList<ImageReader>();
+ List<ImageReader> heicTargets = new ArrayList<ImageReader>();
setupConfigurationTargets(combination.getStreamsInformation(), privTargets, jpegTargets,
- yuvTargets, y8Targets, rawTargets, outputConfigs, MIN_RESULT_COUNT, substituteY8,
+ yuvTargets, y8Targets, rawTargets, heicTargets, outputConfigs, MIN_RESULT_COUNT,
+ substituteY8, substituteHeic,
null /*overrideStreamInfo*/, null /*overridePhysicalCameraIds*/,
null /* overridePhysicalCameraSizes) */);
@@ -600,6 +644,9 @@
for (ImageReader target : rawTargets) {
target.close();
}
+ for (ImageReader target : heicTargets) {
+ target.close();
+ }
}
/**
@@ -635,26 +682,42 @@
private void testMandatoryReprocessableStreamCombination(String cameraId,
MandatoryStreamCombination combination) {
// Test reprocess stream combination
- testMandatoryReprocessableStreamCombination(cameraId, combination, /*substituteY8*/false);
+ testMandatoryReprocessableStreamCombination(cameraId, combination,
+ /*substituteY8*/false, /*substituteHeic*/false);
// Test substituting YUV_888 format with Y8 format in reprocess stream combination.
if (mStaticInfo.isMonochromeWithY8()) {
List<MandatoryStreamInformation> streamsInfo = combination.getStreamsInformation();
- boolean hasY8 = false;
+ boolean substituteY8 = false;
for (MandatoryStreamInformation streamInfo : streamsInfo) {
if (streamInfo.getFormat() == ImageFormat.YUV_420_888) {
- hasY8 = true;
- break;
+ substituteY8 = true;
}
}
- if (hasY8) {
- testMandatoryReprocessableStreamCombination(cameraId, combination, hasY8);
+ if (substituteY8) {
+ testMandatoryReprocessableStreamCombination(cameraId, combination,
+ /*substituteY8*/true, /*substituteHeic*/false);
+ }
+ }
+
+ if (mStaticInfo.isHeicSupported()) {
+ List<MandatoryStreamInformation> streamsInfo = combination.getStreamsInformation();
+ boolean substituteHeic = false;
+ for (MandatoryStreamInformation streamInfo : streamsInfo) {
+ if (streamInfo.getFormat() == ImageFormat.JPEG) {
+ substituteHeic = true;
+ }
+ }
+ if (substituteHeic) {
+ testMandatoryReprocessableStreamCombination(cameraId, combination,
+ /*substituteY8*/false, /*substituteHeic*/true);
}
}
}
private void testMandatoryReprocessableStreamCombination(String cameraId,
- MandatoryStreamCombination combination, boolean substituteY8) {
+ MandatoryStreamCombination combination, boolean substituteY8,
+ boolean substituteHeic) {
final int TIMEOUT_FOR_RESULT_MS = 3000;
final int NUM_REPROCESS_CAPTURES_PER_CONFIG = 3;
@@ -664,6 +727,7 @@
List<ImageReader> yuvTargets = new ArrayList<>();
List<ImageReader> y8Targets = new ArrayList<>();
List<ImageReader> rawTargets = new ArrayList<>();
+ List<ImageReader> heicTargets = new ArrayList<>();
ArrayList<Surface> outputSurfaces = new ArrayList<>();
List<OutputConfiguration> outputConfigs = new ArrayList<OutputConfiguration>();
ImageReader inputReader = null;
@@ -685,13 +749,17 @@
inputFormat = ImageFormat.Y8;
}
+ Log.i(TAG, "testMandatoryReprocessableStreamCombination: " +
+ combination.getDescription() + ", substituteY8 = " + substituteY8 +
+ ", substituteHeic = " + substituteHeic);
try {
// The second stream information entry is the ZSL stream, which is configured
// separately.
setupConfigurationTargets(streamInfo.subList(2, streamInfo.size()), privTargets,
- jpegTargets, yuvTargets, y8Targets, rawTargets, outputConfigs,
- NUM_REPROCESS_CAPTURES_PER_CONFIG, substituteY8, null /*overrideStreamInfo*/,
- null /*overridePhysicalCameraIds*/, null /* overridePhysicalCameraSizes) */);
+ jpegTargets, yuvTargets, y8Targets, rawTargets, heicTargets, outputConfigs,
+ NUM_REPROCESS_CAPTURES_PER_CONFIG, substituteY8, substituteHeic,
+ null /*overrideStreamInfo*/, null /*overridePhysicalCameraIds*/,
+ null /* overridePhysicalCameraSizes) */);
outputSurfaces.ensureCapacity(outputConfigs.size());
for (OutputConfiguration config : outputConfigs) {
@@ -709,7 +777,8 @@
final boolean useY8 = inputIsY8 || y8Targets.size() > 0;
final int totalNumReprocessCaptures = NUM_REPROCESS_CAPTURES_PER_CONFIG * (
((inputIsYuv || inputIsY8) ? 1 : 0) +
- jpegTargets.size() + (useYuv ? yuvTargets.size() : y8Targets.size()));
+ (substituteHeic ? heicTargets.size() : jpegTargets.size()) +
+ (useYuv ? yuvTargets.size() : y8Targets.size()));
// It needs 1 input buffer for each reprocess capture + the number of buffers
// that will be used as outputs.
@@ -750,6 +819,10 @@
reprocessOutputs.add(reader.getSurface());
}
+ for (ImageReader reader : heicTargets) {
+ reprocessOutputs.add(reader.getSurface());
+ }
+
for (ImageReader reader : yuvTargets) {
reprocessOutputs.add(reader.getSurface());
}
@@ -803,6 +876,10 @@
target.close();
}
+ for (ImageReader target : heicTargets) {
+ target.close();
+ }
+
if (inputReader != null) {
inputReader.close();
}
@@ -1916,6 +1993,7 @@
static final int YUV = ImageFormat.YUV_420_888;
static final int RAW = ImageFormat.RAW_SENSOR;
static final int Y8 = ImageFormat.Y8;
+ static final int HEIC = ImageFormat.HEIC;
// Max resolution indices
static final int PREVIEW = 0;
@@ -1933,6 +2011,7 @@
StaticMetadata.StreamDirection.Output);
Size[] jpegSizes = sm.getJpegOutputSizesChecked();
Size[] rawSizes = sm.getRawOutputSizesChecked();
+ Size[] heicSizes = sm.getHeicOutputSizesChecked();
Size maxPreviewSize = getMaxPreviewSize(context, cameraId);
@@ -1975,6 +2054,13 @@
maxY8Sizes[MAXIMUM] = CameraTestUtils.getMaxSize(y8Sizes);
maxY8Sizes[VGA] = vgaSize;
}
+
+ if (sm.isHeicSupported()) {
+ maxHeicSizes[PREVIEW] = getMaxSize(heicSizes, maxPreviewSize);
+ maxHeicSizes[RECORD] = getMaxRecordingSize(cameraId);
+ maxHeicSizes[MAXIMUM] = CameraTestUtils.getMaxSize(heicSizes);
+ maxHeicSizes[VGA] = vgaSize;
+ }
}
Size[] privInputSizes = configs.getInputSizes(ImageFormat.PRIVATE);
@@ -1992,6 +2078,7 @@
public final Size[] maxJpegSizes = new Size[RESOLUTION_COUNT];
public final Size[] maxYuvSizes = new Size[RESOLUTION_COUNT];
public final Size[] maxY8Sizes = new Size[RESOLUTION_COUNT];
+ public final Size[] maxHeicSizes = new Size[RESOLUTION_COUNT];
public final Size maxRawSize;
// TODO: support non maximum reprocess input.
public final Size maxInputPrivSize;
@@ -2119,9 +2206,10 @@
List<ImageReader> yuvTargets = new ArrayList<ImageReader>();
List<ImageReader> y8Targets = new ArrayList<ImageReader>();
List<ImageReader> rawTargets = new ArrayList<ImageReader>();
+ List<ImageReader> heicTargets = new ArrayList<ImageReader>();
setupConfigurationTargets(config, maxSizes, privTargets, jpegTargets, yuvTargets,
- y8Targets, rawTargets, outputConfigs, MIN_RESULT_COUNT, i,
+ y8Targets, rawTargets, heicTargets, outputConfigs, MIN_RESULT_COUNT, i,
physicalCamerasForSize, physicalCameraSizes);
boolean haveSession = false;
@@ -2196,7 +2284,8 @@
private void setupConfigurationTargets(int[] configs, MaxStreamSizes maxSizes,
List<SurfaceTexture> privTargets, List<ImageReader> jpegTargets,
List<ImageReader> yuvTargets, List<ImageReader> y8Targets,
- List<ImageReader> rawTargets, List<OutputConfiguration> outputConfigs, int numBuffers,
+ List<ImageReader> rawTargets, List<ImageReader> heicTargets,
+ List<OutputConfiguration> outputConfigs, int numBuffers,
int overrideStreamIndex, List<String> overridePhysicalCameraIds,
List<Size> overridePhysicalCameraSizes) {
@@ -2241,6 +2330,20 @@
jpegTargets.add(target);
break;
}
+ case HEIC: {
+ Size targetSize = (numConfigs == 1) ? maxSizes.maxHeicSizes[sizeLimit] :
+ overridePhysicalCameraSizes.get(j);
+ ImageReader target = ImageReader.newInstance(
+ targetSize.getWidth(), targetSize.getHeight(), HEIC, numBuffers);
+ target.setOnImageAvailableListener(imageDropperListener, mHandler);
+ OutputConfiguration config = new OutputConfiguration(target.getSurface());
+ if (numConfigs > 1) {
+ config.setPhysicalCameraId(overridePhysicalCameraIds.get(j));
+ }
+ outputConfigs.add(config);
+ heicTargets.add(target);
+ break;
+ }
case YUV: {
Size targetSize = (numConfigs == 1) ? maxSizes.maxYuvSizes[sizeLimit] :
overridePhysicalCameraSizes.get(j);
diff --git a/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java b/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
index a169fee..22e2424 100644
--- a/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
@@ -100,7 +100,46 @@
continue;
}
openDevice(mCameraIds[i]);
- jpegExifTestByCamera();
+ Size maxJpegSize = mOrderedStillSizes.get(0);
+ stillExifTestByCamera(ImageFormat.JPEG, maxJpegSize);
+ } finally {
+ closeDevice();
+ closeImageReader();
+ }
+ }
+ }
+
+ /**
+ * Test HEIC capture exif fields for each camera.
+ */
+ @Test
+ public void testHeicExif() throws Exception {
+ for (int i = 0; i < mCameraIds.length; i++) {
+ try {
+ Log.i(TAG, "Testing HEIC exif for Camera " + mCameraIds[i]);
+ if (!mAllStaticInfo.get(mCameraIds[i]).isColorOutputSupported()) {
+ Log.i(TAG, "Camera " + mCameraIds[i] +
+ " does not support color outputs, skipping");
+ continue;
+ }
+ if (!mAllStaticInfo.get(mCameraIds[i]).isHeicSupported()) {
+ Log.i(TAG, "Camera " + mCameraIds[i] +
+ " does not support HEIC, skipping");
+ continue;
+ }
+
+ openDevice(mCameraIds[i]);
+
+ // Test maximum Heic size capture
+ List<Size> orderedHeicSizes = CameraTestUtils.getSupportedHeicSizes(
+ mCameraIds[i], mCameraManager, null/*bound*/);
+ Size maxHeicSize = orderedHeicSizes.get(0);
+ stillExifTestByCamera(ImageFormat.HEIC, maxHeicSize);
+
+ // Test preview size Heic capture
+ Size previewSize = mOrderedPreviewSizes.get(0);
+ stillExifTestByCamera(ImageFormat.HEIC, previewSize);
+
} finally {
closeDevice();
closeImageReader();
@@ -318,7 +357,7 @@
* Test all combination of available preview sizes and still sizes.
* <p>
* For each still capture, Only the jpeg buffer is validated, capture
- * result validation is covered by {@link #jpegExifTestByCamera} test.
+ * result validation is covered by {@link #stillExifTestByCamera} test.
* </p>
*/
@Test(timeout=60*60*1000) // timeout = 60 mins for long running tests
@@ -585,7 +624,7 @@
// Set the max number of images to number of focal lengths supported
prepareStillCaptureAndStartPreview(previewRequest, stillRequest, maxPreviewSz,
- maxStillSz, resultListener, focalLengths.length, imageListener);
+ maxStillSz, resultListener, focalLengths.length, imageListener, false /*isHeic*/);
for(float focalLength : focalLengths) {
@@ -613,7 +652,7 @@
validateJpegCapture(image, maxStillSz);
verifyJpegKeys(image, result, maxStillSz, thumbnailSize, exifTestData,
- mStaticInfo, mCollector, mDebugFileNameBase);
+ mStaticInfo, mCollector, mDebugFileNameBase, ImageFormat.JPEG);
}
}
@@ -633,7 +672,7 @@
CaptureRequest.Builder stillRequest =
mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
prepareStillCaptureAndStartPreview(previewRequest, stillRequest, maxPreviewSz,
- maxStillSz, resultListener, imageListener);
+ maxStillSz, resultListener, imageListener, false /*isHeic*/);
// make sure preview is actually running
waitForNumResults(resultListener, NUM_FRAMES_WAITED);
@@ -719,7 +758,7 @@
stillRequest = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
}
prepareStillCaptureAndStartPreview(previewRequest, stillRequest, maxPreviewSz,
- maxStillSz, resultListener, imageListener);
+ maxStillSz, resultListener, imageListener, false /*isHeic*/);
// Set AE mode to ON_AUTO_FLASH if flash is available.
if (mStaticInfo.hasFlash()) {
@@ -930,7 +969,7 @@
CaptureRequest.Builder stillRequest =
mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
prepareStillCaptureAndStartPreview(previewRequest, stillRequest, previewSz,
- stillSz, resultListener, imageListener);
+ stillSz, resultListener, imageListener, false /*isHeic*/);
mSession.capture(stillRequest.build(), resultListener, mHandler);
Image image = imageListener.getImage((mStaticInfo.isHardwareLevelLegacy()) ?
RELAXED_CAPTURE_IMAGE_TIMEOUT_MS : CAPTURE_IMAGE_TIMEOUT_MS);
@@ -1049,7 +1088,7 @@
CaptureResult result = resultListener.getCaptureResultForRequest(multiRequest,
NUM_RESULTS_WAIT_TIMEOUT);
Image jpegImage = jpegListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
- basicValidateJpegImage(jpegImage, maxStillSz);
+ basicValidateBlobImage(jpegImage, maxStillSz, ImageFormat.JPEG);
Image rawImage = rawListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
validateRaw16Image(rawImage, size);
verifyRawCaptureResult(multiRequest, result);
@@ -1188,17 +1227,19 @@
}
/**
- * Issue a Jpeg capture and validate the exif information.
+ * Issue a still capture and validate the exif information.
* <p>
* TODO: Differentiate full and limited device, some of the checks rely on
* per frame control and synchronization, most of them don't.
* </p>
*/
- private void jpegExifTestByCamera() throws Exception {
+ private void stillExifTestByCamera(int format, Size stillSize) throws Exception {
+ assertTrue(format == ImageFormat.JPEG || format == ImageFormat.HEIC);
+ boolean isHeic = (format == ImageFormat.HEIC);
+
Size maxPreviewSz = mOrderedPreviewSizes.get(0);
- Size maxStillSz = mOrderedStillSizes.get(0);
if (VERBOSE) {
- Log.v(TAG, "Testing JPEG exif with jpeg size " + maxStillSz.toString()
+ Log.v(TAG, "Testing exif with size " + stillSize.toString()
+ ", preview size " + maxPreviewSz);
}
@@ -1209,8 +1250,8 @@
mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
SimpleImageReaderListener imageListener = new SimpleImageReaderListener();
- prepareStillCaptureAndStartPreview(previewBuilder, stillBuilder, maxPreviewSz, maxStillSz,
- resultListener, imageListener);
+ prepareStillCaptureAndStartPreview(previewBuilder, stillBuilder, maxPreviewSz, stillSize,
+ resultListener, imageListener, isHeic);
// Set the jpeg keys, then issue a capture
Size[] thumbnailSizes = mStaticInfo.getAvailableThumbnailSizesChecked();
@@ -1223,15 +1264,15 @@
for (int i = 0; i < EXIF_TEST_DATA.length; i++) {
setJpegKeys(stillBuilder, EXIF_TEST_DATA[i], testThumbnailSizes[i], mCollector);
- // Capture a jpeg image.
+ // Capture a jpeg/heic image.
CaptureRequest request = stillBuilder.build();
mSession.capture(request, resultListener, mHandler);
CaptureResult stillResult =
resultListener.getCaptureResultForRequest(request, NUM_RESULTS_WAIT_TIMEOUT);
Image image = imageListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
- verifyJpegKeys(image, stillResult, maxStillSz, testThumbnailSizes[i], EXIF_TEST_DATA[i],
- mStaticInfo, mCollector, mDebugFileNameBase);
+ verifyJpegKeys(image, stillResult, stillSize, testThumbnailSizes[i], EXIF_TEST_DATA[i],
+ mStaticInfo, mCollector, mDebugFileNameBase, format);
// Free image resources
image.close();
@@ -1292,7 +1333,7 @@
// Set the max number of images to be same as the burst count, as the verification
// could be much slower than producing rate, and we don't want to starve producer.
prepareStillCaptureAndStartPreview(previewRequest, stillRequest, maxPreviewSz,
- maxStillSz, resultListener, numSteps, imageListener);
+ maxStillSz, resultListener, numSteps, imageListener, false /*isHeic*/);
for (int i = 0; i <= numSteps; i++) {
int exposureCompensation = i * stepsPerEv + compensationRange.getLower();
diff --git a/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java b/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
index 8c245bd..7a9ae93 100644
--- a/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
+++ b/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
@@ -285,9 +285,10 @@
protected void prepareStillCaptureAndStartPreview(CaptureRequest.Builder previewRequest,
CaptureRequest.Builder stillRequest, Size previewSz, Size stillSz,
CaptureCallback resultListener,
- ImageReader.OnImageAvailableListener imageListener) throws Exception {
+ ImageReader.OnImageAvailableListener imageListener, boolean isHeic) throws Exception {
prepareCaptureAndStartPreview(previewRequest, stillRequest, previewSz, stillSz,
- ImageFormat.JPEG, resultListener, MAX_READER_IMAGES, imageListener);
+ isHeic ? ImageFormat.HEIC : ImageFormat.JPEG, resultListener, MAX_READER_IMAGES,
+ imageListener);
}
/**
@@ -304,9 +305,9 @@
protected void prepareStillCaptureAndStartPreview(CaptureRequest.Builder previewRequest,
CaptureRequest.Builder stillRequest, Size previewSz, Size stillSz,
CaptureCallback resultListener, int maxNumImages,
- ImageReader.OnImageAvailableListener imageListener) throws Exception {
+ ImageReader.OnImageAvailableListener imageListener, boolean isHeic) throws Exception {
prepareCaptureAndStartPreview(previewRequest, stillRequest, previewSz, stillSz,
- ImageFormat.JPEG, resultListener, maxNumImages, imageListener);
+ isHeic ? ImageFormat.HEIC : ImageFormat.JPEG, resultListener, maxNumImages, imageListener);
}
/**
@@ -573,11 +574,13 @@
* @param resultListener Capture result listener
* @param maxNumImages The max number of images set to the image reader
* @param imageListeners The single capture capture image listeners
+ * @param isHeic HEIC still capture if true, JPEG still capture if false
*/
protected ImageReader[] prepareStillCaptureAndStartPreview(
CaptureRequest.Builder previewRequest, CaptureRequest.Builder stillRequest,
Size previewSz, Size[] captureSizes, int[] formats, CaptureCallback resultListener,
- int maxNumImages, ImageReader.OnImageAvailableListener[] imageListeners)
+ int maxNumImages, ImageReader.OnImageAvailableListener[] imageListeners,
+ boolean isHeic)
throws Exception {
if ((captureSizes == null) || (formats == null) || (imageListeners == null) &&
diff --git a/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java b/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
index 4fd4b39..883d86b 100644
--- a/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
+++ b/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
@@ -1035,11 +1035,12 @@
ByteBuffer buffer = null;
// JPEG doesn't have pixelstride and rowstride, treat it as 1D buffer.
- // Same goes for DEPTH_POINT_CLOUD and DEPTH_JPEG
+ // Same goes for DEPTH_POINT_CLOUD, RAW_PRIVATE, DEPTH_JPEG, and HEIC
if (format == ImageFormat.JPEG || format == ImageFormat.DEPTH_POINT_CLOUD ||
- format == ImageFormat.RAW_PRIVATE || format == ImageFormat.DEPTH_JPEG) {
+ format == ImageFormat.RAW_PRIVATE || format == ImageFormat.DEPTH_JPEG ||
+ format == ImageFormat.HEIC) {
buffer = planes[0].getBuffer();
- assertNotNull("Fail to get jpeg or depth ByteBuffer", buffer);
+ assertNotNull("Fail to get jpeg/depth/heic ByteBuffer", buffer);
data = new byte[buffer.remaining()];
buffer.get(data);
buffer.rewind();
@@ -1122,6 +1123,7 @@
case ImageFormat.DEPTH_POINT_CLOUD:
case ImageFormat.DEPTH_JPEG:
case ImageFormat.Y8:
+ case ImageFormat.HEIC:
assertEquals("JPEG/RAW/depth/Y8 Images should have one plane", 1, planes.length);
break;
default:
@@ -1364,6 +1366,11 @@
return getSortedSizesForFormat(cameraId, cameraManager, ImageFormat.JPEG, bound);
}
+ static public List<Size> getSupportedHeicSizes(String cameraId,
+ CameraManager cameraManager, Size bound) throws CameraAccessException {
+ return getSortedSizesForFormat(cameraId, cameraManager, ImageFormat.HEIC, bound);
+ }
+
static public Size getMinPreviewSize(String cameraId, CameraManager cameraManager)
throws CameraAccessException {
List<Size> sizes = getSupportedPreviewSizes(cameraId, cameraManager, null);
@@ -1551,6 +1558,9 @@
case ImageFormat.Y8:
validateY8Data(data, width, height, format, image.getTimestamp(), filePath);
break;
+ case ImageFormat.HEIC:
+ validateHeicData(data, width, height, filePath);
+ break;
default:
throw new UnsupportedOperationException("Unsupported format for validation: "
+ format);
@@ -1733,6 +1743,26 @@
}
+ private static void validateHeicData(byte[] heicData, int width, int height, String filePath) {
+ BitmapFactory.Options bmpOptions = new BitmapFactory.Options();
+ // DecodeBound mode: only parse the frame header to get width/height.
+ // it doesn't decode the pixel.
+ bmpOptions.inJustDecodeBounds = true;
+ BitmapFactory.decodeByteArray(heicData, 0, heicData.length, bmpOptions);
+ assertEquals(width, bmpOptions.outWidth);
+ assertEquals(height, bmpOptions.outHeight);
+
+ // Pixel decoding mode: decode whole image. check if the image data
+ // is decodable here.
+ assertNotNull("Decoding heic failed",
+ BitmapFactory.decodeByteArray(heicData, 0, heicData.length));
+ if (DEBUG && filePath != null) {
+ String fileName =
+ filePath + "/" + width + "x" + height + ".heic";
+ dumpFile(fileName, heicData);
+ }
+ }
+
public static <T> T getValueNotNull(CaptureResult result, CaptureResult.Key<T> key) {
if (result == null) {
throw new IllegalArgumentException("Result must not be null");
@@ -2047,49 +2077,54 @@
* continue the test if the jpeg image captured has some serious failures.
* </p>
*
- * @param image The captured jpeg image
- * @param expectedSize Expected capture jpeg size
+ * @param image The captured JPEG/HEIC image
+ * @param expectedSize Expected capture JEPG/HEIC size
+ * @param format JPEG/HEIC image format
*/
- public static void basicValidateJpegImage(Image image, Size expectedSize) {
+ public static void basicValidateBlobImage(Image image, Size expectedSize, int format) {
Size imageSz = new Size(image.getWidth(), image.getHeight());
assertTrue(
String.format("Image size doesn't match (expected %s, actual %s) ",
expectedSize.toString(), imageSz.toString()), expectedSize.equals(imageSz));
- assertEquals("Image format should be JPEG", ImageFormat.JPEG, image.getFormat());
+ assertEquals("Image format should be " + ((format == ImageFormat.HEIC) ? "HEIC" : "JPEG"),
+ format, image.getFormat());
assertNotNull("Image plane shouldn't be null", image.getPlanes());
assertEquals("Image plane number should be 1", 1, image.getPlanes().length);
- // Jpeg decoding validate was done in ImageReaderTest, no need to duplicate the test here.
+ // Jpeg/Heic decoding validate was done in ImageReaderTest,
+ // no need to duplicate the test here.
}
/**
- * Verify the JPEG EXIF and JPEG related keys in a capture result are expected.
+ * Verify the EXIF and JPEG related keys in a capture result are expected.
* - Capture request get values are same as were set.
* - capture result's exif data is the same as was set by
* the capture request.
* - new tags in the result set by the camera service are
* present and semantically correct.
*
- * @param image The output JPEG image to verify.
+ * @param image The output JPEG/HEIC image to verify.
* @param captureResult The capture result to verify.
- * @param expectedSize The expected JPEG size.
+ * @param expectedSize The expected JPEG/HEIC size.
* @param expectedThumbnailSize The expected thumbnail size.
* @param expectedExifData The expected EXIF data
* @param staticInfo The static metadata for the camera device.
- * @param jpegFilename The filename to dump the jpeg to.
+ * @param blobFilename The filename to dump the jpeg/heic to.
* @param collector The camera error collector to collect errors.
+ * @param format JPEG/HEIC format
*/
public static void verifyJpegKeys(Image image, CaptureResult captureResult, Size expectedSize,
Size expectedThumbnailSize, ExifTestData expectedExifData, StaticMetadata staticInfo,
- CameraErrorCollector collector, String debugFileNameBase) throws Exception {
+ CameraErrorCollector collector, String debugFileNameBase, int format) throws Exception {
- basicValidateJpegImage(image, expectedSize);
+ basicValidateBlobImage(image, expectedSize, format);
- byte[] jpegBuffer = getDataFromImage(image);
+ byte[] blobBuffer = getDataFromImage(image);
// Have to dump into a file to be able to use ExifInterface
- String jpegFilename = debugFileNameBase + "/verifyJpegKeys.jpeg";
- dumpFile(jpegFilename, jpegBuffer);
- ExifInterface exif = new ExifInterface(jpegFilename);
+ String filePostfix = (format == ImageFormat.HEIC ? ".heic" : ".jpeg");
+ String blobFilename = debugFileNameBase + "/verifyJpegKeys" + filePostfix;
+ dumpFile(blobFilename, blobBuffer);
+ ExifInterface exif = new ExifInterface(blobFilename);
if (expectedThumbnailSize.equals(new Size(0,0))) {
collector.expectTrue("Jpeg shouldn't have thumbnail when thumbnail size is (0, 0)",
diff --git a/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java b/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
index 15701f1..6af6be5 100644
--- a/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
+++ b/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
@@ -1347,6 +1347,16 @@
}
/**
+ * Get supported heic output sizes and do the check.
+ *
+ * @return Empty size array if heic output is not supported
+ */
+ public Size[] getHeicOutputSizesChecked() {
+ return getAvailableSizesForFormatChecked(ImageFormat.HEIC,
+ StreamDirection.Output);
+ }
+
+ /**
* Used to determine the stream direction for various helpers that look up
* format or size information.
*/
@@ -2361,6 +2371,14 @@
}
/**
+ * Check if HEIC format is supported
+ */
+ public boolean isHeicSupported() {
+ int[] formats = getAvailableFormats(StaticMetadata.StreamDirection.Output);
+ return CameraTestUtils.contains(formats, ImageFormat.HEIC);
+ }
+
+ /**
* Check if the dynamic black level is supported.
*
* <p>
diff --git a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/ChildlessActivityTest.java b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/ChildlessActivityTest.java
index 8dbda23..a58eefc 100644
--- a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/ChildlessActivityTest.java
+++ b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/ChildlessActivityTest.java
@@ -60,7 +60,6 @@
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import java.util.Arrays;
@@ -108,7 +107,6 @@
activity.assertDefaultEvents(session);
}
- @Ignore("not implemented yet, pending on b/123658889")
@Test
public void testGetContentCapture_disabledWhenNoService() throws Exception {
diff --git a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/Helper.java b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/Helper.java
index 30ba124..3cd2354 100644
--- a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/Helper.java
+++ b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/Helper.java
@@ -20,6 +20,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.os.SystemClock;
+import android.support.test.InstrumentationRegistry;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
@@ -33,7 +34,7 @@
/**
* Helper for common funcionalities.
*/
-final class Helper {
+public final class Helper {
public static final String TAG = "ContentCaptureTest";
@@ -43,6 +44,8 @@
public static final long MY_EPOCH = SystemClock.uptimeMillis();
+ public static final Context sContext = InstrumentationRegistry.getTargetContext();
+
/**
* Awaits for a latch to be counted down.
*/
diff --git a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/ContentCaptureContextTest.java b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/unit/ContentCaptureContextTest.java
similarity index 98%
rename from tests/contentcaptureservice/src/android/contentcaptureservice/cts/ContentCaptureContextTest.java
rename to tests/contentcaptureservice/src/android/contentcaptureservice/cts/unit/ContentCaptureContextTest.java
index c19f0f7..ed1ffce 100644
--- a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/ContentCaptureContextTest.java
+++ b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/unit/ContentCaptureContextTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.contentcaptureservice.cts;
+package android.contentcaptureservice.cts.unit;
import static com.google.common.truth.Truth.assertThat;
@@ -34,8 +34,8 @@
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+@AppModeFull(reason = "unit test")
@RunWith(JUnit4.class)
-@AppModeFull // Unit test
public class ContentCaptureContextTest {
private static final Uri URI = Uri.parse("file:/dev/null");
diff --git a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/unit/UserDataRemovalRequestTest.java b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/unit/UserDataRemovalRequestTest.java
new file mode 100644
index 0000000..93a15ec
--- /dev/null
+++ b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/unit/UserDataRemovalRequestTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2019 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.contentcaptureservice.cts.unit;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.assertThrows;
+
+import android.net.Uri;
+import android.platform.test.annotations.AppModeFull;
+import android.view.contentcapture.UserDataRemovalRequest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+@AppModeFull(reason = "unit test")
+@RunWith(MockitoJUnitRunner.class)
+public class UserDataRemovalRequestTest {
+
+ @Mock
+ private final Uri mUri = Uri.parse("content://com.example/");
+
+ private UserDataRemovalRequest.Builder mBuilder = new UserDataRemovalRequest.Builder();
+
+ @Test
+ public void testBuilder_addUri_invalid() {
+ assertThrows(NullPointerException.class, () -> mBuilder.addUri(null, false));
+ }
+
+ @Test
+ public void testBuilder_addUri_valid() {
+ assertThat(mBuilder.addUri(mUri, false)).isNotNull();
+ assertThat(mBuilder.addUri(Uri.parse("content://com.example2"), true)).isNotNull();
+ }
+
+ @Test
+ public void testBuilder_addUriAfterForEverything() {
+ assertThat(mBuilder.forEverything()).isNotNull();
+ assertThrows(IllegalStateException.class, () -> mBuilder.addUri(mUri, false));
+ }
+
+ @Test
+ public void testBuilder_forEverythingAfterAddingUri() {
+ assertThat(mBuilder.addUri(mUri, false)).isNotNull();
+ assertThrows(IllegalStateException.class, () -> mBuilder.forEverything());
+ }
+
+ @Test
+ public void testBuild_invalid() {
+ assertThrows(IllegalStateException.class, () -> mBuilder.build());
+ }
+
+ @Test
+ public void testBuild_valid() {
+ assertThat(new UserDataRemovalRequest.Builder().forEverything().build())
+ .isNotNull();
+ assertThat(new UserDataRemovalRequest.Builder().addUri(mUri, false).build())
+ .isNotNull();
+ }
+
+ @Test
+ public void testNoMoreInteractionsAfterBuild() {
+ assertThat(mBuilder.forEverything().build()).isNotNull();
+
+ assertThrows(IllegalStateException.class, () -> mBuilder.addUri(mUri, false));
+ assertThrows(IllegalStateException.class, () -> mBuilder.forEverything());
+ assertThrows(IllegalStateException.class, () -> mBuilder.build());
+
+ }
+}
diff --git a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/unit/ViewNodeTest.java b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/unit/ViewNodeTest.java
new file mode 100644
index 0000000..8d9cdeb
--- /dev/null
+++ b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/unit/ViewNodeTest.java
@@ -0,0 +1,415 @@
+/*
+ * Copyright (C) 2019 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.contentcaptureservice.cts.unit;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.assertThrows;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.os.LocaleList;
+import android.os.Parcel;
+import android.platform.test.annotations.AppModeFull;
+import android.support.test.InstrumentationRegistry;
+import android.view.View;
+import android.view.ViewStructure.HtmlInfo;
+import android.view.autofill.AutofillId;
+import android.view.autofill.AutofillValue;
+import android.view.contentcapture.ViewNode;
+import android.view.contentcapture.ViewNode.ViewStructureImpl;
+import android.widget.FrameLayout;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.util.Locale;
+
+@AppModeFull(reason = "unit test")
+@RunWith(MockitoJUnitRunner.class)
+public class ViewNodeTest {
+
+ private final Context mContext = InstrumentationRegistry.getTargetContext();
+
+ @Mock
+ private HtmlInfo mHtmlInfoMock;
+
+ @Test
+ public void testAutofillIdMethods_orphanView() {
+ View view = new View(mContext);
+ AutofillId initialId = new AutofillId(42);
+ view.setAutofillId(initialId);
+
+ ViewStructureImpl structure = new ViewStructureImpl(view);
+ ViewNode node = structure.getNode();
+
+ assertThat(node.getAutofillId()).isEqualTo(initialId);
+ assertThat(node.getParentAutofillId()).isNull();
+
+ AutofillId newId = new AutofillId(108);
+ structure.setAutofillId(newId);
+ assertThat(node.getAutofillId()).isEqualTo(newId);
+ assertThat(node.getParentAutofillId()).isNull();
+
+ structure.setAutofillId(new AutofillId(66), 6);
+ assertThat(node.getAutofillId()).isEqualTo(new AutofillId(66, 6));
+ assertThat(node.getParentAutofillId()).isEqualTo(new AutofillId(66));
+ }
+
+ @Test
+ public void testAutofillIdMethods_parentedView() {
+ FrameLayout parent = new FrameLayout(mContext);
+ AutofillId initialParentId = new AutofillId(48);
+ parent.setAutofillId(initialParentId);
+
+ View child = new View(mContext);
+ AutofillId initialChildId = new AutofillId(42);
+ child.setAutofillId(initialChildId);
+
+ parent.addView(child);
+
+ ViewStructureImpl structure = new ViewStructureImpl(child);
+ ViewNode node = structure.getNode();
+
+ assertThat(node.getAutofillId()).isEqualTo(initialChildId);
+ assertThat(node.getParentAutofillId()).isEqualTo(initialParentId);
+
+ AutofillId newChildId = new AutofillId(108);
+ structure.setAutofillId(newChildId);
+ assertThat(node.getAutofillId()).isEqualTo(newChildId);
+ assertThat(node.getParentAutofillId()).isEqualTo(initialParentId);
+
+ AutofillId newParentId = new AutofillId(15162342);
+ parent.setAutofillId(newParentId);
+ assertThat(node.getAutofillId()).isEqualTo(newChildId);
+ assertThat(node.getParentAutofillId()).isEqualTo(initialParentId);
+
+ structure.setAutofillId(new AutofillId(66), 6);
+ assertThat(node.getAutofillId()).isEqualTo(new AutofillId(66, 6));
+ assertThat(node.getParentAutofillId()).isEqualTo(new AutofillId(66));
+ }
+
+ @Test
+ public void testAutofillIdMethods_explicitIdsConstructor() {
+ AutofillId initialParentId = new AutofillId(42);
+ ViewStructureImpl structure = new ViewStructureImpl(initialParentId, 108, 666);
+ ViewNode node = structure.getNode();
+
+ assertThat(node.getAutofillId()).isEqualTo(new AutofillId(initialParentId, 108, 666));
+ assertThat(node.getParentAutofillId()).isEqualTo(initialParentId);
+
+ AutofillId newChildId = new AutofillId(108);
+ structure.setAutofillId(newChildId);
+ assertThat(node.getAutofillId()).isEqualTo(newChildId);
+ assertThat(node.getParentAutofillId()).isEqualTo(initialParentId);
+
+ structure.setAutofillId(new AutofillId(66), 6);
+ assertThat(node.getAutofillId()).isEqualTo(new AutofillId(66, 6));
+ assertThat(node.getParentAutofillId()).isEqualTo(new AutofillId(66));
+ }
+
+ @Test
+ public void testInvalidSetters() {
+ View view = new View(mContext);
+ AutofillId initialId = new AutofillId(42);
+ view.setAutofillId(initialId);
+
+ ViewStructureImpl structure = new ViewStructureImpl(view);
+ ViewNode node = structure.getNode();
+ assertThat(node.getAutofillId()).isEqualTo(initialId); // sanity check
+
+ assertThrows(NullPointerException.class, () -> structure.setAutofillId(null));
+ assertThat(node.getAutofillId()).isEqualTo(initialId); // invariant
+
+ assertThrows(NullPointerException.class, () -> structure.setAutofillId(null, 666));
+ assertThat(node.getAutofillId()).isEqualTo(initialId); // invariant
+
+ assertThrows(NullPointerException.class, () -> structure.setTextIdEntry(null));
+ assertThat(node.getTextIdEntry()).isNull();
+ }
+
+ @Test
+ public void testValidProperties_directly() {
+ ViewStructureImpl structure = newSimpleStructure();
+ assertSimpleStructure(structure);
+ assertSimpleNode(structure.getNode());
+ }
+
+ @Test
+ public void testValidProperties_throughParcel() {
+ ViewStructureImpl structure = newSimpleStructure();
+ final ViewNode node = structure.getNode();
+ assertSimpleNode(node); // sanity check
+
+ final ViewNode clone = cloneThroughParcel(node);
+ assertSimpleNode(clone);
+ }
+
+ @Test
+ public void testComplexText_directly() {
+ ViewStructureImpl structure = newStructureWithComplexText();
+ assertStructureWithComplexText(structure);
+ assertNodeWithComplexText(structure.getNode());
+ }
+
+ @Test
+ public void testComplexText_throughParcel() {
+ ViewStructureImpl structure = newStructureWithComplexText();
+ final ViewNode node = structure.getNode();
+ assertNodeWithComplexText(node); // sanity check
+
+ ViewNode clone = cloneThroughParcel(node);
+ assertNodeWithComplexText(clone);
+ }
+
+ @Test
+ public void testVisibility() {
+ // Visibility is a special case becase it use flag masks, so we want to make sure it works
+ // fine
+ View view = new View(mContext);
+ ViewStructureImpl structure = new ViewStructureImpl(view);
+ ViewNode node = structure.getNode();
+
+ structure.setVisibility(View.VISIBLE);
+ assertThat(node.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(cloneThroughParcel(node).getVisibility()).isEqualTo(View.VISIBLE);
+
+ structure.setVisibility(View.GONE);
+ assertThat(node.getVisibility()).isEqualTo(View.GONE);
+ assertThat(cloneThroughParcel(node).getVisibility()).isEqualTo(View.GONE);
+
+ structure.setVisibility(View.VISIBLE);
+ assertThat(node.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(cloneThroughParcel(node).getVisibility()).isEqualTo(View.VISIBLE);
+
+ structure.setVisibility(View.INVISIBLE);
+ assertThat(node.getVisibility()).isEqualTo(View.INVISIBLE);
+ assertThat(cloneThroughParcel(node).getVisibility()).isEqualTo(View.INVISIBLE);
+
+ structure.setVisibility(View.INVISIBLE | View.GONE);
+ assertThat(node.getVisibility()).isEqualTo(View.INVISIBLE | View.GONE);
+ assertThat(cloneThroughParcel(node).getVisibility()).isEqualTo(View.INVISIBLE | View.GONE);
+
+
+ final int invalidValue = Math.max(Math.max(View.VISIBLE, View.INVISIBLE), View.GONE) * 2;
+ structure.setVisibility(View.VISIBLE);
+ structure.setVisibility(invalidValue); // should be ignored
+ assertThat(node.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(cloneThroughParcel(node).getVisibility()).isEqualTo(View.VISIBLE);
+
+ structure.setVisibility(View.GONE | invalidValue);
+ assertThat(node.getVisibility()).isEqualTo(View.GONE);
+ assertThat(cloneThroughParcel(node).getVisibility()).isEqualTo(View.GONE);
+ }
+
+ /**
+ * Creates a {@link ViewStructureImpl} that can be asserted through
+ * {@link #assertSimpleNode(ViewNode)}.
+ */
+ private ViewStructureImpl newSimpleStructure() {
+ View view = new View(mContext);
+ view.setAutofillId(new AutofillId(42));
+
+ ViewStructureImpl structure = new ViewStructureImpl(view);
+
+ // Basic properties
+ structure.setText("Text is set!");
+ structure.setClassName("Classy!");
+ structure.setContentDescription("Described I am!");
+ structure.setVisibility(View.INVISIBLE);
+
+ // Autofill properties
+ structure.setAutofillType(View.AUTOFILL_TYPE_TEXT);
+ structure.setAutofillHints(new String[] { "Auto", "Man" });
+ structure.setAutofillOptions(new String[] { "Maybe" });
+ structure.setAutofillValue(AutofillValue.forText("Malkovich"));
+
+ // Extra text properties
+ structure.setMinTextEms(6);
+ structure.setMaxTextLength(66);
+ structure.setMaxTextEms(666);
+ structure.setInputType(42);
+ structure.setTextIdEntry("TEXT, Y U NO ENTRY?");
+ structure.setLocaleList(new LocaleList(Locale.US, Locale.ENGLISH));
+
+ // Resource id
+ structure.setId(16, "package.name", "type.name", "entry.name");
+
+ // Dimensions
+ structure.setDimens(4, 8, 15, 16, 23, 42);
+
+ // Boolean properties
+ structure.setAssistBlocked(true);
+ structure.setEnabled(true);
+ structure.setClickable(true);
+ structure.setLongClickable(true);
+ structure.setContextClickable(true);
+ structure.setFocusable(true);
+ structure.setFocused(true);
+ structure.setAccessibilityFocused(true);
+ structure.setChecked(true);
+ structure.setActivated(true);
+ structure.setOpaque(true);
+
+ // Bundle
+ assertThat(structure.hasExtras()).isFalse();
+ final Bundle bundle = structure.getExtras();
+ assertThat(bundle).isNotNull();
+ bundle.putString("Marlon", "Bundle");
+ assertThat(structure.hasExtras()).isTrue();
+ return structure;
+ }
+
+ /**
+ * Asserts the properties of a {@link ViewNode} that was created by
+ * {@link #newSimpleStructure()}.
+ */
+ private void assertSimpleNode(ViewNode node) {
+
+ // Basic properties
+ assertThat(node.getAutofillId()).isEqualTo(new AutofillId(42));
+ assertThat(node.getParentAutofillId()).isNull();
+ assertThat(node.getText()).isEqualTo("Text is set!");
+ assertThat(node.getClassName()).isEqualTo("Classy!");
+ assertThat(node.getContentDescription().toString()).isEqualTo("Described I am!");
+ assertThat(node.getVisibility()).isEqualTo(View.INVISIBLE);
+
+ // Autofill properties
+ assertThat(node.getAutofillType()).isEqualTo(View.AUTOFILL_TYPE_TEXT);
+ assertThat(node.getAutofillHints()).asList().containsExactly("Auto", "Man").inOrder();
+ assertThat(node.getAutofillOptions()).asList().containsExactly("Maybe").inOrder();
+ assertThat(node.getAutofillValue().getTextValue()).isEqualTo("Malkovich");
+
+ // Extra text properties
+ assertThat(node.getMinTextEms()).isEqualTo(6);
+ assertThat(node.getMaxTextLength()).isEqualTo(66);
+ assertThat(node.getMaxTextEms()).isEqualTo(666);
+ assertThat(node.getInputType()).isEqualTo(42);
+ assertThat(node.getTextIdEntry()).isEqualTo("TEXT, Y U NO ENTRY?");
+ assertThat(node.getLocaleList()).isEqualTo(new LocaleList(Locale.US, Locale.ENGLISH));
+
+ // Resource id
+ assertThat(node.getId()).isEqualTo(16);
+ assertThat(node.getIdPackage()).isEqualTo("package.name");
+ assertThat(node.getIdType()).isEqualTo("type.name");
+ assertThat(node.getIdEntry()).isEqualTo("entry.name");
+
+ // Dimensions
+ assertThat(node.getLeft()).isEqualTo(4);
+ assertThat(node.getTop()).isEqualTo(8);
+ assertThat(node.getScrollX()).isEqualTo(15);
+ assertThat(node.getScrollY()).isEqualTo(16);
+ assertThat(node.getWidth()).isEqualTo(23);
+ assertThat(node.getHeight()).isEqualTo(42);
+
+ // Boolean properties
+ assertThat(node.isAssistBlocked()).isTrue();
+ assertThat(node.isEnabled()).isTrue();
+ assertThat(node.isClickable()).isTrue();
+ assertThat(node.isLongClickable()).isTrue();
+ assertThat(node.isContextClickable()).isTrue();
+ assertThat(node.isFocusable()).isTrue();
+ assertThat(node.isFocused()).isTrue();
+ assertThat(node.isAccessibilityFocused()).isTrue();
+ assertThat(node.isChecked()).isTrue();
+ assertThat(node.isActivated()).isTrue();
+ assertThat(node.isOpaque()).isTrue();
+
+ // Bundle
+ final Bundle bundle = node.getExtras();
+ assertThat(bundle).isNotNull();
+ assertThat(bundle.size()).isEqualTo(1);
+ assertThat(bundle.getString("Marlon")).isEqualTo("Bundle");
+ }
+
+ /**
+ * Asserts the properties of a {@link ViewStructureImpl} that was created by
+ * {@link #newSimpleStructure()}.
+ */
+ private void assertSimpleStructure(ViewStructureImpl structure) {
+ assertThat(structure.getAutofillId()).isEqualTo(new AutofillId(42));
+ assertThat(structure.getText()).isEqualTo("Text is set!");
+
+ // Bundle
+ final Bundle bundle = structure.getExtras();
+ assertThat(bundle.size()).isEqualTo(1);
+ assertThat(bundle.getString("Marlon")).isEqualTo("Bundle");
+ }
+
+ /**
+ * Creates a {@link ViewStructureImpl} with "complex" text properties (such as selection); it
+ * can be asserted through {@link #assertNodeWithComplexText(ViewNode)}.
+ */
+ private ViewStructureImpl newStructureWithComplexText() {
+ View view = new View(mContext);
+ ViewStructureImpl structure = new ViewStructureImpl(view);
+ structure.setText("IGNORE ME!");
+ structure.setText("Now we're talking!", 4, 8);
+ structure.setHint("Soylent Green is SPOILER ALERT");
+ structure.setTextStyle(15.0f, 16, 23, 42);
+ structure.setTextLines(new int[] {4, 8, 15} , new int[] {16, 23, 42});
+ return structure;
+ }
+
+ /**
+ * Asserts the properties of a {@link ViewNode} that was created by
+ * {@link #newStructureWithComplexText()}.
+ */
+ private void assertNodeWithComplexText(ViewNode node) {
+ assertThat(node.getText()).isEqualTo("Now we're talking!");
+ assertThat(node.getTextSelectionStart()).isEqualTo(4);
+ assertThat(node.getTextSelectionEnd()).isEqualTo(8);
+ assertThat(node.getHint()).isEqualTo("Soylent Green is SPOILER ALERT");
+ assertThat(node.getTextSize()).isWithin(1.0e-10f).of(15.0f);
+ assertThat(node.getTextColor()).isEqualTo(16);
+ assertThat(node.getTextBackgroundColor()).isEqualTo(23);
+ assertThat(node.getTextStyle()).isEqualTo(42);
+ assertThat(node.getTextLineCharOffsets()).asList().containsExactly(4, 8, 15).inOrder();
+ assertThat(node.getTextLineBaselines()).asList().containsExactly(16, 23, 42).inOrder();
+ }
+
+ /**
+ * Asserts the properties of a {@link ViewStructureImpl} that was created by
+ * {@link #newStructureWithComplexText()}.
+ */
+ private void assertStructureWithComplexText(ViewStructureImpl structure) {
+ assertThat(structure.getText()).isEqualTo("Now we're talking!");
+ assertThat(structure.getTextSelectionStart()).isEqualTo(4);
+ assertThat(structure.getTextSelectionEnd()).isEqualTo(8);
+ assertThat(structure.getHint()).isEqualTo("Soylent Green is SPOILER ALERT");
+ }
+
+ private ViewNode cloneThroughParcel(ViewNode node) {
+ Parcel parcel = Parcel.obtain();
+
+ try {
+ // Write to parcel
+ parcel.setDataPosition(0); // Sanity / paranoid check
+ ViewNode.writeToParcel(parcel, node, 0);
+
+ // Read from parcel
+ parcel.setDataPosition(0);
+ ViewNode clone = ViewNode.readFromParcel(parcel);
+ assertThat(clone).isNotNull();
+ return clone;
+ } finally {
+ parcel.recycle();
+ }
+ }
+}
diff --git a/tests/fragment/Android.bp b/tests/fragment/Android.bp
new file mode 100644
index 0000000..64a4486
--- /dev/null
+++ b/tests/fragment/Android.bp
@@ -0,0 +1,47 @@
+// Copyright (C) 2016 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.
+
+android_test {
+ name: "CtsFragmentTestCases",
+ defaults: ["cts_defaults"],
+
+ dex_preopt: {
+ enabled: false,
+ },
+
+ optimize: {
+ enabled: false,
+ },
+
+ static_libs: [
+ "android-support-test",
+ "mockito-target-minus-junit4",
+ "android-common",
+ "compatibility-device-util",
+ "ctstestrunner",
+ ],
+ libs: ["android.test.base.stubs"],
+
+ srcs: ["src/**/*.java"],
+
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ "cts_instant",
+ ],
+
+ sdk_version: "test_current",
+}
diff --git a/tests/fragment/Android.mk b/tests/fragment/Android.mk
deleted file mode 100644
index 94a4d91..0000000
--- a/tests/fragment/Android.mk
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsFragmentTestCases
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := tests
-
-# and when built explicitly put it in the data partition
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_STATIC_JAVA_LIBRARIES += \
- android-support-test \
- mockito-target-minus-junit4 \
- android-common \
- compatibility-device-util \
- ctstestrunner
-LOCAL_JAVA_LIBRARIES := android.test.base.stubs
-#LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util android-support-test
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_CTS_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/fragment/TEST_MAPPING b/tests/fragment/TEST_MAPPING
new file mode 100644
index 0000000..a5be057
--- /dev/null
+++ b/tests/fragment/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsFragmentTestCases"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/tests/fragment/sdk26/Android.bp b/tests/fragment/sdk26/Android.bp
new file mode 100644
index 0000000..303c3cd
--- /dev/null
+++ b/tests/fragment/sdk26/Android.bp
@@ -0,0 +1,36 @@
+// Copyright (C) 2016 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.
+
+android_test {
+ name: "CtsFragmentTestCasesSdk26",
+ defaults: ["cts_defaults"],
+
+ optimize: {
+ enabled: false,
+ },
+
+ static_libs: ["android-support-test"],
+
+ srcs: ["src/**/*.java"],
+
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "vts",
+ "general-tests",
+ "cts_instant",
+ ],
+
+ sdk_version: "26",
+}
diff --git a/tests/fragment/sdk26/Android.mk b/tests/fragment/sdk26/Android.mk
deleted file mode 100644
index 5947137..0000000
--- a/tests/fragment/sdk26/Android.mk
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := CtsFragmentTestCasesSdk26
-
-# don't include this package in any target
-LOCAL_MODULE_TAGS := tests
-
-# and when built explicitly put it in the data partition
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_STATIC_JAVA_LIBRARIES += android-support-test
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts vts general-tests cts_instant
-
-LOCAL_SDK_VERSION := 26
-
-include $(BUILD_CTS_PACKAGE)
diff --git a/tests/fragment/sdk26/TEST_MAPPING b/tests/fragment/sdk26/TEST_MAPPING
new file mode 100644
index 0000000..28bdfed
--- /dev/null
+++ b/tests/fragment/sdk26/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsFragmentTestCasesSdk26"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/tests/providerui/AndroidTest.xml b/tests/providerui/AndroidTest.xml
index 6a123f6..9ef1d6c 100644
--- a/tests/providerui/AndroidTest.xml
+++ b/tests/providerui/AndroidTest.xml
@@ -16,7 +16,9 @@
<configuration description="Config for CTS Provider UI test cases">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="framework" />
- <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+ <!-- Instant apps cannot access external storage -->
+ <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsProviderUiTestCases.apk" />
diff --git a/tests/tests/permission/AndroidManifest.xml b/tests/tests/permission/AndroidManifest.xml
index 928da95..5400c7d 100644
--- a/tests/tests/permission/AndroidManifest.xml
+++ b/tests/tests/permission/AndroidManifest.xml
@@ -32,33 +32,8 @@
android:permissionGroup="android.permission.cts.groupC"
android:description="@string/perm_c" />
- <!-- for android.permission.cts.PermissionUsage -->
- <permission android:name="android.permission.cts.D"
- android:usageInfoRequired="true" />
-
- <!-- for android.permission.cts.PermissionUsage and LocationAccessCheckTest -->
- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
- android:dataSentOffDevice="no"
- android:dataSharedWithThirdParty="no"
- android:dataUsedForMonetization="no"
- android:dataRetentionTime="notRetained" />
-
- <!-- for android.permission.cts.PermissionUsage -->
- <uses-permission android:name="android.permission.READ_PHONE_STATE"
- android:dataSentOffDevice="yes"
- android:dataSharedWithThirdParty="yes"
- android:dataUsedForMonetization="yes"
- android:dataRetentionTime="32" />
-
- <!-- for android.permission.cts.PermissionUsage -->
- <uses-permission android:name="android.permission.RECORD_AUDIO"
- android:dataSentOffDevice="userTriggered"
- android:dataSharedWithThirdParty="userTriggered"
- android:dataUsedForMonetization="userTriggered"
- android:dataRetentionTime="unlimited" />
-
- <!-- for android.permission.cts.PermissionUsage -->
- <uses-permission android:name="android.permission.READ_CALENDAR" />
+ <!-- for android.permission.cts.LocationAccessCheckTest -->
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- for android.permission.cts.PermissionGroupChange -->
<permission-group android:description="@string/perm_group_b"
diff --git a/tests/tests/permission/src/android/permission/cts/PermissionUsageTest.java b/tests/tests/permission/src/android/permission/cts/PermissionUsageTest.java
deleted file mode 100644
index 39c66a6..0000000
--- a/tests/tests/permission/src/android/permission/cts/PermissionUsageTest.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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.permission.cts;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.Manifest;
-import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PermissionInfo;
-import android.content.pm.UsesPermissionInfo;
-import android.test.InstrumentationTestCase;
-
-import org.junit.Before;
-
-public final class PermissionUsageTest extends InstrumentationTestCase {
- private PackageManager mPm;
- private Context mContext;
-
- @Override
- @Before
- public void setUp() throws Exception {
- mContext = getInstrumentation().getTargetContext();
- mPm = mContext.getPackageManager();
- assertNotNull(mPm);
- }
-
- private UsesPermissionInfo getUsesPermissionInfo(String permission) throws Exception {
- PackageInfo info = mPm.getPackageInfo(mContext.getPackageName(),
- PackageManager.GET_PERMISSIONS);
- assertNotNull(info);
- assertNotNull(info.usesPermissions);
- for (UsesPermissionInfo upi : info.usesPermissions) {
- if (permission.equals(upi.getPermission())) {
- return upi;
- }
- }
- return null;
- }
-
- public void testBasic() throws Exception {
- UsesPermissionInfo upi = getUsesPermissionInfo(Manifest.permission.ACCESS_FINE_LOCATION);
- assertEquals(UsesPermissionInfo.USAGE_NO, upi.getDataSentOffDevice());
- assertEquals(UsesPermissionInfo.USAGE_NO, upi.getDataSharedWithThirdParty());
- assertEquals(UsesPermissionInfo.USAGE_NO, upi.getDataUsedForMonetization());
- assertEquals(UsesPermissionInfo.RETENTION_NOT_RETAINED, upi.getDataRetention());
- }
-
- public void testRetentionWeeks() throws Exception {
- UsesPermissionInfo upi
- = getUsesPermissionInfo(Manifest.permission.READ_PHONE_STATE);
- assertEquals(UsesPermissionInfo.USAGE_YES, upi.getDataSentOffDevice());
- assertEquals(UsesPermissionInfo.USAGE_YES, upi.getDataSharedWithThirdParty());
- assertEquals(UsesPermissionInfo.USAGE_YES, upi.getDataUsedForMonetization());
- assertEquals(UsesPermissionInfo.RETENTION_SPECIFIED, upi.getDataRetention());
- assertEquals(32, upi.getDataRetentionWeeks());
- }
-
- public void testUserTriggered() throws Exception {
- UsesPermissionInfo upi
- = getUsesPermissionInfo(Manifest.permission.RECORD_AUDIO);
- assertEquals(UsesPermissionInfo.USAGE_USER_TRIGGERED, upi.getDataSentOffDevice());
- assertEquals(UsesPermissionInfo.USAGE_USER_TRIGGERED,
- upi.getDataSharedWithThirdParty());
- assertEquals(UsesPermissionInfo.USAGE_USER_TRIGGERED,
- upi.getDataUsedForMonetization());
- assertEquals(UsesPermissionInfo.RETENTION_UNLIMITED, upi.getDataRetention());
- }
-
- public void testUndefined() throws Exception {
- UsesPermissionInfo upi
- = getUsesPermissionInfo(Manifest.permission.READ_CALENDAR);
- assertEquals(UsesPermissionInfo.USAGE_UNDEFINED, upi.getDataSentOffDevice());
- assertEquals(UsesPermissionInfo.USAGE_UNDEFINED, upi.getDataSharedWithThirdParty());
- assertEquals(UsesPermissionInfo.USAGE_UNDEFINED, upi.getDataUsedForMonetization());
- assertEquals(UsesPermissionInfo.RETENTION_UNDEFINED, upi.getDataRetention());
- }
-
- public void testUsageInfoRequired() throws Exception {
- PermissionInfo pi = mPm.getPermissionInfo("android.permission.cts.D", 0);
- assertTrue(pi.usageInfoRequired);
- }
-}
diff --git a/tests/tests/permission/src/android/permission/cts/ShellPermissionTest.java b/tests/tests/permission/src/android/permission/cts/ShellPermissionTest.java
index cf49f50..96eef77 100644
--- a/tests/tests/permission/src/android/permission/cts/ShellPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/ShellPermissionTest.java
@@ -23,7 +23,6 @@
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
-import android.content.pm.UsesPermissionInfo;
import android.os.Process;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
@@ -65,10 +64,9 @@
String pkg = pkgs[0];
final PackageInfo packageInfo = pm.getPackageInfo(pkg, PackageManager.GET_PERMISSIONS);
- assertNotNull("No permissions found for " + pkg, packageInfo.usesPermissions);
+ assertNotNull("No permissions found for " + pkg, packageInfo.requestedPermissions);
- for (UsesPermissionInfo permInfo : packageInfo.usesPermissions) {
- final String permission = permInfo.getPermission();
+ for (String permission : packageInfo.requestedPermissions) {
Log.d(LOG_TAG, "SHELL as " + pkg + " uses permission " + permission);
assertFalse("SHELL as " + pkg + " contains the illegal permission " + permission,
blacklist.contains(permission));
diff --git a/tests/tests/preference/AndroidTest.xml b/tests/tests/preference/AndroidTest.xml
index 4287b76..1980c38 100644
--- a/tests/tests/preference/AndroidTest.xml
+++ b/tests/tests/preference/AndroidTest.xml
@@ -17,6 +17,7 @@
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="uitoolkit" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="not-shardable" value="true" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
diff --git a/tests/tests/preference/OWNERS b/tests/tests/preference/OWNERS
index d20511f..827134e 100644
--- a/tests/tests/preference/OWNERS
+++ b/tests/tests/preference/OWNERS
@@ -1,2 +1,3 @@
+lpf@google.com
pavlis@google.com
clarabayarri@google.com
diff --git a/tests/tests/preference2/AndroidTest.xml b/tests/tests/preference2/AndroidTest.xml
index a3fb234..452702d 100644
--- a/tests/tests/preference2/AndroidTest.xml
+++ b/tests/tests/preference2/AndroidTest.xml
@@ -17,6 +17,7 @@
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="uitoolkit" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsPreference2TestCases.apk" />
diff --git a/tests/tests/preference2/OWNERS b/tests/tests/preference2/OWNERS
new file mode 100644
index 0000000..827134e
--- /dev/null
+++ b/tests/tests/preference2/OWNERS
@@ -0,0 +1,3 @@
+lpf@google.com
+pavlis@google.com
+clarabayarri@google.com
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java
index bb5857e..914660d 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java
@@ -41,6 +41,7 @@
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionPlan;
+import android.telephony.TelephonyManager;
import com.android.compatibility.common.util.SystemUtil;
import com.android.internal.util.ArrayUtils;
@@ -167,7 +168,7 @@
@Test
public void testIsUsableSubscriptionId() throws Exception {
if (!isSupported()) return;
- assertTrue(SubscriptionManager.isUsableSubIdValue(mSubId));
+ assertTrue(SubscriptionManager.isUsableSubscriptionId(mSubId));
}
@Test
@@ -405,6 +406,15 @@
}
@Test
+ public void testSubscriptionInfoCarrierId() {
+ if (!isSupported()) return;
+
+ SubscriptionInfo info = mSm.getActiveSubscriptionInfo(mSubId);
+ int carrierId = info.getCarrierId();
+ assertTrue(carrierId >= TelephonyManager.UNKNOWN_CARRIER_ID);
+ }
+
+ @Test
public void testSettingSubscriptionMeteredNess() throws Exception {
if (!isSupported()) return;
diff --git a/tests/tests/telephony4/src/android/telephony4/cts/SimRestrictedApisTest.java b/tests/tests/telephony4/src/android/telephony4/cts/SimRestrictedApisTest.java
index 4732193..8058679 100644
--- a/tests/tests/telephony4/src/android/telephony4/cts/SimRestrictedApisTest.java
+++ b/tests/tests/telephony4/src/android/telephony4/cts/SimRestrictedApisTest.java
@@ -67,21 +67,6 @@
}
/**
- * Tests the TelephonyManager.setLine1NumberForDisplay(long, string, string) API. This makes a
- * call to setLine1NumberForDisplay() API and expects a SecurityException since the test apk is
- * not signed by the certificate on the SIM.
- */
- public void testSetLine1NumberForDisplay2() {
- try {
- if (isSimCardPresent()) {
- mTelephonyManager.setLine1NumberForDisplay(0, "", "");
- fail("Expected SecurityException. App doesn't have carrier privileges.");
- }
- } catch (SecurityException expected) {
- }
- }
-
- /**
* Tests the TelephonyManager.iccOpenLogicalChannel() API. This makes a call to
* iccOpenLogicalChannel() API and expects a SecurityException since the test apk is not signed
* by certificate on the SIM.
@@ -172,34 +157,6 @@
}
/**
- * Tests the TelephonyManager.nvWriteItem() API. This makes a call to nvWriteItem() API and
- * expects a SecurityException since the test apk is not signed by a certificate on the SIM.
- */
- public void testNvWriteItem() {
- try {
- if (isSimCardPresent()) {
- mTelephonyManager.nvWriteItem(0, "");
- fail("Expected SecurityException. App doesn't have carrier privileges.");
- }
- } catch (SecurityException expected) {
- }
- }
-
- /**
- * Tests the TelephonyManager.nvWriteCdmaPrl() API. This makes a call to nvWriteCdmaPrl() API
- * and expects a SecurityException since the test apk is not signed by a certificate on the SIM.
- */
- public void testNvWriteCdmaPrl() {
- try {
- if (isSimCardPresent()) {
- mTelephonyManager.nvWriteCdmaPrl(null);
- fail("Expected SecurityException. App doesn't have carrier privileges.");
- }
- } catch (SecurityException expected) {
- }
- }
-
- /**
* Tests the TelephonyManager.nvResetConfig() API. This makes a call to nvResetConfig() API and
* expects a SecurityException since the test apk is not signed by a certificate on the SIM.
*/
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/EdgeEffectTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/EdgeEffectTests.java
index 57462b6..955d51f 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/EdgeEffectTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/EdgeEffectTests.java
@@ -19,6 +19,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyFloat;
import static org.mockito.Mockito.mock;
@@ -26,6 +27,7 @@
import android.content.Context;
import android.graphics.Bitmap;
+import android.graphics.BlendMode;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
@@ -137,6 +139,17 @@
}
@Test
+ public void testSetBlendMode() {
+ assertEdgeEffect(edgeEffect -> {
+ edgeEffect.setBlendMode(null);
+ assertNull(edgeEffect.getBlendMode());
+ edgeEffect.setBlendMode(EdgeEffect.DEFAULT_BLEND_MODE);
+ assertEquals(BlendMode.SRC_ATOP, edgeEffect.getBlendMode());
+ edgeEffect.onPull(1);
+ });
+ }
+
+ @Test
public void testOnPullWithDisplacement() {
assertEdgeEffect(edgeEffect -> {
edgeEffect.onPull(1, 0);
diff --git a/tests/tests/view/AndroidManifest.xml b/tests/tests/view/AndroidManifest.xml
index dabbc1a..925f3e2 100644
--- a/tests/tests/view/AndroidManifest.xml
+++ b/tests/tests/view/AndroidManifest.xml
@@ -31,6 +31,15 @@
android:supportsRtl="true">
<uses-library android:name="android.test.runner" />
+ <activity android:name="android.app.Activity"
+ android:label="Empty Activity"
+ android:theme="@style/ViewStyleTestTheme">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+ </intent-filter>
+ </activity>
+
<activity android:name="android.view.cts.ViewStubCtsActivity"
android:screenOrientation="locked"
android:label="ViewStubCtsActivity">
diff --git a/tests/tests/view/res/layout/view_style_layout.xml b/tests/tests/view/res/layout/view_style_layout.xml
new file mode 100644
index 0000000..dd488ef
--- /dev/null
+++ b/tests/tests/view/res/layout/view_style_layout.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <View android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/view1"
+ android:paddingTop="7dp"
+ style="@style/ExplicitStyle1" />
+
+ <View android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/view2"
+ style="@style/ExplicitStyle2" />
+
+ <View android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/view3" />
+
+ <View android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/view4"
+ style="?android:attr/textAppearanceLarge"/>
+
+ <Button android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/button1" />
+
+ <Button android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/button2"
+ style="@style/ExplicitStyle1" />
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/tests/view/res/values/styles.xml b/tests/tests/view/res/values/styles.xml
index 5e47363..ab984e8 100644
--- a/tests/tests/view/res/values/styles.xml
+++ b/tests/tests/view/res/values/styles.xml
@@ -187,4 +187,26 @@
<item name="android:windowContentTransitions">false</item>
<item name="android:windowAnimationStyle">@null</item>
</style>
+
+ <style name="ViewStyleTestTheme" parent="@android:Theme.Material">
+ <item name="android:buttonStyle">@style/MyButtonStyle</item>
+ </style>
+
+ <style name="MyButtonStyle" parent="@style/MyButtonStyleParent">
+ <item name="android:paddingTop">3dp</item>
+ </style>
+
+ <style name="MyButtonStyleParent">
+ <item name="android:textColor">#ff00ff</item>
+ </style>
+
+ <style name="ExplicitStyle1" parent="@style/ParentOfExplicitStyle1">
+ <item name="android:padding">1dp</item>
+ </style>
+
+ <style name="ParentOfExplicitStyle1">
+ <item name="android:paddingLeft">2dp</item>
+ </style>
+
+ <style name="ExplicitStyle2" />
</resources>
diff --git a/tests/tests/view/src/android/view/cts/ViewStyleTest.java b/tests/tests/view/src/android/view/cts/ViewStyleTest.java
new file mode 100644
index 0000000..866e8b6
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/ViewStyleTest.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2019 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.view.cts;
+
+import static org.junit.Assert.assertEquals;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.MediumTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.uiautomator.UiDevice;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+import java.util.Map;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class ViewStyleTest {
+
+ @Rule
+ public ActivityTestRule<Activity> mActivityRule =
+ new ActivityTestRule<>(Activity.class, true, false);
+
+ private static final String DISABLE_SHELL_COMMAND =
+ "settings delete global debug_view_attributes_application_package";
+
+ private static final String ENABLE_SHELL_COMMAND =
+ "settings put global debug_view_attributes_application_package android.view.cts";
+
+ private UiDevice mUiDevice;
+
+ @Before
+ public void setUp() throws Exception {
+ mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ mUiDevice.executeShellCommand(ENABLE_SHELL_COMMAND);
+ mActivityRule.launchActivity(null);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mUiDevice.executeShellCommand(DISABLE_SHELL_COMMAND);
+ }
+
+ @Test
+ public void testGetExplicitStyle() {
+ Context context = InstrumentationRegistry.getTargetContext();
+ LayoutInflater inflater = LayoutInflater.from(context);
+ LinearLayout rootView = (LinearLayout) inflater.inflate(R.layout.view_style_layout, null);
+ View view1 = rootView.findViewById(R.id.view1);
+ assertEquals(R.style.ExplicitStyle1, view1.getExplicitStyle());
+
+ View view2 = rootView.findViewById(R.id.view2);
+ assertEquals(R.style.ExplicitStyle2, view2.getExplicitStyle());
+
+ View view3 = rootView.findViewById(R.id.view3);
+ assertEquals(Resources.ID_NULL, view3.getExplicitStyle());
+
+ View view4 = rootView.findViewById(R.id.view4);
+ assertEquals(android.R.style.TextAppearance_Material_Large, view4.getExplicitStyle());
+ }
+
+ @Test
+ public void testGetAttributeResolutionStack() {
+ LayoutInflater inflater = LayoutInflater.from(mActivityRule.getActivity());
+ LinearLayout rootView = (LinearLayout) inflater.inflate(R.layout.view_style_layout, null);
+ // View that has an explicit style ExplicitStyle1 set via style = ...
+ View view1 = rootView.findViewById(R.id.view1);
+ List<Integer> stackView1 = view1.getAttributeResolutionStack();
+ assertEquals(3, stackView1.size());
+ assertEquals(R.layout.view_style_layout, stackView1.get(0).intValue());
+ assertEquals(R.style.ExplicitStyle1, stackView1.get(1).intValue());
+ assertEquals(R.style.ParentOfExplicitStyle1, stackView1.get(2).intValue());
+
+ // Button that has the default style MyButtonStyle set in ViewStyleTestTheme Activity theme
+ // via android:buttonStyle
+ Button button1 = rootView.findViewById(R.id.button1);
+ List<Integer> stackButton1 = button1.getAttributeResolutionStack();
+ assertEquals(3, stackButton1.size());
+ assertEquals(R.layout.view_style_layout, stackButton1.get(0).intValue());
+ assertEquals(R.style.MyButtonStyle, stackButton1.get(1).intValue());
+ assertEquals(R.style.MyButtonStyleParent, stackButton1.get(2).intValue());
+
+ // Button that has the default style MyButtonStyle set in ViewStyleTestTheme Activity theme
+ // via android:buttonStyle and has an explicit style ExplicitStyle1 set via style = ...
+ Button button2 = rootView.findViewById(R.id.button2);
+ List<Integer> stackButton2 = button2.getAttributeResolutionStack();
+ assertEquals(5, stackButton2.size());
+ assertEquals(R.layout.view_style_layout, stackButton2.get(0).intValue());
+ assertEquals(R.style.ExplicitStyle1, stackButton2.get(1).intValue());
+ assertEquals(R.style.ParentOfExplicitStyle1, stackButton2.get(2).intValue());
+ assertEquals(R.style.MyButtonStyle, stackButton2.get(3).intValue());
+ assertEquals(R.style.MyButtonStyleParent, stackButton2.get(4).intValue());
+ }
+
+ @Test
+ public void testGetAttributeSourceResourceMap() {
+ LayoutInflater inflater = LayoutInflater.from(mActivityRule.getActivity());
+ LinearLayout rootView = (LinearLayout) inflater.inflate(R.layout.view_style_layout, null);
+ // View that has an explicit style ExplicitStyle1 set via style = ...
+ View view1 = rootView.findViewById(R.id.view1);
+ Map<Integer, Integer> attributeMapView1 = view1.getAttributeSourceResourceMap();
+ assertEquals(9, attributeMapView1.size());
+ assertEquals(R.style.ExplicitStyle1,
+ (attributeMapView1.get(android.R.attr.padding)).intValue());
+ assertEquals(R.style.ParentOfExplicitStyle1,
+ (attributeMapView1.get(android.R.attr.paddingLeft)).intValue());
+ assertEquals(R.layout.view_style_layout,
+ (attributeMapView1.get(android.R.attr.paddingTop)).intValue());
+ }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/AbsListViewTest.java b/tests/tests/widget/src/android/widget/cts/AbsListViewTest.java
index 49b0f64..39ddda0 100644
--- a/tests/tests/widget/src/android/widget/cts/AbsListViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AbsListViewTest.java
@@ -69,6 +69,7 @@
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
+import android.widget.EdgeEffect;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
@@ -1127,6 +1128,27 @@
}
}
+ @SmallTest
+ @UiThreadTest
+ @Test
+ public void testEdgeEffectColors() {
+ int defaultColor = new EdgeEffect(mListView.getContext()).getColor();
+ assertEquals(mListView.getTopEdgeEffectColor(), defaultColor);
+ assertEquals(mListView.getBottomEdgeEffectColor(), defaultColor);
+
+ mListView.setEdgeEffectColor(Color.BLUE);
+ assertEquals(mListView.getTopEdgeEffectColor(), Color.BLUE);
+ assertEquals(mListView.getBottomEdgeEffectColor(), Color.BLUE);
+
+ mListView.setTopEdgeEffectColor(Color.RED);
+ assertEquals(mListView.getTopEdgeEffectColor(), Color.RED);
+ assertEquals(mListView.getBottomEdgeEffectColor(), Color.BLUE);
+
+ mListView.setBottomEdgeEffectColor(Color.GREEN);
+ assertEquals(mListView.getTopEdgeEffectColor(), Color.RED);
+ assertEquals(mListView.getBottomEdgeEffectColor(), Color.GREEN);
+ }
+
// Helper method that emulates fast scroll by dragging along the right edge of our ListView.
private void verifyFastScroll() throws Throwable {
setAdapter();