am 9cd799e8: am fca7c4fe: Merge "Update Android CTS bandaid urls that use test_key1 to a new key" into lmp-mr1-dev
* commit '9cd799e8fee57b94ee4124c0cc15d564c16e718e':
Update Android CTS bandaid urls that use test_key1 to a new key
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index 953a1dd..e80f4be 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -113,6 +113,7 @@
CtsAdminTestCases \
CtsAnimationTestCases \
CtsAppTestCases \
+ CtsAppWidgetTestCases \
CtsBluetoothTestCases \
CtsCalendarcommon2TestCases \
CtsContentTestCases \
@@ -202,11 +203,7 @@
CtsUiAutomatorTests
cts_device_jars := \
- CtsDeviceJank \
- CtsPrintInstrument
-
-cts_device_executables := \
- print-instrument
+ CtsDeviceJank
cts_target_junit_tests := \
CtsJdwp
diff --git a/apps/CtsVerifier/Android.mk b/apps/CtsVerifier/Android.mk
index 87f962f..f6ece3b 100644
--- a/apps/CtsVerifier/Android.mk
+++ b/apps/CtsVerifier/Android.mk
@@ -32,8 +32,7 @@
LOCAL_PACKAGE_NAME := CtsVerifier
-LOCAL_JNI_SHARED_LIBRARIES := libctsverifier_jni \
- #libcameraanalyzer # Needed for the disabled CameraAnalyzer tests
+LOCAL_JNI_SHARED_LIBRARIES := libctsverifier_jni
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 3b2eb46..8666a14 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -18,7 +18,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.cts.verifier"
android:versionCode="5"
- android:versionName="5.1_r0.5">
+ android:versionName="5.0_r1.91">
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="21"/>
@@ -870,23 +870,6 @@
<meta-data android:name="test_required_features" android:value="android.hardware.camera.any"/>
</activity>
-<!-- Experimental. If re-enabling, libcameraanalyzer must be included in the build
- <activity android:name=".camera.analyzer.CameraAnalyzerActivity"
- android:label="@string/camera_analyzer"
- android:screenOrientation="landscape">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
- <meta-data android:name="test_category" android:value="@string/test_category_camera" />
-
- <intent-filter>
- <action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
- </intent-filter>
- <meta-data android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
- android:resource="@xml/accessory_filter_adk" />
- </activity>
--->
<activity android:name=".camera.intents.CameraIntentsActivity"
android:label="@string/camera_intents">
@@ -1135,8 +1118,6 @@
<meta-data android:name="test_category" android:value="@string/test_category_other" />
<meta-data android:name="test_required_features"
android:value="android.software.app_widgets" />
- <meta-data android:name="test_excluded_features"
- android:value="android.software.leanback" />
</activity>
<activity android:name=".deskclock.DeskClockTestsActivity"
diff --git a/apps/CtsVerifier/jni/cameraanalyzer/Android.mk b/apps/CtsVerifier/jni/cameraanalyzer/Android.mk
deleted file mode 100644
index d595a20..0000000
--- a/apps/CtsVerifier/jni/cameraanalyzer/Android.mk
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright (C) 2011 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_MODULE := libcameraanalyzer
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := com_android_cts_verifier_camera_analyzer_CameraTests.cpp \
- com_android_cts_verifier_camera_analyzer_ColorCheckerTest.cpp \
- com_android_cts_verifier_camera_analyzer_ExposureCompensationTest.cpp \
- com_android_cts_verifier_camera_analyzer_AutoLockTest.cpp \
- com_android_cts_verifier_camera_analyzer_MeteringTest.cpp \
- com_android_cts_verifier_camera_analyzer_WhiteBalanceTest.cpp
-
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../include/colorchecker $(JNI_H_INCLUDE)
-
-LOCAL_CXX_STL := libc++
-LOCAL_STATIC_LIBRARIES := libcolorchecker
-LOCAL_SHARED_LIBRARIES := \
- libjnigraphics \
- libcutils \
- libutils \
- liblog \
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_AutoLockTest.cpp b/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_AutoLockTest.cpp
deleted file mode 100644
index fac39e1..0000000
--- a/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_AutoLockTest.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#define LOG_NDEBUG 0
-
-#define LOG_TAG "AutoLockJNI"
-#include <utils/Log.h>
-#include "com_android_cts_verifier_camera_analyzer_AutoLockTest.h"
-
-#include <vector>
-#include <string>
-#include <string.h>
-
-#include "testingimage.h"
-#include "autolocktest.h"
-#include "vec2.h"
-#include "android/bitmap.h"
-
-jlong Java_com_android_cts_verifier_camera_analyzer_AutoLockTest_createAutoLockTest(
- JNIEnv* env,
- jobject thiz) {
-
- AutoLockTest* testHandler = new AutoLockTest();
- long handlerAddress = (long)testHandler;
- return handlerAddress;
-}
-
-void Java_com_android_cts_verifier_camera_analyzer_AutoLockTest_createAutoLockClass(
- JNIEnv* env,
- jobject thiz,
- jlong inputImageAddress,
- jlong inputHandlerAddress,
- jlong checkercenterAddress,
- jlong checkerradiusAddress) {
-
- ALOGV("JNI createAutoLockClass starts!");
- long imageAddress = (long)inputImageAddress;
- long handlerAddress = (long)inputHandlerAddress;
-
- TestingImage *image = (TestingImage*) imageAddress;
- AutoLockTest *testHandler = (AutoLockTest*) handlerAddress;
-
- std::vector<std::vector< Vec2f > >* checkerCenter =
- (std::vector<std::vector< Vec2f > >*) (long) checkercenterAddress;
- std::vector<std::vector< float > >* checkerRadius =
- (std::vector<std::vector< float > >*) (long) checkerradiusAddress;
- ALOGV("Classes recovered");
-
- // Uses only the gray patches on the color checker for comparison.
- testHandler->addDataToList(image->getColorChecker(3, 4, 0, 6,
- checkerCenter,
- checkerRadius));
-
- delete image;
-}
-
-void Java_com_android_cts_verifier_camera_analyzer_AutoLockTest_processAutoLockTest(
- JNIEnv* env,
- jobject thiz,
- jlong inputHandlerAddress,
- jbooleanArray tempArray) {
-
- ALOGV("Processing Auto Lock data!");
-
- long handlerAddress = (long) inputHandlerAddress;
- AutoLockTest *testHandler = (AutoLockTest*) handlerAddress;
-
- testHandler->processData();
-
- // Converts the native boolean array into a java boolean array.
- const std::vector<bool>* nativeComparisonResults =
- testHandler->getComparisonResults();
- jboolean comparisonResults[nativeComparisonResults->size()];
-
- for (int i = 0; i < nativeComparisonResults->size(); ++i) {
- comparisonResults[i] = (jboolean) (*nativeComparisonResults)[i];
- }
-
- env->SetBooleanArrayRegion(tempArray,
- 0, nativeComparisonResults->size(),
- comparisonResults);
- testHandler->clearData();
-}
diff --git a/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_AutoLockTest.h b/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_AutoLockTest.h
deleted file mode 100644
index dc40bc2..0000000
--- a/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_AutoLockTest.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef JNI_CAMERAANALYZER_AUTOLOCKTEST_H
-#define JNI_CAMERAANALYZER_AUTOLOCKTEST_H
-
-#include <jni.h>
-#include <stdio.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-JNIEXPORT jlong JNICALL
-Java_com_android_cts_verifier_camera_analyzer_AutoLockTest_createAutoLockTest(
- JNIEnv* env,
- jobject thiz);
-
-JNIEXPORT void JNICALL
-Java_com_android_cts_verifier_camera_analyzer_AutoLockTest_createAutoLockClass(
- JNIEnv *env,
- jobject thiz,
- jlong inputImageAddress,
- jlong inputHandlerAddress,
- jlong checkercenterAddress,
- jlong checkerradiusAddress);
-
-JNIEXPORT void JNICALL
-Java_com_android_cts_verifier_camera_analyzer_AutoLockTest_processAutoLockTest(
- JNIEnv* env,
- jobject thiz,
- jlong inputHandlerAddress,
- jbooleanArray tempArray);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_CameraTests.cpp b/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_CameraTests.cpp
deleted file mode 100644
index ed91233..0000000
--- a/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_CameraTests.cpp
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#define LOG_NDEBUG 0
-
-#define LOG_TAG "CameraTestsJNI"
-#include <utils/Log.h>
-#include "com_android_cts_verifier_camera_analyzer_CameraTests.h"
-#include "android/bitmap.h"
-#include "testingimage.h"
-#include "imagetesthandler.h"
-
-#include <string.h>
-
-jlong Java_com_android_cts_verifier_camera_analyzer_CameraTests_findNative(
- JNIEnv* env,
- jobject thiz,
- jobject inputBitmap) {
-
- ALOGV("JNI findNative starts!");
-
- // Verify that we can handle the input bitmap
- AndroidBitmapInfo inputInfo;
- AndroidBitmap_getInfo(env, inputBitmap, &inputInfo);
- if (inputInfo.format != ANDROID_BITMAP_FORMAT_RGBA_8888 &&
- inputInfo.format != ANDROID_BITMAP_FORMAT_RGB_565) {
- ALOGE("Only RGBA_8888 and RGB_565 bitmaps are supported, type was %d.",
- inputInfo.format);
- }
-
- // Get some references to the fields and class type of ColorChecker
- jclass thizCls = env->GetObjectClass(thiz);
- ALOGV("ColorChecker field and classes reference finished!");
-
- // Get raw inputs and outputs ready
- uint8_t *inputBuffer = NULL;
- int result = AndroidBitmap_lockPixels(
- env,
- inputBitmap,
- reinterpret_cast<void**>(&inputBuffer));
-
- if (result != ANDROID_BITMAP_RESULT_SUCCESS) {
- ALOGE("Unable to lock input bitmap");
- }
-
- uint8_t *outputImage = NULL;
- int outputWidth, outputHeight;
-
- ALOGV("Input and output images created!");
-
- // Find the color checker
- bool success;
- uint8_t *inputBufferRGBA = NULL;
- int inputStride;
- bool freeInputRGBA = false;
- switch (inputInfo.format) {
- case ANDROID_BITMAP_FORMAT_RGB_565: {
- // First convert to RGBA_8888
- inputBufferRGBA = new uint8_t[inputInfo.width *
- inputInfo.height *
- 4];
- inputStride = inputInfo.width * 4;
- uint8_t *outP = inputBufferRGBA;
- for (int y = 0; y < inputInfo.height; y++ ) {
- uint16_t *inP = (uint16_t*)(&inputBuffer[y * inputInfo.stride]);
- for (int x = 0; x < inputInfo.width; x++) {
- *(outP++) = ( ((*inP) >> 0) & 0x001F) << 3;
- *(outP++) = ( ((*inP) >> 5) & 0x003F) << 2;
- *(outP++) = ( ((*inP) >> 11) & 0x001F) << 3;
- outP++;
- inP++;
- }
- }
- freeInputRGBA = true;
-
- ALOGV("RGB_565 Format with width, height and stride as %d, %d, %d",
- inputInfo.width, inputInfo.height, inputStride);
- break;
- }
- case ANDROID_BITMAP_FORMAT_RGBA_8888: {
- // Already in RGBA
- inputBufferRGBA = inputBuffer;
- inputStride = inputInfo.stride;
- ALOGV("RGB_8888 Format with width, height and stride as %d, %d, %d",
- inputInfo.width, inputInfo.height, inputStride);
- break;
- }
- }
-
- TestingImage *input_testing_image =
- new TestingImage(inputBufferRGBA, inputInfo.height, inputInfo.width,
- 4, inputStride, 120, 160);
-
- long lp = (long)input_testing_image;
-
- result = AndroidBitmap_unlockPixels(env, inputBitmap);
- if (result != ANDROID_BITMAP_RESULT_SUCCESS) {
- ALOGE("Unable to unlock input bitmap");
- }
-
- if (freeInputRGBA) {
- ALOGV("Deleteing inputbufferRGBA");
- delete[] inputBufferRGBA;
- }
-
- return lp;
- ALOGV("Input format switched!");
-}
-
-jlong Java_com_android_cts_verifier_camera_analyzer_CameraTests_createImageTestHandler(
- JNIEnv* env,
- jobject thiz,
- jint debugHeight,
- jint debugWidth) {
-
- ImageTestHandler* testHandler =
- new ImageTestHandler(debugHeight, debugWidth);
- long handlerAddress = (long)testHandler;
- return handlerAddress;
-}
-
-void Java_com_android_cts_verifier_camera_analyzer_CameraTests_cleanUpHandler(
- JNIEnv* env,
- jobject thiz,
- jlong inputHandlerAddress) {
-
- ImageTestHandler* testHandler = (ImageTestHandler*) (long) inputHandlerAddress;
- delete testHandler;
-}
-
-void Java_com_android_cts_verifier_camera_analyzer_CameraTests_displayHandlerDebugOutput(
- JNIEnv* env,
- jobject thiz,
- jlong inputHandlerAddress) {
-
- jclass thizCls = env->GetObjectClass(thiz);
- jfieldID outputId = env->GetFieldID(thizCls, "mDebugOutput",
- "Landroid/graphics/Bitmap;");
-
- ImageTestHandler* testHandler = (ImageTestHandler*) (long) inputHandlerAddress;
- uint8_t *outputImage = new uint8_t[testHandler->getDebugHeight() *
- testHandler->getDebugWidth() * 4];
-
- const unsigned char *debugoutput = testHandler->debug_output();
- memcpy(outputImage, debugoutput, testHandler->getDebugHeight() *
- testHandler->getDebugWidth() * 4);
-
- int outputWidth = testHandler->getDebugWidth();
- int outputHeight = testHandler->getDebugHeight();
- bool success = false;
-
- if (outputImage == NULL) {
- ALOGV("output Image is null!");
- } else {
- ALOGV("output Image is ready!");
- }
-
- // Create debug bitmap from output image data
- if (outputImage != NULL) {
- // Get method handles, create inputs to createBitmap
- jclass bitmapClass =
- env->FindClass("android/graphics/Bitmap");
- jclass bitmapConfigClass =
- env->FindClass("android/graphics/Bitmap$Config");
-
- jmethodID createBitmap = env->GetStaticMethodID(
- bitmapClass, "createBitmap",
- "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");
-
- jmethodID getConfig = env->GetStaticMethodID(
- bitmapConfigClass, "valueOf",
- "(Ljava/lang/String;)Landroid/graphics/Bitmap$Config;");
-
- // Create bitmap config and bitmap
- jstring bitmapConfigValue = env->NewStringUTF("ARGB_8888");
- jobject rgbaConfig = env->CallStaticObjectMethod(bitmapConfigClass,
- getConfig,
- bitmapConfigValue);
- jobject outputBitmap = env->CallStaticObjectMethod(bitmapClass,
- createBitmap,
- outputWidth,
- outputHeight,
- rgbaConfig);
- // Copy output image into it
- uint8_t *outputBuffer;
- int result = AndroidBitmap_lockPixels(
- env,
- outputBitmap,
- reinterpret_cast<void**>(&outputBuffer) );
-
- if (result != ANDROID_BITMAP_RESULT_SUCCESS) {
- ALOGE("Unable to lock output bitmap");
- }
-
- memcpy(outputBuffer, outputImage, outputWidth * outputHeight * 4);
-
- result = AndroidBitmap_unlockPixels(env, outputBitmap);
- if (result != ANDROID_BITMAP_RESULT_SUCCESS) {
- ALOGE("Unable to unlock output bitmap");
- }
-
- // Write new Bitmap reference into mDebugOutput class member
- env->SetObjectField(thiz, outputId, outputBitmap);
- ALOGV("Copied to outputBitmap");
- delete [] outputImage;
- env->DeleteLocalRef(outputBitmap);
- env->DeleteLocalRef(rgbaConfig);
- env->DeleteLocalRef(bitmapClass);
- env->DeleteLocalRef(bitmapConfigClass);
- }
-}
diff --git a/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_CameraTests.h b/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_CameraTests.h
deleted file mode 100644
index e071dc1..0000000
--- a/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_CameraTests.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef JNI_CAMERAANALYZER_CAMERATESTS_H
-#define JNI_CAMERAANALYZER_CAMERATESTS_H
-
-#include <jni.h>
-#include <stdio.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-JNIEXPORT jlong JNICALL
-Java_com_android_cts_verifier_camera_analyzer_CameraTests_findNative(
- JNIEnv *env,
- jobject thiz,
- jobject inputBitmap);
-
-JNIEXPORT jlong JNICALL
-Java_com_android_cts_verifier_camera_analyzer_CameraTests_createImageTestHandler(
- JNIEnv* env,
- jobject thiz,
- jint debugHeight,
- jint debugWidth);
-
-JNIEXPORT void JNICALL
-Java_com_android_cts_verifier_camera_analyzer_CameraTests_cleanUpHandler(
- JNIEnv* env,
- jobject thiz,
- jlong inputHandlerAddress);
-
-JNIEXPORT void JNICALL
-Java_com_android_cts_verifier_camera_analyzer_CameraTests_displayHandlerDebugOutput(
- JNIEnv* env,
- jobject thiz,
- jlong inputHandlerAddress);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_ColorCheckerTest.cpp b/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_ColorCheckerTest.cpp
deleted file mode 100644
index 94e3ac2..0000000
--- a/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_ColorCheckerTest.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#define LOG_NDEBUG 0
-
-#define LOG_TAG "FindColorCheckerJNI"
-#include <utils/Log.h>
-#include "com_android_cts_verifier_camera_analyzer_ColorCheckerTest.h"
-
-#include <string.h>
-#include "android/bitmap.h"
-#include "colorcheckertest.h"
-#include "testingimage.h"
-
-jlong Java_com_android_cts_verifier_camera_analyzer_ColorCheckerTest_createColorCheckerTest(
- JNIEnv* env,
- jobject thiz,
- jint debugHeight,
- jint debugWidth) {
- ColorCheckerTest* testHandler = new ColorCheckerTest(debugHeight,
- debugWidth);
- long testHandlerAddress = (long)testHandler;
- return testHandlerAddress;
-}
-
-void Java_com_android_cts_verifier_camera_analyzer_ColorCheckerTest_createColorCheckerClass(
- JNIEnv* env,
- jobject thiz,
- jlong inputImageAddress,
- jlong inputHandlerAddress) {
- ALOGV("JNI createColorCheckerClass starts!");
-
- TestingImage *testImage = (TestingImage*) (long) inputImageAddress;
- ColorCheckerTest *testHandler = (ColorCheckerTest*)
- (long) inputHandlerAddress;
-
- testHandler->addTestingImage(testImage);
-}
-
-jboolean Java_com_android_cts_verifier_camera_analyzer_ColorCheckerTest_processColorCheckerTest(
- JNIEnv* env,
- jobject thiz,
- jlong inputHandlerAddress) {
-
- ColorCheckerTest *testHandler = (ColorCheckerTest*)
- (long) inputHandlerAddress;
- testHandler->processData();
- return testHandler->getSuccess();
-}
-
-jlong Java_com_android_cts_verifier_camera_analyzer_ColorCheckerTest_getColorCheckerRadiusAdd(
- JNIEnv* env,
- jobject thiz,
- jlong inputHandlerAddress) {
-
- ColorCheckerTest *testHandler = (ColorCheckerTest*)
- (long) inputHandlerAddress;
- long rtn = (long) testHandler->getCheckerRadiusAdd();
- return rtn;
-}
-
-jlong Java_com_android_cts_verifier_camera_analyzer_ColorCheckerTest_getColorCheckerCenterAdd(
- JNIEnv* env,
- jobject thiz,
- jlong inputHandlerAddress) {
-
- ColorCheckerTest *testHandler = (ColorCheckerTest*)
- (long) inputHandlerAddress;
-
- long rtn = (long) testHandler->getCheckerCenterAdd();
- return rtn;
-}
diff --git a/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_ColorCheckerTest.h b/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_ColorCheckerTest.h
deleted file mode 100644
index fb87735..0000000
--- a/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_ColorCheckerTest.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef JNI_CAMERAANALYZER_COLORCHECKERTEST_H
-#define JNI_CAMERAANALYZER_COLORCHECKERTEST_H
-
-#include <jni.h>
-#include <stdio.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-JNIEXPORT jlong JNICALL
-Java_com_android_cts_verifier_camera_analyzer_ColorCheckerTest_createColorCheckerTest(
- JNIEnv* env,
- jobject thiz,
- jint output_height,
- jint output_width);
-
-JNIEXPORT void JNICALL
-Java_com_android_cts_verifier_camera_analyzer_ColorCheckerTest_createColorCheckerClass(
- JNIEnv *env,
- jobject thiz,
- jlong buffer_address,
- jlong handler_address);
-
-JNIEXPORT jlong JNICALL
-Java_com_android_cts_verifier_camera_analyzer_ColorCheckerTest_getColorCheckerRadiusAdd(
- JNIEnv *env,
- jobject thiz,
- jlong handler_address);
-
-JNIEXPORT jlong JNICALL
-Java_com_android_cts_verifier_camera_analyzer_ColorCheckerTest_getColorCheckerCenterAdd(
- JNIEnv *env,
- jobject thiz,
- jlong handler_address);
-
-JNIEXPORT jboolean JNICALL
-Java_com_android_cts_verifier_camera_analyzer_ColorCheckerTest_processColorCheckerTest(
- JNIEnv* env,
- jobject thiz,
- jlong handler_address);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_ExposureCompensationTest.cpp b/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_ExposureCompensationTest.cpp
deleted file mode 100644
index 0224639..0000000
--- a/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_ExposureCompensationTest.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#define LOG_NDEBUG 0
-
-#define LOG_TAG "ExposureCompensationJNI"
-#include <utils/Log.h>
-#include <vector>
-#include <string.h>
-
-#include "android/bitmap.h"
-#include "testingimage.h"
-#include "exposurecompensationtest.h"
-#include "vec2.h"
-
-#include "com_android_cts_verifier_camera_analyzer_ExposureCompensationTest.h"
-
-jlong Java_com_android_cts_verifier_camera_analyzer_ExposureCompensationTest_createExposureCompensationTest(
- JNIEnv* env,
- jobject thiz,
- jint debugHeight,
- jint debugWidth) {
-
- ExposureCompensationTest* testHandler =
- new ExposureCompensationTest(debugHeight, debugWidth);
- long handlerAddress = (long)testHandler;
-
- return handlerAddress;
-}
-
-void Java_com_android_cts_verifier_camera_analyzer_ExposureCompensationTest_createExposureCompensationClass(
- JNIEnv* env,
- jobject thiz,
- jlong inputImageAddress,
- jlong inputHandlerAddress,
- jlong checkerCenterAddress,
- jlong checkerRadiusAddress,
- jfloat exposureValue) {
-
- ALOGV("JNI createExposureCompensationClass starts!");
-
- long imageAddress = (long)inputImageAddress;
- long handlerAddress = (long)inputHandlerAddress;
-
- TestingImage *inputImage = (TestingImage*) imageAddress;
- ExposureCompensationTest *testHandler =
- (ExposureCompensationTest*) handlerAddress;
-
- std::vector<std::vector< Vec2f > >* checkerCenter =
- (std::vector<std::vector< Vec2f > >*) (long) checkerCenterAddress;
- std::vector<std::vector< float > >* checkerRadius =
- (std::vector<std::vector< float > >*) (long) checkerRadiusAddress;
-
- const std::vector<Vec3f>* checkerValue =
- inputImage->getColorChecker(3, 4, 0, 6,
- checkerCenter, checkerRadius);
- testHandler->addDataToList((float) exposureValue, checkerValue);
- delete inputImage;
- delete checkerValue;
-}
-
-jstring Java_com_android_cts_verifier_camera_analyzer_ExposureCompensationTest_processExposureCompensationTest(
- JNIEnv* env,
- jobject thiz,
- jlong inputHandlerAddress) {
-
- long handlerAddress = (long) inputHandlerAddress;
- ExposureCompensationTest *testHandler =
- (ExposureCompensationTest*) handlerAddress;
-
- testHandler->processData();
-
- const char* nativeDebugText = testHandler->getDebugText();
- ALOGV("%s", nativeDebugText);
- return env->NewStringUTF(nativeDebugText);
-}
diff --git a/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_ExposureCompensationTest.h b/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_ExposureCompensationTest.h
deleted file mode 100644
index 8e8761d..0000000
--- a/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_ExposureCompensationTest.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef JNI_CAMERAANALYZER_EXPOSURECOMPENSATIONTEST_H
-#define JNI_CAMERAANALYZER_EXPOSURECOMPENSATIONTEST_H
-
-#include <jni.h>
-#include <stdio.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-JNIEXPORT jlong JNICALL
-Java_com_android_cts_verifier_camera_analyzer_ExposureCompensationTest_createExposureCompensationTest(
- JNIEnv* env,
- jobject thiz,
- jint debugHeight,
- jint debugWidth);
-
-JNIEXPORT void JNICALL
-Java_com_android_cts_verifier_camera_analyzer_ExposureCompensationTest_createExposureCompensationClass(
- JNIEnv* env,
- jobject thiz,
- jlong inputImageAddress,
- jlong inputHandlerAddress,
- jlong checkerCenterAddress,
- jlong checkerRadiusAddress,
- jfloat exposureValue);
-
-
-JNIEXPORT jstring JNICALL
-Java_com_android_cts_verifier_camera_analyzer_ExposureCompensationTest_processExposureCompensationTest(
- JNIEnv* env,
- jobject thiz,
- jlong inputHandlerAddress);
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_MeteringTest.cpp b/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_MeteringTest.cpp
deleted file mode 100644
index faebe21..0000000
--- a/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_MeteringTest.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#define LOG_NDEBUG 0
-
-#define LOG_TAG "MeteringJNI"
-#include <utils/Log.h>
-#include "com_android_cts_verifier_camera_analyzer_MeteringTest.h"
-
-#include <vector>
-#include <string>
-#include <string.h>
-#include <math.h>
-
-#include "testingimage.h"
-#include "meteringtest.h"
-#include "vec2.h"
-#include "android/bitmap.h"
-
-jlong Java_com_android_cts_verifier_camera_analyzer_MeteringTest_createMeteringTest(
- JNIEnv* env,
- jobject thiz) {
-
- MeteringTest* testHandler = new MeteringTest();
- long handlerAddress = (long)testHandler;
- return handlerAddress;
-}
-
-void Java_com_android_cts_verifier_camera_analyzer_MeteringTest_createMeteringClass(
- JNIEnv* env,
- jobject thiz,
- jlong inputImageAddress,
- jlong inputHandlerAddress,
- jlong checkercenterAddress,
- jlong checkerradiusAddress){
-
- ALOGV("JNI createMeteringClass starts!");
- long imageAddress = (long)inputImageAddress;
- long handlerAddress = (long)inputHandlerAddress;
-
- TestingImage *image = (TestingImage*) imageAddress;
- MeteringTest *testHandler = (MeteringTest*) handlerAddress;
-
- std::vector<std::vector< Vec2f > >* checkerCenter =
- (std::vector<std::vector< Vec2f > >*) (long) checkercenterAddress;
- std::vector<std::vector< float > >* checkerRadius =
- (std::vector<std::vector< float > >*) (long) checkerradiusAddress;
- ALOGV("Classes recovered");
-
- testHandler->addDataToList(image->getColorChecker(3, 4, 0, 6,
- checkerCenter,
- checkerRadius));
-
- delete image;
-}
-
-void Java_com_android_cts_verifier_camera_analyzer_MeteringTest_processMeteringTest(
- JNIEnv* env,
- jobject thiz,
- jlong inputHandlerAddress,
- jbooleanArray tempArray) {
-
- ALOGV("Processing Auto Lock data!");
-
- long handlerAddress = (long) inputHandlerAddress;
- MeteringTest *testHandler = (MeteringTest*) handlerAddress;
-
- testHandler->processData();
-
- const std::vector<bool>* nativeComparisonResults =
- testHandler->getComparisonResults();
- jboolean jComparisonResults[nativeComparisonResults->size()];
-
- for (int i = 0; i < nativeComparisonResults->size(); ++i) {
- jComparisonResults[i] = (jboolean) (*nativeComparisonResults)[i];
- }
-
- env->SetBooleanArrayRegion(tempArray,
- 0, nativeComparisonResults->size(),
- jComparisonResults);
- testHandler->clearData();
-}
-
-// Find the gray checker borders from the native array of checker center and
-// radius. Convert the coordinate to the coordinates accepted by Android
-// Camera.Area type, which defines the top left corner to (-1000, -1000) and
-// bottom right corner to (1000, 1000).
-void Java_com_android_cts_verifier_camera_analyzer_MeteringTest_findGreyCoordinates(
- JNIEnv* env,
- jobject thiz,
- jintArray greyCoordinates,
- jlong checkercenterAddress,
- jlong checkerradiusAddress){
-
- ALOGV("Start finding grey coordinates");
-
- std::vector<std::vector< Vec2f > >* checkerCenter =
- (std::vector<std::vector< Vec2f > >*) (long) checkercenterAddress;
- std::vector<std::vector< float > >* checkerRadius =
- (std::vector<std::vector< float > >*) (long) checkerradiusAddress;
-
- ALOGV("Checker recovered!");
- int nativeGreyCoordinates[24];
-
- for (int i = 0; i < 6; ++i) {
- float radius = sqrt((*checkerRadius)[3][i]);
- nativeGreyCoordinates[i * 4] = static_cast<int>(
- ((*checkerCenter)[3][i].y() - radius)
- / 160.0 * 2000.0 - 1000.0);
- nativeGreyCoordinates[i * 4 + 1] = static_cast<int>(
- ((*checkerCenter)[3][i].x() - radius)
- / 120.0 * 2000.0 - 1000.0);
- nativeGreyCoordinates[i * 4 + 2] = static_cast<int>(
- ((*checkerCenter)[3][i].y() + radius)
- / 160.0 * 2000.0 - 1000.0);
- nativeGreyCoordinates[i * 4 + 3] = static_cast<int>(
- ((*checkerCenter)[3][i].x() + radius)
- / 120.0 * 2000.0 - 1000.0);
-
- ALOGV("checker is bounded by %f, %f, %f",
- (*checkerCenter)[3][i].x(), (*checkerCenter)[3][i].y(), radius);
-
- ALOGV("Square is bounded by %d, %d, %d, %d",
- nativeGreyCoordinates[i * 4], nativeGreyCoordinates[i * 4 + 1],
- nativeGreyCoordinates[i * 4 + 2],
- nativeGreyCoordinates[i * 4 + 3]);
- }
-
- env->SetIntArrayRegion(greyCoordinates, 0, 24, nativeGreyCoordinates);
-}
diff --git a/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_MeteringTest.h b/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_MeteringTest.h
deleted file mode 100644
index ecc1b96..0000000
--- a/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_MeteringTest.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef JNI_CAMERAANALYZER_METERINGTEST_H
-#define JNI_CAMERAANALYZER_METERINGTEST_H
-
-#include <jni.h>
-#include <stdio.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-JNIEXPORT jlong JNICALL
-Java_com_android_cts_verifier_camera_analyzer_MeteringTest_createMeteringTest(
- JNIEnv* env,
- jobject thiz);
-
-JNIEXPORT void JNICALL
-Java_com_android_cts_verifier_camera_analyzer_MeteringTest_createMeteringClass(
- JNIEnv *env,
- jobject thiz,
- jlong inputAddress,
- jlong handlerAddress,
- jlong checkercenterAddress,
- jlong checkerradiusAddress);
-
-JNIEXPORT void JNICALL
-Java_com_android_cts_verifier_camera_analyzer_MeteringTest_processMeteringTest(
- JNIEnv* env,
- jobject thiz,
- jlong handlerAddress,
- jbooleanArray tempArray);
-
-JNIEXPORT void JNICALL
-Java_com_android_cts_verifier_camera_analyzer_MeteringTest_findGreyCoordinates(
- JNIEnv* env,
- jobject thiz,
- jintArray greyCoordinates,
- jlong checkercenterAddress,
- jlong checkerradiusAddress);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_WhiteBalanceTest.cpp b/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_WhiteBalanceTest.cpp
deleted file mode 100644
index bce0fca..0000000
--- a/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_WhiteBalanceTest.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#define LOG_NDEBUG 0
-
-#define LOG_TAG "WhiteBalanceJNI"
-#include <utils/Log.h>
-#include "com_android_cts_verifier_camera_analyzer_WhiteBalanceTest.h"
-
-#include <vector>
-#include <string>
-#include <string.h>
-
-#include "testingimage.h"
-#include "whitebalancetest.h"
-#include "vec2.h"
-#include "android/bitmap.h"
-
-jlong Java_com_android_cts_verifier_camera_analyzer_WhiteBalanceTest_createWhiteBalanceTest(
- JNIEnv* env,
- jobject thiz) {
-
- WhiteBalanceTest* testHandler = new WhiteBalanceTest();
- long handlerAddress = (long)testHandler;
- return handlerAddress;
-}
-
-void Java_com_android_cts_verifier_camera_analyzer_WhiteBalanceTest_createWhiteBalanceClass(
- JNIEnv* env,
- jobject thiz,
- jlong inputImageAddress,
- jlong inputHandlerAddress,
- jlong checkercenterAddress,
- jlong checkerradiusAddress,
- jstring whiteBalance){
-
- ALOGV("JNI createWhiteBalanceClass starts!");
- long imageAddress = (long)inputImageAddress;
- long handlerAddress = (long)inputHandlerAddress;
-
- TestingImage *image = (TestingImage*) imageAddress;
- WhiteBalanceTest *testHandler = (WhiteBalanceTest*) handlerAddress;
-
- std::vector<std::vector< Vec2f > >* checkerCenter =
- (std::vector<std::vector< Vec2f > >*) (long) checkercenterAddress;
- std::vector<std::vector< float > >* checkerRadius =
- (std::vector<std::vector< float > >*) (long) checkerradiusAddress;
- ALOGV("Classes recovered");
-
- jboolean isCopy;
- const char* stringWhiteBalance =
- env->GetStringUTFChars(whiteBalance, &isCopy);
- ALOGV("White Balance is %s", stringWhiteBalance);
-
- // Adds the gray checker's RGB values to the test handler.
- testHandler->addDataToList(stringWhiteBalance,
- image->getColorChecker(3, 4, 0, 6,
- checkerCenter,
- checkerRadius));
-
- env->ReleaseStringUTFChars(whiteBalance, stringWhiteBalance);
- delete image;
-}
-
-jint Java_com_android_cts_verifier_camera_analyzer_WhiteBalanceTest_processWhiteBalanceTest(
- JNIEnv* env,
- jobject thiz,
- jlong inputHandlerAddress) {
- ALOGV("Processing white balance test");
-
- long handlerAddress = (long) inputHandlerAddress;
- WhiteBalanceTest *testHandler = (WhiteBalanceTest*) handlerAddress;
-
- testHandler->processData();
-
- ALOGV("CCT is %d", testHandler->getCorrelatedColorTemp());
- return testHandler->getCorrelatedColorTemp();
-}
diff --git a/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_WhiteBalanceTest.h b/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_WhiteBalanceTest.h
deleted file mode 100644
index 88cf52e..0000000
--- a/apps/CtsVerifier/jni/cameraanalyzer/com_android_cts_verifier_camera_analyzer_WhiteBalanceTest.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef JNI_CAMERAANALYZER_WHITEBALANCETEST_H
-#define JNI_CAMERAANALYZER_WHITEBALANCETEST_H
-
-#include <jni.h>
-#include <stdio.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-JNIEXPORT jlong JNICALL
-Java_com_android_cts_verifier_camera_analyzer_WhiteBalanceTest_createWhiteBalanceTest(
- JNIEnv* env,
- jobject thiz);
-
-JNIEXPORT void JNICALL
-Java_com_android_cts_verifier_camera_analyzer_WhiteBalanceTest_createWhiteBalanceClass(
- JNIEnv *env,
- jobject thiz,
- jlong inputAddress,
- jlong handlerAddress,
- jlong checkercenterAddress,
- jlong checkerradiusAddress,
- jstring whiteBalance);
-
-JNIEXPORT jint JNICALL
-Java_com_android_cts_verifier_camera_analyzer_WhiteBalanceTest_processWhiteBalanceTest(
- JNIEnv* env,
- jobject thiz,
- jlong handlerAddress);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/apps/CtsVerifier/lib/Android.mk b/apps/CtsVerifier/lib/Android.mk
deleted file mode 100644
index 56a3fa8..0000000
--- a/apps/CtsVerifier/lib/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# Copyright (C) 2011 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-include $(call all-subdir-makefiles)
diff --git a/apps/CtsVerifier/lib/colorchecker/Android.mk b/apps/CtsVerifier/lib/colorchecker/Android.mk
deleted file mode 100644
index 48f1356..0000000
--- a/apps/CtsVerifier/lib/colorchecker/Android.mk
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright (C) 2011 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-#####################
-# Build image analysis library
-
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE := libcolorchecker
-
-LOCAL_SRC_FILES += testingimage.cpp \
- vec3.cpp \
- vec2.cpp \
- imagetesthandler.cpp \
- colorcheckertest.cpp \
- exposurecompensationtest.cpp \
- autolocktest.cpp \
- meteringtest.cpp \
- whitebalancetest.cpp
-
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../include/colorchecker
-LOCAL_CXX_STL := libc++
-LOCAL_SHARED_LIBRARIES := \
- libcutils \
- libutils \
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/apps/CtsVerifier/lib/colorchecker/autolocktest.cpp b/apps/CtsVerifier/lib/colorchecker/autolocktest.cpp
deleted file mode 100644
index 6bfa922..0000000
--- a/apps/CtsVerifier/lib/colorchecker/autolocktest.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#define LOG_NDEBUG 0
-
-#define LOG_TAG "AutoLockTest"
-#include <utils/Log.h>
-#include <utils/Timers.h>
-#include <cmath>
-#include <string>
-
-#include "vec2.h"
-#include "vec3.h"
-#include "autolocktest.h"
-
-const float kOverExposure = 230.f;
-const float kEqThreshold = 0.05f;
-// Processes the color checker values and compare the two values from
-// the same individual test.
-void AutoLockTest::processData() {
- ALOGV("Start Processing Auto Lock Test Data!");
-
- int numTests = mCheckerColors.size() / 2;
- mNumPatches = 0;
-
- if (numTests > 0) {
- mNumPatches = mCheckerColors[0].size();
- }
-
- for (int i = 0; i < numTests; ++i) {
- mComparisonResults.push_back(
- IsBrighterThan((&mCheckerColors[i * 2]),
- (&mCheckerColors[i * 2 + 1])));
- mComparisonResults.push_back(
- IsEquivalentTo((&mCheckerColors[i * 2]),
- (&mCheckerColors[i * 2 + 1])));
- }
-}
-
-// Compares whether one array of gray color patches is brighter than
-// another one.
-bool AutoLockTest::IsBrighterThan(
- const std::vector<Vec3f>* colorCheckers1,
- const std::vector<Vec3f>* colorCheckers2) const {
- float meanRatio = 0.f;
- int meanNumCount = 0;
-
- for (int i = 0; i < mNumPatches; ++i) {
- float luminance1 = (*colorCheckers1)[i].convertToLuminance();
- float luminance2 = (*colorCheckers2)[i].convertToLuminance();
-
- // Consider a 5% raise as a considerably large increase.
- if ((luminance1 < kOverExposure) && (luminance2 != 0.f)) {
- meanRatio += luminance1 / luminance2;
- ++meanNumCount;
- }
- }
- meanRatio = meanRatio / meanNumCount;
-
- return (meanRatio > 1 + kEqThreshold);
-}
-
-// Compares whether one array of gray color patches is within a small range
-// of the other one to be considered equivalent.
-bool AutoLockTest::IsEquivalentTo(
- const std::vector<Vec3f>* colorCheckers1,
- const std::vector<Vec3f>* colorCheckers2) const {
- float meanRatio = 0.f;
- int meanNumCount = 0;
-
- for (int i = 0; i < mNumPatches; ++i) {
- float luminance1 = (*colorCheckers1)[i].convertToLuminance();
- float luminance2 = (*colorCheckers2)[i].convertToLuminance();
- ALOGV("Luma_1 and Luma_2 is %f, %f", luminance1, luminance2);
-
- if ((luminance1 < kOverExposure) && (luminance2 < kOverExposure)) {
- meanRatio += luminance2 / luminance1;
- ++meanNumCount;
- }
- }
- meanRatio = meanRatio / meanNumCount;
-
- return ((meanRatio >= 1 - kEqThreshold) && (meanRatio <= 1 + kEqThreshold));
-}
-
-void AutoLockTest::clearData() {
- mCheckerColors.clear();
- mComparisonResults.clear();
-}
diff --git a/apps/CtsVerifier/lib/colorchecker/colorcheckertest.cpp b/apps/CtsVerifier/lib/colorchecker/colorcheckertest.cpp
deleted file mode 100644
index ef7d2c6..0000000
--- a/apps/CtsVerifier/lib/colorchecker/colorcheckertest.cpp
+++ /dev/null
@@ -1,979 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#define LOG_NDEBUG 0
-
-#define LOG_TAG "ColorCheckerTest"
-#include <utils/Log.h>
-#include <utils/Timers.h>
-#include <cmath>
-#include <string>
-
-#include "vec2.h"
-#include "vec3.h"
-#include "colorcheckertest.h"
-
-const float GAMMA_CORRECTION = 2.2f;
-const float COLOR_ERROR_THRESHOLD = 200.f;
-ColorCheckerTest::~ColorCheckerTest() {
- ALOGV("Deleting color checker test handler");
-
- if (mImage != NULL) {
- delete mImage;
- }
- ALOGV("Image deleted");
-
- int numHorizontalLines = mCandidateColors.size();
- int numVerticalLines = mCandidateColors[0].size();
-
- for (int i = 0; i < numHorizontalLines; ++i) {
- for (int j = 0; j < numVerticalLines; ++j) {
- if (mCandidateColors[i][j] != NULL) {
- delete mCandidateColors[i][j];
- }
- if (mCandidatePositions[i][j] != NULL) {
- delete mCandidatePositions[i][j];
- }
- }
- }
- ALOGV("Candidates deleted!");
-
- for (int i = 0; i < 4; ++i) {
- for (int j = 0; j < 6; ++j) {
- if (mMatchPositions[i][j] != NULL) {
- delete mMatchPositions[i][j];
- }
- if (mReferenceColors[i][j] != NULL) {
- delete mReferenceColors[i][j];
- }
- if (mMatchColors[i][j] != NULL) {
- delete mMatchColors[i][j];
- }
- }
- }
-}
-
-// Adds a new image to the test handler.
-void ColorCheckerTest::addTestingImage(TestingImage* inputImage) {
- if (mImage != NULL) {
- delete mImage;
- }
- mImage = NULL;
- ALOGV("Original image deleted");
- mImage = inputImage;
-
- if ((mImage->getHeight() == getDebugHeight()) &&
- (mImage->getWidth() == getDebugWidth())) {
- copyDebugImage(getDebugHeight(), getDebugWidth(), mImage->getImage());
- }
-}
-
-void ColorCheckerTest::processData() {
- mSuccess = false;
- initializeRefColor();
- edgeDetection();
-}
-
-void ColorCheckerTest::initializeRefColor() {
- mReferenceColors.resize(4, std::vector<Vec3i*>(6, NULL));
- mMatchPositions.resize(4, std::vector<Vec2f*>(6, NULL));
- mMatchColors.resize(4, std::vector<Vec3f*>(6, NULL));
- mMatchRadius.resize(4, std::vector<float>(6, 0.f));
-
- mReferenceColors[0][0]= new Vec3i(115, 82, 68);
- mReferenceColors[0][1]= new Vec3i(194, 150, 130);
- mReferenceColors[0][2]= new Vec3i(98, 122, 157);
- mReferenceColors[0][3]= new Vec3i(87, 108, 67);
- mReferenceColors[0][4]= new Vec3i(133, 128, 177);
- mReferenceColors[0][5]= new Vec3i(103, 189, 170);
- mReferenceColors[1][0]= new Vec3i(214, 126, 44);
- mReferenceColors[1][1]= new Vec3i(80, 91, 166);
- mReferenceColors[1][2]= new Vec3i(193, 90, 99);
- mReferenceColors[1][3]= new Vec3i(94, 60, 108);
- mReferenceColors[1][4]= new Vec3i(157, 188, 64);
- mReferenceColors[1][5]= new Vec3i(224, 163, 46);
- mReferenceColors[2][0]= new Vec3i(56, 61, 150);
- mReferenceColors[2][1]= new Vec3i(70, 148, 73);
- mReferenceColors[2][2]= new Vec3i(175, 54, 60);
- mReferenceColors[2][3]= new Vec3i(231, 199, 31);
- mReferenceColors[2][4]= new Vec3i(187, 86, 149);
- mReferenceColors[2][5]= new Vec3i(8, 133, 161);
- mReferenceColors[3][0]= new Vec3i(243, 243, 242);
- mReferenceColors[3][1]= new Vec3i(200, 200, 200);
- mReferenceColors[3][2]= new Vec3i(160, 160, 160);
- mReferenceColors[3][3]= new Vec3i(122, 122, 121);
- mReferenceColors[3][4]= new Vec3i(85, 85, 85);
- mReferenceColors[3][5]= new Vec3i(52, 52, 52);
-}
-
-void ColorCheckerTest::edgeDetection() {
- int width = mImage->getWidth();
- int height = mImage->getHeight();
-
- bool* edgeMap = new bool[height * width];
- unsigned char* grayImage = new unsigned char[height * width];
-
- // If the image is a color image and can be converted to a luminance layer
- if (mImage->rgbToGrayScale(grayImage)) {
- float* gradientMap = new float[height * width * 2];
-
- // Computes the gradient image on the luminance layer.
- computeGradient(grayImage, gradientMap);
-
- float* gradientMagnitude = new float[height * width];
- int* gradientDirectionInt = new int[height * width];
- float* gradientDirection = new float[height * width];
-
- // Computes the absolute gradient of the image without padding.
- for (int i = 1; i < height - 1; ++i) {
- for (int j = 1; j < width - 1; ++j) {
- gradientMagnitude[i * width + j] =
- sqrt(gradientMap[(i * width + j) * 2] *
- gradientMap[(i * width + j) * 2] +
- gradientMap[(i * width + j ) * 2 + 1] *
- gradientMap[(i * width + j ) * 2 + 1]);
-
- // Computes the gradient direction of the image.
- if (gradientMap[(i * width + j) * 2] == 0 ) {
- // If the vertical gradient is 0, the edge is horizontal
- // Mark the gradient direction as 90 degrees.
- gradientDirectionInt[i * width + j] = 2;
- gradientDirection[i * width + j] = 90.0f;
- } else {
- // Otherwise the atan operation is valid and can decide
- // the gradient direction of the edge.
- float gradient = atan(gradientMap[(i * width + j) * 2 + 1]
- / gradientMap[(i * width + j) * 2])
- / (M_PI / 4);
-
- gradientDirection[i * width + j] = gradient * 45.0f;
-
- // Maps the gradient direction to 4 major directions with
- // 0 mapped to up and 2 mapped to right.
- if (gradient - floor(gradient) > 0.5) {
- gradientDirectionInt[i * width + j] =
- (static_cast<int>(ceil(gradient)) + 4) % 4;
- } else {
- gradientDirectionInt[i * width + j] =
- (static_cast<int>(floor(gradient)) + 4) % 4;
- }
- }
- }
- }
-
- // Compute a boolean map to show whether a pixel is on the edge.
- for (int i = 1; i < height - 1; ++i) {
- for (int j = 1; j < width - 1; ++j) {
- edgeMap[i * width + j] = false;
-
- switch (gradientDirectionInt[i * width + j]) {
- case 0:
- // If the gradient points rightwards, the pixel is
- // on an edge if it has a larger absolute gradient than
- // pixels on its left and right sides.
- if ((gradientMagnitude[i * width + j] >=
- gradientMagnitude[i * width + j + 1]) &&
- (gradientMagnitude[i * width + j] >=
- gradientMagnitude[i * width + j - 1])) {
- edgeMap[i * width + j] = true;
- }
- break;
- case 1:
- // If the gradient points right-downwards, the pixel is
- // on an edge if it has a larger absolute gradient than
- // pixels on its upper left and bottom right sides.
- if ((gradientMagnitude[i * width + j] >=
- gradientMagnitude[(i + 1) * width + j + 1]) &&
- (gradientMagnitude[i * width + j] >=
- gradientMagnitude[(i - 1) * width + j - 1])) {
- edgeMap[i * width + j] = true;
- }
- break;
- case 2:
- // If the gradient points upwards, the pixel is
- // on an edge if it has a larger absolute gradient than
- // pixels on its up and down sides.
- if ((gradientMagnitude[i * width + j] >=
- gradientMagnitude[(i + 1) * width + j]) &&
- (gradientMagnitude[i * width + j] >=
- gradientMagnitude[(i - 1) * width + j])) {
- edgeMap[i * width + j] = true;
- }
- break;
- case 3:
- // If the gradient points right-upwards, the pixel is
- // on an edge if it has a larger absolute gradient than
- // pixels on its bottom left and upper right sides.
- if ((gradientMagnitude[i * width + j] >=
- gradientMagnitude[(i - 1) * width + j + 1]) &&
- (gradientMagnitude[i * width + j] >=
- gradientMagnitude[(i + 1) * width + j - 1])) {
- edgeMap[i * width + j] = true;
- }
- }
-
- }
- }
-
- houghLineDetection(edgeMap, gradientMagnitude, gradientDirection);
-
- // Cleans up
- delete[] gradientMap;
- delete[] gradientDirectionInt;
- delete[] gradientMagnitude;
- delete[] gradientDirection;
-
- } else {
- ALOGE("Not a color image!");
- }
-
- delete[] edgeMap;
- delete[] grayImage;
-}
-
-// Runs the hough voting algorithm to find the grid of the color checker
-// with the edge map, gradient direction and gradient magnitude as inputs.
-void ColorCheckerTest::houghLineDetection(bool* edgeMap,
- float* gradientMagnitude,
- float* gradientDirection) {
- // Constructs a graph for Hough voting. The vertical axis counts the vote
- // for a certain angle. The horizontal axis counts the vote for the distance
- // of a line from the origin of the image.
- int houghHeight = 180;
- int houghWidth = 200;
- int houghCounts[houghHeight][houghWidth];
- int houghSum[houghHeight][houghWidth];
-
- int** houghVote;
- houghVote = new int*[180];
- for (int i = 0; i < 180; ++i) {
- houghVote[i] = new int[200];
- }
-
- for (int i = 0; i < houghHeight; ++i) {
- for (int j = 0; j < houghWidth; ++j) {
- houghCounts[i][j] = 0;
- houghVote[i][j] = 0;
- houghSum[i][j] = 0;
- }
- }
-
- // Vectors to record lines in two orthogonal directions.
- // Each line is represented by its direction and its distance to the origin.
- std::vector<std::vector<int> > verticalLines;
- std::vector<std::vector<int> > horizontalLines;
- float radius;
- int height = mImage->getHeight();
- int width = mImage->getWidth();
-
- // Processes the signicant edge pixels and cast vote for the corresponding
- // edge passing this pixel.
- for (int i = 1; i < height - 1; ++i) {
- for (int j = 1; j < width - 1; ++j) {
- // Sets threashold for the gradient magnitude to discount noises
- if (edgeMap[i * width + j] &&
- (gradientMagnitude[i * width + j] > 15)) {
- int shiftedAngle;
-
- // Shifts angles for 45 degrees so the vertical and horizontal
- // direction is mapped to 45 and 135 degrees to avoid padding.
- // This uses the assumption that the color checker is placed
- // roughly parallel to the image boarders. So that the edges
- // at the angle of 45 will be rare.
- shiftedAngle = (static_cast<int>(
- -gradientDirection[i * width + j]) + 225 % 180);
- float shiftedAngleRad = static_cast<float>(shiftedAngle)
- * M_PI / 180.0f;
-
- // Computes the distance of the line from the origin.
- float a, b;
- a = static_cast<float>(i - j) / sqrt(2.0f);
- b = static_cast<float>(i + j) / sqrt(2.0f);
- radius = a * sin(shiftedAngleRad) - b * cos(shiftedAngleRad);
-
- // Adds one vote for the line. The line's angle is shifted by
- // 45 degrees to avoid avoid padding for the vertical lines,
- // which is more common than diagonal lines. The line's
- // distance is mapped to [0, 200] from [-200, 200].
- ++houghCounts[shiftedAngle][static_cast<int>((radius / 2.0f) +
- 100.0f)];
-
- drawPoint(i, j, Vec3i(255, 255, 255));
- }
- }
- }
-
- int houghAngleSum[houghHeight];
- int primaryVerticalAngle, primaryHorizontalAngle;
- int max1 = 0;
- int max2 = 0;
-
- // Looking for the two primary angles of the lines.
- for (int i = 5; i < houghHeight - 5; ++i) {
- houghAngleSum[i] = 0;
- for (int j = 0; j < houghWidth; ++j) {
- for (int l = -5; l <= 5; ++l) {
- houghSum[i][j] += houghCounts[i + l][j];
- }
- houghAngleSum[i] += houghSum[i][j];
- }
-
- if ((i < houghHeight / 2) && (houghAngleSum[i] > max1)) {
- max1 = houghAngleSum[i];
- primaryVerticalAngle = i;
- } else if ((i > houghHeight / 2) && (houghAngleSum[i] > max2)) {
- max2 = houghAngleSum[i];
- primaryHorizontalAngle = i;
- }
- }
-
- ALOGV("Primary angles are %d, %d",
- primaryVerticalAngle, primaryHorizontalAngle);
-
- int angle;
-
- // For each primary angle, look for the highest voted lines.
- for (int k = 0; k < 2; ++k) {
- if (k == 0) {
- angle = primaryVerticalAngle;
- } else {
- angle = primaryHorizontalAngle;
- }
-
- std::vector<int> line(2);
- for (int j = 2; j < houghWidth - 2; ++j) {
- houghVote[angle][j] = houghSum[angle][j];
- houghSum[angle][j] = 0;
- }
-
- // For each radius, average the vote with nearby ones.
- for (int j = 2; j < houghWidth - 2; ++j) {
- for (int m = -2; m <= 2; ++m) {
- houghSum[angle][j] += houghVote[angle][j + m];
- }
- }
-
- bool isCandidate[houghWidth];
-
- // Find whether a lines is a candidate by rejecting the ones that have
- // lower vote than others in the neighborhood.
- for (int j = 2; j < houghWidth - 2; ++j) {
- isCandidate[j] = true;
- for (int m = -2; ((isCandidate[j]) && (m <= 2)); ++m) {
- if ((houghSum[angle][j] < 20) ||
- (houghSum[angle][j] < houghSum[angle][j + m])) {
- isCandidate[j] = false;
- }
- }
- }
-
- int iter1 = 0;
- int iter2 = 0;
- int count = 0;
-
- // Finds the lines that are not too close to each other and add to the
- // detected lines.
- while (iter2 < houghWidth) {
- while ((!isCandidate[iter2]) && (iter2 < houghWidth)) {
- ++iter2;
- }
- if ((isCandidate[iter2]) && (iter2 - iter1 < 5)) {
- iter1 = (iter2 + iter1) / 2;
- ++iter2;
- } else {
- line[0] = angle;
- line[1] = (iter1 - 100) * 2;
- if (iter1 != 0) {
- if (k == 0) {
- verticalLines.push_back(line);
- Vec3i color(verticalLines.size() * 20, 0, 0);
- drawLine(line[0], line[1], color);
- } else {
- horizontalLines.push_back(line);
- Vec3i color(0, horizontalLines.size() * 20, 0);
- drawLine(line[0], line[1], color);
- }
- }
- iter1 = iter2;
- ++iter2;
- ALOGV("pushing back line %d %d", line[0], line[1]);
- }
- }
- }
-
- ALOGV("Numbers of lines in each direction is %d, %d",
- verticalLines.size(), horizontalLines.size());
-
- for (int i = 0; i < 180; ++i) {
- delete[] houghVote[i];
- }
- delete[] houghVote;
-
- findCheckerBoards(verticalLines, horizontalLines);
-}
-
-// Computes the gradient in both x and y direction of a layer
-void ColorCheckerTest::computeGradient(unsigned char* layer,
- float* gradientMap) {
- int width = mImage->getWidth();
- int height = mImage->getHeight();
-
- // Computes the gradient in the whole image except the image boarders.
- for (int i = 1; i < height - 1; ++i) {
- for (int j = 1; j < width - 1; ++j) {
- gradientMap[(i * width + j) * 2] =
- 0.5f * (layer[i * width + j + 1] -
- layer[i * width + j - 1]);
- gradientMap[(i * width + j) * 2 + 1] =
- 0.5f * (layer[(i + 1) * width + j] -
- layer[(i - 1) * width + j]);
- }
- }
-}
-
-// Tries to find the checker boards with the highest voted lines
-void ColorCheckerTest::findCheckerBoards(
- std::vector<std::vector<int> > verticalLines,
- std::vector<std::vector<int> > horizontalLines) {
- ALOGV("Start looking for Color checker");
-
- int numHorizontalLines = mCandidateColors.size();
- int numVerticalLines;
- if (numHorizontalLines > 0) {
- numVerticalLines = mCandidateColors[0].size();
- for (int i = 0; i < numHorizontalLines; ++i) {
- for (int j = 0; j < numVerticalLines; ++j) {
- if (mCandidateColors[i][j] != NULL) {
- delete mCandidateColors[i][j];
- }
- if (mCandidatePositions[i][j] != NULL) {
- delete mCandidatePositions[i][j];
- }
- }
- mCandidateColors[i].clear();
- mCandidatePositions[i].clear();
- }
- }
- mCandidateColors.clear();
- mCandidatePositions.clear();
-
- ALOGV("Candidates deleted!");
-
- numVerticalLines = verticalLines.size();
- numHorizontalLines = horizontalLines.size();
- Vec2f pointUpperLeft;
- Vec2f pointBottomRight;
-
- mCandidateColors.resize(numHorizontalLines - 1);
- mCandidatePositions.resize(numHorizontalLines - 1);
-
- for (int i = numVerticalLines - 1; i >= 1; --i) {
- for (int j = 0; j < numHorizontalLines - 1; ++j) {
- // Finds the upper left and bottom right corner of each rectangle
- // formed by two neighboring highest voted lines.
- pointUpperLeft = findCrossing(verticalLines[i], horizontalLines[j]);
- pointBottomRight = findCrossing(verticalLines[i - 1],
- horizontalLines[j + 1]);
-
- Vec3i* color = new Vec3i();
- Vec2f* pointCenter = new Vec2f();
- // Verifies if they are separated by a reasonable distance.
- if (verifyPointPair(pointUpperLeft, pointBottomRight,
- pointCenter, color)) {
- mCandidatePositions[j].push_back(pointCenter);
- mCandidateColors[j].push_back(color);
- ALOGV("Color at (%d, %d) is (%d, %d, %d)", j, i,color->r(), color->g(), color->b());
-
- } else {
- mCandidatePositions[j].push_back(NULL);
- mCandidateColors[j].push_back(NULL);
- delete color;
- delete pointCenter;
- }
- }
- }
-
- ALOGV("Candidates Number (%d, %d)", mCandidateColors.size(), mCandidateColors[0].size());
- // Verifies whether the current line candidates form a valid color checker.
- verifyColorGrid();
-}
-
-// Returns the corssing point of two lines given the lines.
-Vec2f ColorCheckerTest::findCrossing(std::vector<int> line1,
- std::vector<int> line2) {
- Vec2f crossingPoint;
- float r1 = static_cast<float>(line1[1]);
- float r2 = static_cast<float>(line2[1]);
- float ang1, ang2;
- float y1, y2;
-
- ang1 = static_cast<float>(line1[0]) / 180.0f * M_PI;
- ang2 = static_cast<float>(line2[0]) / 180.0f * M_PI;
-
- float x, y;
- x = (r1 * cos(ang2) - r2 * cos(ang1)) / sin(ang1 - ang2);
- y = (r1 * sin(ang2) - r2 * sin(ang1)) / sin(ang1 - ang2);
-
- crossingPoint.set((x + y) / sqrt(2.0), (y - x) / sqrt(2.0));
-
- //ALOGV("Crosspoint at (%f, %f)", crossingPoint.x(), crossingPoint.y());
- return crossingPoint;
-}
-
-// Verifies whether two opposite corners on a quadrilateral actually can be
-// the two corners of a color checker.
-bool ColorCheckerTest::verifyPointPair(Vec2f pointUpperLeft,
- Vec2f pointBottomRight,
- Vec2f* pointCenter,
- Vec3i* color) {
- bool success = true;
-
- /** 5 and 30 are the threshold tuned for resolution 640*480*/
- if ((pointUpperLeft.x() < 0) ||
- (pointUpperLeft.x() >= mImage->getHeight()) ||
- (pointUpperLeft.y() < 0) ||
- (pointUpperLeft.y() >= mImage->getWidth()) ||
- (pointBottomRight.x() < 0) ||
- (pointBottomRight.x() >= mImage->getHeight()) ||
- (pointBottomRight.y() < 0) ||
- (pointBottomRight.y() >= mImage->getWidth()) ||
- (std::abs(pointUpperLeft.x() - pointBottomRight.x()) <= 5) ||
- (std::abs(pointUpperLeft.y() - pointBottomRight.y()) <= 5) ||
- (std::abs(pointUpperLeft.x() - pointBottomRight.x()) >= 30) ||
- (std::abs(pointUpperLeft.y() - pointBottomRight.y()) >= 30)) {
-
- // If any of the quadrilateral corners are out of the image or if
- // the distance between them are too large or too big, the quadrilateral
- // could not be one of the checkers
- success = false;
- } else {
- // Find the checker center if the corners of the rectangle meet criteria
- pointCenter->set((pointUpperLeft.x() + pointBottomRight.x()) / 2.0f,
- (pointUpperLeft.y() + pointBottomRight.y()) / 2.0f);
- color->set(mImage->getPixelValue(*pointCenter).r(),
- mImage->getPixelValue(*pointCenter).g(),
- mImage->getPixelValue(*pointCenter).b());
- ALOGV("Color at (%f, %f) is (%d, %d, %d)", pointCenter->x(), pointCenter->y(),color->r(), color->g(), color->b());
- }
- return success;
-}
-
-// Verifies the color checker centers and finds the match between the detected
-// color checker and the reference MacBeth color checker
-void ColorCheckerTest::verifyColorGrid() {
- ALOGV("Start looking for Color Grid");
- int numHorizontalLines = mCandidateColors.size();
- int numVerticalLines = mCandidateColors[0].size();
- bool success = false;
-
- // Computes the standard deviation of one row/column of the proposed color
- // checker. Discards the row/column if the std is below a threshold.
- for (int i = 0; i < numHorizontalLines; ++i) {
- Vec3f meanColor(0.f, 0.f, 0.f);
- int numNonZero = 0;
-
- for (int j = 0; j < numVerticalLines; ++j) {
- if (mCandidateColors[i][j] != NULL) {
- ALOGV("candidate color (%d, %d) is (%d, %d, %d)", i, j, mCandidateColors[i][j]->r(), mCandidateColors[i][j]->g(), mCandidateColors[i][j]->b());
-
- meanColor = meanColor + (*mCandidateColors[i][j]);
- ++numNonZero;
- }
- }
- if (numNonZero > 0) {
- meanColor = meanColor / numNonZero;
- }
- ALOGV("Mean color for vertical direction computed!");
-
- float std = 0;
- for (int j = 0; j < numVerticalLines; ++j) {
- if (mCandidateColors[i][j] != NULL) {
- std += mCandidateColors[i][j]->squareDistance<float>(meanColor);
- }
- }
- if (numNonZero > 0) {
- std = sqrt(std / (3 * numNonZero));
- }
- ALOGV("st. deviation for the %d dir1 is %d", i, static_cast<int>(std));
-
- if ((std <= 30) && (numNonZero > 1)) {
- for (int j = 0; j < numVerticalLines; ++j) {
- if (mCandidateColors[i][j] != NULL) {
- delete mCandidateColors[i][j];
- mCandidateColors[i][j] = NULL;
- }
- }
- }
- }
-
- // Discards the column/row of the color checker if the std is below a
- // threshold.
- for (int j = 0; j < numVerticalLines; ++j) {
- Vec3f meanColor(0.f, 0.f, 0.f);
- int numNonZero = 0;
-
- for (int i = 0; i < numHorizontalLines; ++i) {
- if (mCandidateColors[i][j] != NULL) {
- meanColor = meanColor + (*mCandidateColors[i][j]);
- ++numNonZero;
- }
- }
- if (numNonZero > 0) {
- meanColor = meanColor / numNonZero;
- }
-
- float std = 0;
- for (int i = 0; i < numHorizontalLines; ++i) {
- if (mCandidateColors[i][j] != NULL) {
- std += mCandidateColors[i][j]->squareDistance<float>(meanColor);
- }
- }
- if (numNonZero > 0) {
- std = sqrt(std / (3 * numNonZero));
- }
-
- ALOGV("st. deviation for the %d dir2 is %d", j, static_cast<int>(std));
-
- if ((std <= 30) && (numNonZero > 1)) {
- for (int i = 0; i < numHorizontalLines; ++i) {
- if (mCandidateColors[i][j] != NULL) {
- delete mCandidateColors[i][j];
- mCandidateColors[i][j] = NULL;
- }
- }
- }
- }
-
- for (int i = 0; i < numHorizontalLines; ++i) {
- for (int j = 0; j < numVerticalLines; ++j) {
- if (mCandidateColors[i][j] != NULL) {
- ALOGV("position (%d, %d) is at (%f, %f) with color (%d, %d, %d)",
- i, j,
- mCandidatePositions[i][j]->x(),
- mCandidatePositions[i][j]->y(),
- mCandidateColors[i][j]->r(),
- mCandidateColors[i][j]->g(),
- mCandidateColors[i][j]->b());
- } else {
- ALOGV("position (%d, %d) is 0", i, j);
- }
- }
- }
-
- // Finds the match between the detected color checker and the reference
- // MacBeth color checker.
- int rowStart = 0;
- int rowEnd = 0;
-
- // Loops until all dectected color checker has been processed.
- while (!success) {
- int columnStart = 0;
- int columnEnd = 0;
- bool isRowStart = false;
- bool isRowEnd = true;
-
- // Finds the row start of the next block of detected color checkers.
- while ((!isRowStart) && (rowStart < numHorizontalLines)) {
- for (int j = 0; j < numVerticalLines; ++j) {
- if (mCandidateColors[rowStart][j] != NULL) {
- isRowStart = true;
- }
- }
- ++rowStart;
- }
- rowStart--;
- rowEnd = rowStart;
- ALOGV("rowStart is %d", rowStart);
-
- // Finds the row end of the next block of detected color checkers.
- while ((isRowEnd) && (rowEnd < numHorizontalLines)) {
- isRowEnd = false;
- for (int j = 0; j < numVerticalLines; ++j) {
- if (mCandidateColors[rowEnd][j] != NULL) {
- isRowEnd= true;
- }
- }
- if (isRowEnd) {
- ++rowEnd;
- }
- }
- if ((!isRowEnd) && isRowStart) {
- rowEnd--;
- }
- if ((isRowEnd) && (rowEnd == numHorizontalLines)) {
- rowEnd--;
- isRowEnd = false;
- }
- ALOGV("rowEnd is %d", rowEnd);
-
- // Matches color checkers between the start row and the end row.
- bool successVertical = false;
-
- while (!successVertical) {
- bool isColumnEnd = true;
- bool isColumnStart = false;
-
- // Finds the start column of the next block of color checker
- while ((!isColumnStart) && (columnStart < numVerticalLines)) {
- if (mCandidateColors[rowStart][columnStart] != NULL) {
- isColumnStart = true;
- }
- ++columnStart;
- }
- columnStart--;
- columnEnd = columnStart;
-
- // Finds the end column of the next block of color checker
- while ((isColumnEnd) && (columnEnd < numVerticalLines)) {
- isColumnEnd = false;
- if (mCandidateColors[rowStart][columnEnd] != NULL)
- isColumnEnd = true;
- if (isColumnEnd) {
- ++columnEnd;
- }
- }
-
- if ((!isColumnEnd) && isColumnStart) {
- columnEnd--;
- }
- if ((isColumnEnd) && (columnEnd == numVerticalLines)) {
- columnEnd--;
- isColumnEnd = false;
- }
-
- // Finds the best match on the MacBeth reference color checker for
- // the continuous block of detected color checker
- if (isRowStart && (!isRowEnd) &&
- isColumnStart && (!isColumnEnd)) {
- findBestMatch(rowStart, rowEnd, columnStart, columnEnd);
- }
- ALOGV("FindBestMatch for %d, %d, %d, %d", rowStart,
- rowEnd, columnStart, columnEnd);
-
- // If the column search finishes, go out of the loop
- if (columnEnd >= numVerticalLines - 1) {
- successVertical = true;
- } else {
- columnStart = columnEnd + 1;
- }
- }
- ALOGV("Continuing to search for direction 1");
-
- // If the row search finishes, go out of the loop
- if (rowEnd >= numHorizontalLines - 1) {
- success = true;
- } else {
- rowStart = rowEnd + 1;
- }
- }
-
- for (int i = 0; i < 4; ++i) {
- for (int j = 0; j < 6; ++j) {
- if (mMatchPositions[i][j] != NULL) {
- ALOGV("Reference Match position for (%d, %d) is (%f, %f)", i, j,
- mMatchPositions[i][j]->x(), mMatchPositions[i][j]->y());
- }
- }
- }
-
- fillRefColorGrid();
-}
-
-// Finds the best match on the MacBeth color checker for the continuous block of
-// detected color checkers bounded by row i1, row i2 and column j1 and column j2
-// Assumes that the subsample is less than 4*6.
-void ColorCheckerTest::findBestMatch(int i1, int i2, int j1, int j2) {
- int numHorizontalGrid = i2 - i1 + 1;
- int numVerticalGrid = j2 - j1 + 1;
-
- if (((numHorizontalGrid > 1) || (numVerticalGrid > 1)) &&
- (numHorizontalGrid <= 4) && (numVerticalGrid <= 6)) {
- ALOGV("i1, j2, j1, j2 is %d, %d, %d, %d", i1, i2, j1, j2);
- float minError;
- float error = 0.f;
- int horizontalMatch, verticalMatch;
-
- // Finds the match start point where the error is minimized.
- for (int i = 0; i < numHorizontalGrid; ++i) {
- for (int j = 0; j < numVerticalGrid; ++j) {
- if (mCandidateColors[i1 + i][j1 + j] != NULL) {
- error += mCandidateColors[i1 + i][j1 + j]->squareDistance<int>(
- *mReferenceColors[i][j]);
- }
- }
- }
- ALOGV("Error is %f", error);
- minError = error;
- horizontalMatch = 0;
- verticalMatch = 0;
-
- for (int i = 0; i <= 4 - numHorizontalGrid; ++i) {
- for (int j = 0; j <= 6 - numVerticalGrid; ++j) {
- error = 0.f;
-
- for (int id = 0; id < numHorizontalGrid; ++id) {
- for (int jd = 0; jd < numVerticalGrid; ++jd) {
- if (mCandidateColors[i1 + id][j1 + jd] != NULL) {
- error += mCandidateColors[i1 + id][j1 + jd]->
- squareDistance<int>(
- *mReferenceColors[i + id][j + jd]);
- }
- }
- }
-
- if (error < minError) {
- minError = error;
- horizontalMatch = i;
- verticalMatch = j;
- }
- ALOGV("Processed %d, %d and error is %f", i, j, error );
- }
- }
-
- for (int id = 0; id < numHorizontalGrid; ++id) {
- for (int jd = 0; jd < numVerticalGrid; ++jd) {
- if (mCandidatePositions[i1 + id][j1 + jd] != NULL) {
- mMatchPositions[horizontalMatch + id][verticalMatch + jd] =
- new Vec2f(mCandidatePositions[i1 + id][j1 + jd]->x(),
- mCandidatePositions[i1 + id][j1 + jd]->y());
- }
- }
- }
- ALOGV("Grid match starts at %d, %d", horizontalMatch, verticalMatch);
- }
-}
-
-// Finds the boundary of a color checker by its color similarity to the center.
-// Also predicts the location of unmatched checkers.
-void ColorCheckerTest::fillRefColorGrid() {
- int rowStart = 0;
- int columnStart = 0;
- bool foundStart = true;
-
- for (int i = 0; (i < 4) && foundStart; ++i) {
- for (int j = 0; (j < 6) && foundStart; ++j) {
- if (mMatchPositions[i][j] != NULL) {
- rowStart = i;
- columnStart = j;
- foundStart = false;
- }
- }
- }
- ALOGV("First match found at (%d, %d)", rowStart, columnStart);
-
- float rowDistance, columnDistance;
- rowDistance = 0;
- columnDistance = 0;
- int numRowGrids = 0;
- int numColumnGrids = 0;
-
- for (int i = rowStart; i < 4; ++i) {
- for (int j = columnStart; j < 6; ++j) {
- if (mMatchPositions[i][j] != NULL) {
- if (i > rowStart) {
- ++numRowGrids;
- rowDistance += (mMatchPositions[i][j]->x() -
- mMatchPositions[rowStart][columnStart]->x()) /
- static_cast<float>(i - rowStart);
- }
- if (j > columnStart) {
- ++numColumnGrids;
- columnDistance += (mMatchPositions[i][j]->y() -
- mMatchPositions[rowStart][columnStart]->y()) /
- static_cast<float>(j - columnStart);
- }
- }
- }
- }
-
- if ((numRowGrids > 0) && (numColumnGrids > 0)) {
- rowDistance = rowDistance / numRowGrids;
- columnDistance = columnDistance / numColumnGrids;
- ALOGV("delta is %f, %f", rowDistance, columnDistance);
-
- for (int i = 0; i < 4; ++i) {
- for (int j = 0 ; j < 6; ++j) {
- if (mMatchPositions[i][j] == NULL) {
- mMatchPositions[i][j] = new Vec2f(
- mMatchPositions[rowStart][columnStart]->x() +
- (i - rowStart) * rowDistance,
- mMatchPositions[rowStart][columnStart]->y() +
- (j - columnStart) * columnDistance);
- }
- }
- }
- for (int i = 0; i < 4; ++i) {
- for (int j = 0; j < 6; ++j) {
- float radius = 0;
- Vec3i color = mImage->getPixelValue(*mMatchPositions[i][j]);
- Vec3f meanColor(0.f , 0.f, 0.f);
-
- int numPixels = 0;
- for (int ii = static_cast<int>(mMatchPositions[i][j]->x() -
- rowDistance/2);
- ii <= static_cast<int>(mMatchPositions[i][j]->x() +
- rowDistance/2);
- ++ii) {
- for (int jj = static_cast<int>(mMatchPositions[i][j]->y() -
- columnDistance/2);
- jj <= static_cast<int>(mMatchPositions[i][j]->y() +
- columnDistance/2);
- ++jj) {
- if ((ii >= 0) && (ii < mImage->getHeight()) &&
- (jj >= 0) && (jj < mImage->getWidth())) {
- Vec3i pixelColor = mImage->getPixelValue(ii,jj);
- float error = color.squareDistance<int>(pixelColor);
-
- if (error < COLOR_ERROR_THRESHOLD) {
- drawPoint(ii, jj, *mReferenceColors[i][j]);
- meanColor = meanColor + pixelColor;
- numPixels++;
- Vec2i pixelPosition(ii, jj);
-
- if (pixelPosition.squareDistance<float>(
- *mMatchPositions[i][j]) > radius) {
- radius = pixelPosition.squareDistance<float>(
- *mMatchPositions[i][j]);
- }
- }
- }
- }
- }
-
- /** Computes the radius of the checker.
- * The above computed radius is the squared distance to the
- * furthest point with a matching color. To be conservative, we
- * only consider an area with radius half of the above computed
- * value. Since radius is computed as a squared root, the one
- * that will be recorded is 1/4 of the above computed value.
- */
- mMatchRadius[i][j] = radius / 4.f;
- mMatchColors[i][j] = new Vec3f(meanColor / numPixels);
-
- ALOGV("Reference color at (%d, %d) is (%d, %d, %d)", i, j,
- mReferenceColors[i][j]->r(),
- mReferenceColors[i][j]->g(),
- mReferenceColors[i][j]->b());
- ALOGV("Average color at (%d, %d) is (%f, %f, %f)", i, j,
- mMatchColors[i][j]->r(),
- mMatchColors[i][j]->g(),
- mMatchColors[i][j]->b());
- ALOGV("Radius is %f", mMatchRadius[i][j]);
- }
- }
-
- mSuccess = true;
- }
-}
diff --git a/apps/CtsVerifier/lib/colorchecker/exposurecompensationtest.cpp b/apps/CtsVerifier/lib/colorchecker/exposurecompensationtest.cpp
deleted file mode 100644
index da9fc40..0000000
--- a/apps/CtsVerifier/lib/colorchecker/exposurecompensationtest.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#define LOG_NDEBUG 0
-
-#define LOG_TAG "ExposureCompensationTest"
-#include <utils/Log.h>
-#include <utils/Timers.h>
-#include <cmath>
-#include <string>
-#include <stdio.h>
-
-#include "vec2.h"
-#include "vec3.h"
-#include "exposurecompensationtest.h"
-
-const float GAMMA_CORRECTION = 2.2f;
-void ExposureCompensationTest::processData() {
- ALOGV("Start Processing Exposure Compensation Test Data!");
- clearDebugImage();
-
- if (mDebugText != NULL) {
- delete mDebugText;
- mDebugText = NULL;
- }
-
- int numTests = mExposureValues.size();
- int numPatches = mCheckerColors[0].size();
- ALOGV("Processing %d tests with %d patches", numTests, numPatches);
-
- mDebugText = new char[320 * numTests];
- mDebugText[0] = 0;
- char* debugText = new char[50];
-
- Vec3i red(255, 0, 0);
- Vec3i green(0, 255, 0);
- Vec3i blue(0, 0, 255);
-
- float minExposure = -3.0f;
- float scale = 9.0f;
- for (int i = 0; i < numTests; ++i) {
- snprintf(debugText, 50, "Exposure is %f \n", mExposureValues[i]);
- strcat(mDebugText, debugText);
- for (int j = 0; j < numPatches; ++j) {
- int exposureRed = static_cast<int>((
- log(static_cast<float>(mReferenceColors[j].r()))
- / log(2.0f) * GAMMA_CORRECTION +
- mExposureValues[i] - minExposure) * scale);
- int exposureGreen = static_cast<int>((
- log(static_cast<float>(mReferenceColors[j].g()))
- / log(2.0f) * GAMMA_CORRECTION +
- mExposureValues[i] - minExposure) * scale);
- int exposureBlue = static_cast<int>((
- log(static_cast<float>(mReferenceColors[j].b()))
- / log(2.0f) * GAMMA_CORRECTION +
- mExposureValues[i] - minExposure) * scale);
-
- snprintf(debugText, 50, "%d %f %d %f %d %f \n",
- exposureRed, mCheckerColors[i][j].r(),
- exposureGreen, mCheckerColors[i][j].g(),
- exposureBlue, mCheckerColors[i][j].b());
-
- ALOGV("%s", debugText);
- strcat(mDebugText, debugText);
-
- drawPoint(200 - exposureRed, mCheckerColors[i][j].r(), red);
- drawPoint(200 - exposureGreen, mCheckerColors[i][j].g(), green);
- drawPoint(200 - exposureBlue, mCheckerColors[i][j].b(), blue);
- }
- }
- mExposureValues.clear();
- mCheckerColors.clear();
-}
-
-void ExposureCompensationTest::initializeReferenceColors() {
- mReferenceColors.resize(6);
-
- mReferenceColors[0].set(243, 243, 242);
- mReferenceColors[1].set(200, 200, 200);
- mReferenceColors[2].set(160, 160, 160);
- mReferenceColors[3].set(122, 122, 121);
- mReferenceColors[4].set(85, 85, 85);
- mReferenceColors[5].set(52, 52, 52);
-}
diff --git a/apps/CtsVerifier/lib/colorchecker/imagetesthandler.cpp b/apps/CtsVerifier/lib/colorchecker/imagetesthandler.cpp
deleted file mode 100644
index cc3bca9..0000000
--- a/apps/CtsVerifier/lib/colorchecker/imagetesthandler.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#define LOG_NDEBUG 0
-
-#define LOG_TAG "ImageTestHandler"
-#include <utils/Log.h>
-#include <utils/Timers.h>
-#include <cmath>
-#include <cstring>
-
-#include "vec2.h"
-#include "vec3.h"
-#include "imagetesthandler.h"
-
-void ImageTestHandler::initDebugImage() {
- mDebugOutput = NULL;
-}
-
-// Initializes the debug image with a given height and width.
-void ImageTestHandler::initDebugImage(int debugHeight,
- int debugWidth) {
- mDebugOutput = NULL;
- mDebugOutput = new unsigned char[debugHeight * debugWidth * 4];
- memset(mDebugOutput, 0, debugHeight * debugWidth * 4);
-
- mDebugHeight = debugHeight;
- mDebugWidth = debugWidth;
-}
-
-// Copies an existing image to the debug image.
-void ImageTestHandler::copyDebugImage(int inputHeight, int inputWidth,
- const unsigned char* inputImage) {
- if ((inputHeight == mDebugHeight) && (inputWidth == mDebugWidth)) {
- ALOGV("Copying debug images");
- memcpy(mDebugOutput, inputImage, mDebugHeight * mDebugWidth * 4);
- }
-}
-
-void ImageTestHandler::clearDebugImage() {
- if (mDebugOutput != NULL) {
- delete[] mDebugOutput;
- mDebugOutput = new unsigned char[mDebugHeight * mDebugWidth * 4];
- memset(mDebugOutput, 0, mDebugHeight * mDebugWidth * 4);
- }
-}
-
-
-// Draws a point of a given color.
-void ImageTestHandler::drawPoint(int row, int column, const Vec3i &color) {
- if ((row >= 0) && (column >= 0) &&
- (column < mDebugWidth) && (row < mDebugHeight)) {
- mDebugOutput[(row*mDebugWidth + column) * 4] = color.r();
- mDebugOutput[(row*mDebugWidth + column) * 4+1] = color.g();
- mDebugOutput[(row*mDebugWidth + column) * 4+2] = color.b();
- mDebugOutput[(row*mDebugWidth + column) * 4+3] = 255;
- }
-}
-
-// Draws a point in Vec2 format of a given color.
-void ImageTestHandler::drawPoint(const Vec2i &point, const Vec3i &color) {
- drawPoint((int) point.y(), (int) point.x(), color);
-}
-
-// Draws a line of a given color.
-void ImageTestHandler::drawLine(int angle, int radius, const Vec3i &color) {
- const int r = color.r();
- const int g = color.g();
- const int b = color.b();
- const int a = 255;
-
- int shiftedMin = -113;
- int shiftedMax = 83;
-
- float radiusDouble = static_cast<float>(radius);
-
- float angleRad = static_cast<float>(angle) * M_PI / 180.0;
-
- //ALOGV("draw line for (%d, %d)", angle, radius);
- for (int i = shiftedMin; i <= shiftedMax; ++i) {
- float j;
-
- assert(angle != 0);
- j = (i - radiusDouble / sin(angleRad)) * tan(angleRad);
- float x = (static_cast<float>(i) + j) / sqrt(2.0);
- float y = (j - static_cast<float>(i)) / sqrt(2.0);
-
- drawPoint(x, y, color);
- }
-}
diff --git a/apps/CtsVerifier/lib/colorchecker/meteringtest.cpp b/apps/CtsVerifier/lib/colorchecker/meteringtest.cpp
deleted file mode 100644
index 47de5d8..0000000
--- a/apps/CtsVerifier/lib/colorchecker/meteringtest.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#define LOG_NDEBUG 0
-
-#define LOG_TAG "MeteringTest"
-#include <utils/Log.h>
-#include <utils/Timers.h>
-#include <cmath>
-#include <string>
-
-#include "vec2.h"
-#include "vec3.h"
-#include "meteringtest.h"
-
-const float kOverExposure = 230.f;
-const float kEqThreshold = 0.05f;
-// Processes the checker colors stored by comparing the pixel values from the
-// two scenarios in a test.
-void MeteringTest::processData() {
- ALOGV("Start Processing Metering Test Data!");
-
- int numTests = mCheckerColors.size() / 2;
- mNumPatches = 0;
-
- if (numTests > 0) {
- mNumPatches = mCheckerColors[0].size();
- }
-
- for (int i = 0; i < numTests; ++i) {
- mComparisonResults.push_back(
- isEquivalentTo((&mCheckerColors[i * 2]),
- (&mCheckerColors[i * 2 + 1])));
- mComparisonResults.push_back(
- isDarkerThan((&mCheckerColors[i * 2]),
- (&mCheckerColors[i * 2 + 1])));
- }
-}
-
-void MeteringTest::clearData() {
- mComparisonResults.clear();
- mCheckerColors.clear();
-}
-
-// Compares two given arrays of pixel values and decide whether the first one is
-// significantly darker than the second one.
-bool MeteringTest::isDarkerThan(
- const std::vector<Vec3f>* checkerColors1,
- const std::vector<Vec3f>* checkerColors2) const {
- float meanRatio = 0.f;
- int meanNumCount = 0;
-
- for (int i = 0; i < mNumPatches; ++i) {
- float luminance1 = (*checkerColors1)[i].convertToLuminance();
- float luminance2 = (*checkerColors2)[i].convertToLuminance();
-
- // Out of the saturation rage, define 5% as a margin for being
- // significantly brighter.
- if ((luminance2 < kOverExposure) && (luminance1 != 0.f)) {
- meanRatio += luminance2 / luminance1;
- ++meanNumCount;
- }
- }
- meanRatio = meanRatio / meanNumCount;
-
- return (meanRatio > 1 + kEqThreshold);
-}
-
-// Compares the two givn arrays of pixel values and decide whether they are
-// equivalent within an acceptable range.
-bool MeteringTest::isEquivalentTo(
- const std::vector<Vec3f>* checkerColors1,
- const std::vector<Vec3f>* checkerColors2) const {
- float meanRatio = 0.f;
- int meanNumCount = 0;
-
- for (int i = 0; i < mNumPatches; ++i) {
- float luminance1 = (*checkerColors1)[i].convertToLuminance();
- float luminance2 = (*checkerColors2)[i].convertToLuminance();
- ALOGV("Luma_1 and Luma_2 is %f, %f", luminance1, luminance2);
-
- if ((luminance1 < kOverExposure) && (luminance2 < kOverExposure)) {
- meanRatio += luminance2 / luminance1;
- ++meanNumCount;
- }
- }
- meanRatio = meanRatio / meanNumCount;
-
- return ((meanRatio >= 1 - kEqThreshold) && (meanRatio <= 1 + kEqThreshold));
-}
diff --git a/apps/CtsVerifier/lib/colorchecker/testingimage.cpp b/apps/CtsVerifier/lib/colorchecker/testingimage.cpp
deleted file mode 100644
index 28f025f..0000000
--- a/apps/CtsVerifier/lib/colorchecker/testingimage.cpp
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#define LOG_NDEBUG 0
-
-#define LOG_TAG "TestingImage"
-#include <utils/Log.h>
-#include <utils/Timers.h>
-#include <string.h>
-#include <cmath>
-#include <vector>
-#include <assert.h>
-#include "vec3.h"
-
-#include "testingimage.h"
-
-const float GAMMA_CORRECTION = 2.2f;
-
-// Constructs an instance with the given image byte array.
-TestingImage::TestingImage(const unsigned char* inputImage,
- int inputHeight, int inputWidth,
- int inputChannel, int inputRowSpan) {
- mImage = new unsigned char[inputRowSpan * inputHeight];
-
- ALOGV("mImage format created! with size as %d, %d, %d",
- inputRowSpan, inputHeight, inputChannel);
- mWidth = inputWidth;
- mHeight = inputHeight;
- mChannels = inputChannel;
- mRowSpan = mWidth * mChannels;
-
- for (int i = 0; i < mHeight; ++i) {
- for (int j = 0; j < mWidth; ++j) {
- for (int k = 0; k < mChannels; ++k) {
- mImage[i * mRowSpan + j* mChannels + k] =
- inputImage[i * inputRowSpan + j * inputChannel + k];
- }
- }
- }
- ALOGV("mImage converted!");
-}
-
-// Constructs an instance with the given image and resize it to a new size.
-TestingImage::TestingImage(const unsigned char* inputImage,
- int inputHeight, int inputWidth,
- int inputChannel, int inputRowSpan,
- int newHeight, int newWidth) {
- mImage = new unsigned char[newHeight * newWidth * inputChannel];
-
- ALOGV("mImage format created! with size as %d, %d, %d",
- newHeight, newWidth, inputChannel);
- mHeight = newHeight;
- mWidth = newWidth;
- mChannels = inputChannel;
- mRowSpan = mWidth * mChannels;
-
- // Computes how many pixels in the original image corresponds to one pixel
- // in the new image.
- int heightScale = inputHeight / newHeight;
- int widthScale = inputWidth / newWidth;
-
- // Average the corresponding pixels in the original image to compute the
- // pixel value of the new image.
- for (int i = 0; i < mHeight; ++i) {
- for (int j = 0; j < mWidth; ++j) {
- for (int k = 0; k < mChannels; ++k) {
- int pixelValue = 0;
-
- for (int l = 0; l < heightScale; ++l) {
- for (int m = 0; m < widthScale; ++m) {
- pixelValue += inputImage[
- (i * heightScale + l) * inputRowSpan
- + (j * widthScale + m) * inputChannel + k];
- }
- }
- pixelValue = pixelValue / (heightScale * widthScale);
- mImage[i * mRowSpan + j * mChannels + k] =
- (unsigned char) pixelValue;
- }
- }
- }
-}
-
-TestingImage::~TestingImage() {
- if (mImage!=NULL) {
- delete[] mImage;
- }
-}
-
-int TestingImage::getPixelValue(int row, int column, int channel) const {
- assert ((row >= 0) && (row < mHeight));
- assert ((column >= 0) && (column < mWidth));
- assert ((channel >= 0) && (channel < mChannels));
- return (int)mImage[row * mRowSpan + column * mChannels + channel];
-}
-
-Vec3i TestingImage::getPixelValue(int row, int column) const {
- Vec3i current_color(getPixelValue(row, column, 0),
- getPixelValue(row, column, 1),
- getPixelValue(row, column, 2));
- return current_color;
-}
-
-Vec3i TestingImage::getPixelValue(const Vec2i &pixelPosition) const {
- return getPixelValue(pixelPosition.x(), pixelPosition.y());
-}
-
-Vec3i TestingImage::getPixelValue(const Vec2f &pixelPosition) const {
- return getPixelValue(static_cast<int>(pixelPosition.x()),
- static_cast<int>(pixelPosition.y()));
-}
-
-// Returns a vector of the colors in the requested block of color checkers.
-// The vector is formatted by going through the block from left to right and
-// from top to bottom.
-const std::vector<Vec3f>* TestingImage::getColorChecker(
- int rowStart, int rowEnd, int columnStart, int columnEnd,
- const std::vector<std::vector< Vec2f > >* centerAddress,
- const std::vector<std::vector< float > >* radiusAddress) const {
- std::vector<Vec3f>* checkerColors = new std::vector<Vec3f>;
-
- // Average the pixel values of the pixels within the given radius to the
- // given center position.
- for (int i = rowStart; i < rowEnd; ++i) {
- for (int j = columnStart; j < columnEnd; ++j) {
- float radius = sqrt((*radiusAddress)[i][j]);
- Vec2f center((*centerAddress)[i][j].x(),
- (*centerAddress)[i][j].y());
- Vec3f meanColor(0.f, 0.f, 0.f);
- int numPixels = 0;
-
- for (int ii = static_cast<int>(center.x() - radius);
- ii < static_cast<int>(center.x() + radius); ++ii) {
- for (int jj = static_cast<int>(center.y() - radius);
- jj < static_cast<int>(center.y() + radius); ++jj) {
-
- Vec2i pixelPosition(ii,jj);
- if (pixelPosition.squareDistance<float>(center) <
- (*radiusAddress)[i][j]) {
- meanColor = meanColor + getPixelValue(pixelPosition);
- ++numPixels;
- }
- }
- }
- meanColor = meanColor / numPixels;
- checkerColors->push_back(meanColor);
- }
- }
-
- return checkerColors;
-}
-
-bool TestingImage::rgbToGrayScale(unsigned char* grayLayer) const {
- if (mChannels == 4) {
- for (int i = 0; i < mWidth; i++) {
- for (int j = 0; j < mHeight; j++) {
- float redLinear = pow(getPixelValue(j, i, 0),
- GAMMA_CORRECTION);
- float greenLinear = pow(getPixelValue(j,i,1),
- GAMMA_CORRECTION);
- float blueLinear = pow(getPixelValue(j,i,2),
- GAMMA_CORRECTION);
-
- // Computes the luminance value
- grayLayer[j * mWidth + i] =
- (unsigned char)((int)pow((0.299f * redLinear
- + 0.587f * greenLinear
- + 0.114f * blueLinear),
- 1/GAMMA_CORRECTION));
- }
- }
-
- return true;
- } else {
-
- return false;
- }
-}
diff --git a/apps/CtsVerifier/lib/colorchecker/vec3.cpp b/apps/CtsVerifier/lib/colorchecker/vec3.cpp
deleted file mode 100644
index ac16620..0000000
--- a/apps/CtsVerifier/lib/colorchecker/vec3.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#define LOG_NDEBUG 0
-
-#define LOG_TAG "Vec3"
-#include <utils/Log.h>
-#include <utils/Timers.h>
-
-#include "vec3.h"
diff --git a/apps/CtsVerifier/lib/colorchecker/whitebalancetest.cpp b/apps/CtsVerifier/lib/colorchecker/whitebalancetest.cpp
deleted file mode 100644
index 6413a2b..0000000
--- a/apps/CtsVerifier/lib/colorchecker/whitebalancetest.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#define LOG_NDEBUG 0
-
-#define LOG_TAG "WhiteBalanceTest"
-#include <utils/Log.h>
-#include <utils/Timers.h>
-#include <cmath>
-#include <string>
-
-#include "vec2.h"
-#include "vec3.h"
-#include "whitebalancetest.h"
-
-// White point in XYZ color space under 5200k illumination.
-const Vec3f kDaylightWhitePoint(0.9781f, 1.f, 0.9021f);
-
-// Process the data of checker colors collected under different white balance.
-// Assuming the Daylight CCT is set to 5200k, compute the CCT of other white
-// balance modes.
-void WhiteBalanceTest::processData() {
- ALOGV("Start Processing White Balance Test Data!");
-
- int numPatches = mCheckerColors.size();
- ALOGV("Processing %d tests with %d patches", 2, numPatches);
-
- std::vector<Vec3f> xyzColors(numPatches);
- for (int j = 0; j < numPatches; ++j) {
- Vec3f xyzCheckerColor = initializeFromRGB(mCheckerColors[j]);
- xyzColors[j] = xyzCheckerColor;
- ALOGV("XYZ coordinate is %f, %f, %f", xyzCheckerColor.r(),
- xyzCheckerColor.g(), xyzCheckerColor.b());
- }
-
- Vec3f meanScale(0.f, 0.f, 0.f);
-
- if (mMode == "daylight") {
- mXyzColorsDaylight = xyzColors;
- // For testing the auto white balance mode. Compute a CCT that would
- // map the gray checkers to a white point.
- for (int j = 1; j < numPatches; ++j) {
- meanScale = meanScale +
- (mXyzColorsDaylight[j] / kDaylightWhitePoint);
- }
- } else {
- for (int j = 1; j < numPatches; ++j) {
- meanScale = meanScale + (mXyzColorsDaylight[j] / xyzColors[j]);
- }
- }
-
- meanScale = meanScale / (numPatches - 1);
- ALOGV("Scale: %f, %f, %f", meanScale.r(), meanScale.g(), meanScale.b());
-
- Vec3f whitePoint;
- whitePoint = meanScale * kDaylightWhitePoint;
-
- ALOGV("White point is %f, %f, %f", whitePoint.r(),
- whitePoint.g(), whitePoint.b());
-
- mCorrelatedColorTemp = findCorrelatedColorTemp(whitePoint);
- ALOGV("CCT is %d", mCorrelatedColorTemp);
-}
-
-// Given a white point, find the correlated color temperature.
-// Formula taken from the paper "Calculating Correlated Color Temperatures
-// Across the Entire Gamut of Daylight and Skylight Chromaticities" by Hernandez
-// Andres et al. in 1999. The numbers are fitting parameters.
-int WhiteBalanceTest::findCorrelatedColorTemp(const Vec3f &whitePoint) {
- Vec2f chromaOfWhitePoint(
- whitePoint.r() / (whitePoint.r() + whitePoint.g() + whitePoint.b()),
- whitePoint.g() / (whitePoint.r() + whitePoint.g() + whitePoint.b()));
-
- float n = (chromaOfWhitePoint.x() - 0.3366f)
- / (chromaOfWhitePoint.y() - 0.1735f);
- float y = -949.86315f + 6253.80338f * exp(-n / 0.92159f)
- + 28.70599f * exp(-n / 0.20039f) + 0.00004f * exp(-n / 0.07125f);
-
- return static_cast<int>(y);
-}
-
-// Converts a RGB pixel value to XYZ color space.
-Vec3f WhiteBalanceTest::initializeFromRGB(const Vec3f &rgb) {
- float linearRed = convertToLinear(rgb.r());
- float linearGreen = convertToLinear(rgb.g());
- float linearBlue = convertToLinear(rgb.b());
-
- float x = 0.4124f * linearRed + 0.3576f * linearGreen +
- 0.1805f * linearBlue;
- float y = 0.2126f * linearRed + 0.7152f * linearGreen +
- 0.0722f * linearBlue;
- float z = 0.0193f * linearRed + 0.1192f * linearGreen +
- 0.9505f * linearBlue;
-
- return Vec3f(x, y, z);
-}
-
-float WhiteBalanceTest::convertToLinear(float color) {
- float norm = color/ 255.0f;
- float linearColor;
-
- // Convert from sRGB space to linear RGB value
- if (norm > 0.04045f) {
- linearColor = pow(((norm + 0.055f) / 1.055f), 2.4f);
- } else {
- linearColor = norm / 12.92f;
- }
-
- return linearColor;
-}
diff --git a/apps/CtsVerifier/proguard.flags b/apps/CtsVerifier/proguard.flags
index ca4680f..fe7eed8 100644
--- a/apps/CtsVerifier/proguard.flags
+++ b/apps/CtsVerifier/proguard.flags
@@ -19,3 +19,5 @@
-dontwarn android.hardware.Sensor
-dontwarn android.test.AndroidTestRunner
-dontwarn java.util.concurrent.ConcurrentLinkedDeque
+-dontwarn android.cts.util.**
+-dontwarn junit.**
diff --git a/apps/CtsVerifier/res/layout/ca_main.xml b/apps/CtsVerifier/res/layout/ca_main.xml
deleted file mode 100644
index 274430d..0000000
--- a/apps/CtsVerifier/res/layout/ca_main.xml
+++ /dev/null
@@ -1,81 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!-- Copyright (C) 2011 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<android.support.wearable.view.BoxInsetLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <LinearLayout app:layout_box="all"
- android:orientation="vertical" android:layout_width="fill_parent"
- android:layout_height="fill_parent">
-
-
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="horizontal" android:layout_width="fill_parent"
- android:layout_height="wrap_content">
- <!--Button android:id="@+id/focusmodesbutton" android:layout_width="0px"
- android:layout_height="wrap_content" android:text="@string/ca_focus_modes_label"
- android:layout_weight="1" /-->
- <Button android:id="@+id/findcheckerboardbutton" android:layout_width="0px"
- android:layout_height="wrap_content" android:text="@string/ca_find_checkerboard_label"
- android:layout_weight="1" />
-
- <Button android:id="@+id/meteringbutton" android:layout_width="0px"
- android:layout_height="wrap_content" android:text="@string/ca_metering_label"
- android:layout_weight="1" />
-
- <Button android:id="@+id/exposurecompensationbutton" android:layout_width="0px"
- android:layout_height="wrap_content" android:text="@string/ca_exposure_test_label"
- android:layout_weight="1"/>
-
- <Button android:id="@+id/whitebalancebutton" android:layout_width="0px"
- android:layout_height="wrap_content" android:text="@string/ca_wb_test_label"
- android:layout_weight="1" />
-
- <Button android:id="@+id/lockbutton" android:layout_width="0px"
- android:layout_height="wrap_content" android:text="@string/ca_lock_test_label"
- android:layout_weight="1" />
- </LinearLayout>
-
- <LinearLayout android:orientation="horizontal"
- android:layout_width="fill_parent" android:layout_height="0px"
- android:layout_weight="1">
-
- <SurfaceView android:id="@+id/cameraview" android:layout_height="fill_parent"
- android:layout_width="wrap_content"
- android:layout_weight="0" />
-
- <LinearLayout android:orientation="vertical"
- android:layout_width="fill_parent" android:layout_height="match_parent"
- android:layout_weight="1">
-
- <ListView android:id="@+id/ca_tests"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:layout_marginLeft="10px"/>
-
- <ImageView android:id="@+id/resultview" android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:layout_weight="1" />
- </LinearLayout>
-
- </LinearLayout>
-
- <include layout="@layout/pass_fail_buttons" />
-
- </LinearLayout>
-</android.support.wearable.view.BoxInsetLayout>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index b92bca9..e93e693 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -624,18 +624,6 @@
<string name="congratulations">Congratulations!</string>
<string name="no_suid_files">No unauthorized suid files detected!</string>
- <!-- Strings for Camera Analyzer -->
- <string name="camera_analyzer">Camera Analyzer</string>
- <string name="ca_find_checkerboard_label">Find target</string>
- <string name="ca_check_formats_label">Output formats</string>
- <string name="ca_exposure_test_label">Exposure Comp.</string>
- <string name="ca_result_label">Results will be here</string>
- <string name="ca_wb_test_label">White Balance</string>
- <string name="ca_lock_test_label">AE Lock</string>
- <string name="ca_metering_label">Metering Area</string>
- <string name="ca_focus_modes_label">Focus Modes</string>
- <string name="ca_info">This test checks the image quality of the camera of this device. It requires a MacBeth 4x6 color checker. With an ADK board and a lamp connected to it on the Relay 1 port, all tests can be run automatically. Without the ADK board, all the tests except the Auto Exposure Lock Test can be run automatically and the Auto Exposure Lock Test will require users to turn on/off a lamp according to the instruction given. </string>
-
<!-- Strings for Camera Orientation -->
<string name="camera_orientation">Camera Orientation</string>
<string name="co_info">This test verifies the orientation capabilities of
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/analyzer/AutoLockTest.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/analyzer/AutoLockTest.java
deleted file mode 100644
index 9181b29..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/analyzer/AutoLockTest.java
+++ /dev/null
@@ -1,1078 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.verifier.camera.analyzer;
-
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.ImageFormat;
-import android.hardware.Camera;
-import android.hardware.usb.UsbAccessory;
-import android.hardware.usb.UsbManager;
-import android.os.ParcelFileDescriptor;
-import android.util.Log;
-import android.view.SurfaceView;
-import android.widget.ImageView;
-import android.widget.Toast;
-
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Implements a test to verify whether the Auto Exposure Lock functions as
- * described in the API.
- *
- * The test consists three sub-categories. The first set of tests focus on
- * testing whether the auto exposure lock works in various situations.
- * For all tests in this set, the lock is set during the period when the camera
- * preview is open. In this way the lock locks exposure according to the
- * lighting at the moment of setting the lock. The second set of tests focus on
- * testing whether the auto exposure lock works as expected after turning the
- * preview off and on. The lock is set during the period when the camera
- * preview is turned off. The lock is expected to lock an exposure level
- * identical to the one before the preview is turned off. One special case in
- * this category is to set lock before the preview is turned on for the first
- * time.
- */
-public class AutoLockTest extends CameraTests {
-
- private static final String TAG = "AutoLockTest";
- /** USB permission to connect to ADK. */
- private static final String ACTION_USB_PERMISSION = "com.android.cts.verifier.USB_PERMISSION";
- /** Defines a long sleep period.*/
- private static final int SHORT_SLEEP = 2000;
- /** Defines a short sleep period. */
- private static final int LONG_SLEEP = 4000;
-
- /** Test results in text format. */
- private String mDebugText = new String();
- /** Detailed report. */
- private String mResultText = new String();
- /** Thread lock of the camera callbacks. */
- private final Object mProcessingImage = new Object();
- /** Memory address of the native test handler. */
- private long mTestHandler;
- /** Array storing the reference test results. */
- private ArrayList<Boolean> mReferenceCompareResults;
- /** Array storing the reference test scenario logs. */
- private ArrayList<String> mReferenceLogs;
- /** Number of tests so far. */
- private int mTestCount;
-
- /** Usb Manager of the USB connections. */
- private UsbManager mUsbManager;
- /** Intent for getting the permission to access the ADK. */
- private PendingIntent mPermissionIntent;
- /** Boolean to represent whether a permission is gained. */
- private boolean mPermissionRequestPending;
- /** USB accessory pointing to the ADK. */
- private UsbAccessory mAccessory;
- /** File descriptor of the USB communication port. */
- private ParcelFileDescriptor mFileDescriptor;
- /** Output stream to write commands for ADK to. */
- private FileOutputStream mOutputStream;
-
- /** Pointer to the CameraAnalyzerActivity activity. */
- private CameraAnalyzerActivity mActivity;
- /** Boolean to tell whether the accessory is opened. */
- private boolean mSetupReady;
- /** Thread lock for setting up the usb. */
- private final Object mUsbSetup = new Object();
- /** Boolean to indicate whether there is an ADK attached. */
- private boolean mUsingUsb = false;
- /** Test results.*/
- private int[] mTestResults;
- /** Number of tests. */
- private int mNumTests;
- /** Singleton test instance.*/
- private static AutoLockTest singletonTest = null;
-
- /**
- * Receives the notice of whether the connection to ADK is granted or
- * denied.
- */
- private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- Log.v(TAG, String.format("Received USB broadcast with action %s ", action));
-
- if (ACTION_USB_PERMISSION.equals(action)) {
- synchronized (this) {
- UsbAccessory accessory =
- (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
-
- if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
- // Grants the permission to connect to the ADK.
- Log.v(TAG, "Open accessory 3");
- openAccessory(accessory);
- // Overwrites the old camera instsance with the one currently opened
- // by the CameraAnalyzerActivity instance, since the permission
- // dialogue pauses the CameraAnalyzerActivity and forces the camera to
- // be released and reopened when the dialogue disappears.
- mTestCamera = mActivity.getCameraInstance();
- } else {
- // Denies the permission to connect to the ADK.
- Log.d(TAG, "permission denied for accessory " + accessory);
- }
- // Marks that the permission request has been processed.
- mPermissionRequestPending = false;
- }
- } else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
- // Invokes when the USB is detached.
- // Closes the accessory if it has not been closed.
- Log.v(TAG, "Usb device detached");
- mUsingUsb = false;
- UsbAccessory accessory =
- (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
- if (accessory != null && accessory.equals(mAccessory)) {
- closeAccessory();
- }
- }
- }
- };
-
- /**
- * Opens the ADK from USB and attaches the output stream with it.
- *
- * Notifies the tread lock that the USB setup is ready.
- */
- private void openAccessory(UsbAccessory accessory) {
- Log.d(TAG, "openAccessory: " + accessory);
- mFileDescriptor = mUsbManager.openAccessory(accessory);
-
- if (mFileDescriptor != null) {
- mAccessory = accessory;
- FileDescriptor fd = mFileDescriptor.getFileDescriptor();
- mOutputStream = new FileOutputStream(fd);
- Log.d(TAG, "accessory opened");
- } else {
- Log.d(TAG, "accessory open fail");
- }
-
- // Unlocks the thread lock of waiting for the USB to be ready.
- synchronized (mUsbSetup) {
- mSetupReady = true;
- Log.v(TAG, "Setup ready");
- mUsbSetup.notifyAll();
- }
- }
-
- /**
- * Closes the ADK and detaches the output stream from it.
- */
- private void closeAccessory() {
- try {
- if (mFileDescriptor != null) {
- mFileDescriptor.close();
- }
- } catch (IOException e) {
- } finally {
- mFileDescriptor = null;
- mAccessory = null;
- }
- }
-
- /**
- * Constructs the AutoLockTest class, which can execute a series of tests
- * to verify whether the device's Auto Exposure Lock is working properly.
- *
- * The test uses the LED lights on an ADK device as light source to change
- * the lighting condition of the environment. The usb connection to the
- * ADK board is established in the constructor.
- *
- * @param hostActivity pointer to the <code>CameraAnalyzerActivity</code>
- * that instructs the Auto Lock Test
- * @param mCamera pointer to the current camera instance
- */
- private AutoLockTest(){
- super();
- }
-
- public static synchronized AutoLockTest getSingletonTest() {
- if (singletonTest == null) {
- Log.v(TAG, "Creating a new AutoLockTest instance");
- singletonTest = new AutoLockTest();
- singletonTest.initializeTest();
- }
- return singletonTest;
- }
-
- private void initializeTest() {
- // Creates a native test handler with a 120x160 pixel debug output
- mTestHandler = createAutoLockTest();
- mReferenceCompareResults = new ArrayList<Boolean>();
- mReferenceLogs = new ArrayList<String>();
- mNumTests = 4;
- mTestResults = new int[mNumTests];
- for (int i = 0; i < mNumTests; ++i) {
- mTestResults[i] = CameraTests.CAMERA_TEST_NOT_RUN;
- }
- }
-
- public void updateCamera() {}
-
- public void setActivity(CameraAnalyzerActivity hostActivity){
- if (mUsingUsb) {
- closeConnection();
- }
-
- mActivity = hostActivity;
-
- mSetupReady = false;
-
- Log.v(TAG, "Start to test ADK connection");
- // Starts to establish the connection to the ADK board.
- mUsbManager = (UsbManager) mActivity.getSystemService(Context.USB_SERVICE);
- mPermissionIntent = PendingIntent.getBroadcast(mActivity, 0,
- new Intent(ACTION_USB_PERMISSION), 0);
- IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
- filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
- filter.addAction(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);
- mActivity.registerReceiver(mUsbReceiver, filter);
-
- if (mActivity.getLastNonConfigurationInstance() != null) {
- mAccessory = (UsbAccessory) mActivity.getLastNonConfigurationInstance();
- Log.v(TAG, "Open acceossory 1");
- openAccessory(mAccessory);
- }
-
- // Skips the permission listener if the user already grants the ADK
- // permission previously in the app.
- UsbAccessory[] accessories = mUsbManager.getAccessoryList();
- UsbAccessory accessory = (accessories == null ? null : accessories[0]);
- if (accessory != null) {
- if (mUsbManager.hasPermission(accessory)) {
- Log.v(TAG, "Open accessory 2");
- openAccessory(accessory);
- } else {
- synchronized (mUsbReceiver) {
- if (!mPermissionRequestPending) {
- mUsbManager.requestPermission(accessory, mPermissionIntent);
- mPermissionRequestPending = true;
- }
- }
- }
- mUsingUsb = true;
- } else {
- Log.d(TAG, "accessory is null");
- mUsingUsb = false;
- }
-
- }
-
- /**
- * Closes the accessories and unregister the USB listener at the end of
- * tests.
- */
- public void closeConnection() {
- closeAccessory();
- mActivity.unregisterReceiver(mUsbReceiver);
- }
-
- protected void finalize () {
- if (mUsingUsb) {
- closeConnection();
- }
- }
-
- /**
- * Runs the Auto Lock tests. A total of 19 tests have been coded and
- * included. Developers can freely comment out tests not interested. In
- * the release version, all tests will be executed.
- */
- @Override
- public synchronized void run(int index){
- if (index == 0) {
- for (int i = 1; i < mNumTests; ++i) {
- run(i);
- }
- return;
- }
-
- Log.v(TAG, "AutoLockTest thread started!");
-
- if (mUsingUsb && (!mSetupReady)) {
- // USB connection is not set up. Locks thread and wait.
- Log.v(TAG, "Setup not ready, waiting");
- synchronized (mUsbSetup) {
- try{
- Log.v(TAG, "Start waiting for Image");
- mUsbSetup.wait();
- } catch (InterruptedException e) {
- Log.v(TAG, "Callback wait fails!");
- }
- }
- }
-
- // Restarts the camera intance and attach the preview to the corrent
- // UI elements.
- restartCamera();
- startPreview();
-
- mTestCount = 0;
- switch (index) {
- case 1:
- Log.v(TAG, "SP -> TP1 -> SP -> +1 -> Lock -> -1 -> TP2");
- test0();
- Log.v(TAG, "SP -> TP1 -> SP -> Lock -> +1 -> TP2 -> -1");
- test1();
- Log.v(TAG, "SP -> Lock -> +1 -> TP1 -> SP -> -1 -> Lock -> TP2");
- test2();
- Log.v(TAG, "SP -> Lock -> +1 -> TP1 -> SP -> Lock -> -1 -> TP2");
- test3();
- break;
- case 2:
- Log.v(TAG, "SP -> +1 -> TP1 -> -1 -> Lock -> SP -> TP2");
- test4();
- Log.v(TAG, "SP -> +1 -> TP1 -> Lock -> SP -> -1 -> TP2");
- test5();
- Log.v(TAG, "SP -> TP1 -> +1 -> Lock -> SP -> -1 -> TP2");
- test6();
- Log.v(TAG, "SP -> TP1 -> +1 -> Lock -> SP -> TP2");
- test7();
- Log.v(TAG, "SP -> TP1 -> Lock -> SP -> +1 -> TP2");
- test8();
- Log.v(TAG, "SP -> +1 -> Lock -> -1 -> TP1 -> Lock -> SP -> TP2");
- test9();
- Log.v(TAG, "SP -> +1 -> Lock -> TP1 -> -1 -> Lock -> SP -> TP2");
- test10();
- Log.v(TAG, "SP -> Lock -> TP1 -> +1 -> Lock -> SP -> -1 -> TP2");
- test11();
- break;
- case 3:
- Log.v(TAG, "Restart -> Lock -> SP -> TP1 -> Restart -> Lock -> SP -> +1 -> TP2");
- test12();
- Log.v(TAG, "Restart -> Lock -> SP -> +1 -> TP1 -> -1 -> Lock -> SP -> TP2");
- test13();
- Log.v(TAG, "Restart -> Lock -> SP -> +1 -> TP1 -> Lock -> SP -> -1 -> TP2");
- test14();
- Log.v(TAG, "Restart -> Lock -> SP -> TP1 -> +1 -> Lock -> SP -> -1 -> TP2");
- test15();
- Log.v(TAG, "Restart -> Lock -> SP -> TP1 -> +1 -> Lock -> SP -> TP2");
- test16();
- Log.v(TAG, "Restart -> Lock -> SP -> TP1 -> Lock -> SP -> +1 -> TP2");
- test17();
- Log.v(TAG, "Restart -> Lock -> SP -> TP1 -> Lock -> SP -> TP2");
- test18();
- break;
- default:
- break;
- }
-
- releaseLock();
-
- Log.v(TAG, "Ready to process data");
- boolean[] testCompareResults = new boolean[2 * mTestCount];
-
- // Processes the data stored in the native test handler instance.
- // Stores the test results into a boolean array.
- processAutoLockTest(mTestHandler, testCompareResults);
-
- // Prepares the test result text output with the booelan result array.
- prepareDebugText(testCompareResults, index);
- mReferenceCompareResults.clear();
- mReferenceLogs.clear();
- }
-
- /**
- * Compares two images taken under the same lighting, Image 1 without AE
- * lock and Image 2 with AE locked under a bright light. Image 1 is
- * expected to be brighter than Image 2.
- * Tests whether AE lock works compared to no AE lock.
- */
- private void test0() {
- releaseLock();
- takePicture();
- startPreview();
- turnOnLight();
- setLock();
- turnOffLight();
- takePicture();
- startPreview();
- releaseLock();
- mReferenceCompareResults.add(true);
- mReferenceCompareResults.add(false);
- mReferenceLogs.add("Same lighting condition with one different lock");
- ++mTestCount;
- }
-
- /**
- * Compares two images taken under different lighting, Image 1 without AE
- * lock and Image 2 with with AE locked under the same light Image 1 is
- * taken. Image 2 is taken under a bright light. Image 1 is expected to be
- * darker than Image 2.
- * Tests whether AE lock works compared to no AE lock.
- */
- private void test1() {
- releaseLock();
- takePicture();
- startPreview();
- setLock();
- turnOnLight();
- takePicture();
- turnOffLight();
- startPreview();
- releaseLock();
- mReferenceCompareResults.add(false);
- mReferenceCompareResults.add(false);
- mReferenceLogs.add("One same lock with different lighting");
- ++mTestCount;
- }
-
- /**
- * Compares two images taken under different light, both with AE locked
- * under the same lighting. Image 1 is taken under a brighter light.
- * Image 1 is expected to be brighter than Image 2.
- * Tests whether AE locks the exposure to the same level in the same
- * lighting condition after preview restarts.
- */
- private void test2() {
- releaseLock();
- setLock();
- turnOnLight();
- takePicture();
- startPreview();
- turnOffLight();
- setLock();
- takePicture();
- startPreview();
- releaseLock();
- mReferenceCompareResults.add(true);
- mReferenceCompareResults.add(false);
- mReferenceLogs.add("Same locking locations with different lighting");
- ++mTestCount;
- }
-
- /**
- * Compares two images taken under different light, Image 1 with AE locked
- * under normal light and Image 2 with AE locked under a bright light.
- * Image 1 is taken under a bright light and Image 2 is taken in the normal
- * lighting. Image 1 is expected to be brighter than Image 2.
- * Tests whether AE lock can adjust to change of lighting conditions.
- */
- private void test3() {
- releaseLock();
- setLock();
- turnOnLight();
- takePicture();
- startPreview();
- setLock();
- turnOffLight();
- takePicture();
- startPreview();
- releaseLock();
- mReferenceCompareResults.add(true);
- mReferenceCompareResults.add(false);
- mReferenceLogs.add("Different locking locations with different lighting");
- ++mTestCount;
- }
-
- /**
- * Compares two images taken under different lighting, Image 1 without
- * AE lock and Image 2 with AE lock set before camera preview resumes.
- * Image 1 is taken under a bright light and the light is turned off before
- * camera preview starts again. Image 1 is expected to be brighter than
- * Image 2.
- * Tests whether setting AE lock between camera preview stops and restarts
- * can retain the exposure level of the previous AE-unlocked photo.
- */
- private void test4() {
- releaseLock();
- turnOnLight();
- takePicture();
- turnOffLight();
- setLock();
- startPreview();
- takePicture();
- startPreview();
- releaseLock();
- mReferenceCompareResults.add(true);
- mReferenceCompareResults.add(false);
- mReferenceLogs.add("Lock after takePicture and light change, before preview");
- ++mTestCount;
- }
-
- /**
- * Compares two images taken under different lighting, Image 1 without
- * AE lock and Image 2 with AE lock set before camera preview resumes.
- * Image 1 is taken under a bright light and the light is turned off after
- * preview restars but before Image 2 is taken. Image 1 is expected to be
- * brighter than Image 2.
- * Tests whether setting AE lock between camera preview stops and restarts
- * can retain the exposure level of the previous AE-unlocked photo.
- */
- private void test5() {
- releaseLock();
- turnOnLight();
- takePicture();
- setLock();
- startPreview();
- turnOffLight();
- takePicture();
- startPreview();
- releaseLock();
- mReferenceCompareResults.add(true);
- mReferenceCompareResults.add(false);
- mReferenceLogs.add("Lock between takePicture and light change, w/o light change");
- ++mTestCount;
- }
-
- private void test6() {
- releaseLock();
- takePicture();
- turnOnLight();
- setLock();
- startPreview();
- turnOffLight();
- takePicture();
- startPreview();
- releaseLock();
- mReferenceCompareResults.add(false);
- mReferenceCompareResults.add(true);
- mReferenceLogs.add("Lock after takePicture and light change, before preview.");
- ++mTestCount;
- }
-
- private void test7() {
- releaseLock();
- takePicture();
- turnOnLight();
- setLock();
- startPreview();
- takePicture();
- startPreview();
- releaseLock();
- turnOffLight();
- mReferenceCompareResults.add(false);
- mReferenceCompareResults.add(false);
- mReferenceLogs.add("Lock after takePicture and light change, before preview.");
- ++mTestCount;
- }
-
- private void test8() {
- releaseLock();
- takePicture();
- setLock();
- startPreview();
- turnOnLight();
- takePicture();
- startPreview();
- releaseLock();
- turnOffLight();
- mReferenceCompareResults.add(false);
- mReferenceCompareResults.add(false);
- mReferenceLogs.add("Lock after takePicture and before startPreview.");
- ++mTestCount;
- }
-
- private void test9() {
- releaseLock();
- turnOnLight();
- setLock();
- turnOffLight();
- takePicture();
- setLock();
- startPreview();
- takePicture();
- releaseLock();
- startPreview();
- mReferenceCompareResults.add(false);
- mReferenceCompareResults.add(true);
- mReferenceLogs.add("Lock after first lock with changing light");
- ++mTestCount;
- }
-
- private void test10() {
- releaseLock();
- turnOnLight();
- setLock();
- takePicture();
- turnOffLight();
- setLock();
- startPreview();
- takePicture();
- releaseLock();
- startPreview();
- mReferenceCompareResults.add(true);
- mReferenceCompareResults.add(false);
- mReferenceLogs.add("Lock after first lock with changing light");
- ++mTestCount;
- }
-
- private void test11() {
- releaseLock();
- setLock();
- takePicture();
- turnOnLight();
- setLock();
- startPreview();
- turnOffLight();
- takePicture();
- releaseLock();
- startPreview();
- mReferenceCompareResults.add(false);
- mReferenceCompareResults.add(true);
- mReferenceLogs.add("Lock after first lock with changing light");
- ++mTestCount;
- }
-
- private void test12() {
- //"Restart -> Lock -> SP -> TP1 -> Restart -> Lock -> SP -> +1 -> TP2"
- restartCamera();
- setLock();
- startPreview();
- takePicture();
- releaseLock();
- restartCamera();
- setLock();
- startPreview();
- turnOnLight();
- takePicture();
- releaseLock();
- turnOffLight();
- startPreview();
- //mTestCamera.release();
- mReferenceCompareResults.add(false);
- mReferenceCompareResults.add(false);
- mReferenceLogs.add("Lock before first preview");
- ++mTestCount;
- }
-
- private void test13() {
- //"Restart -> Lock -> SP -> +1 -> TP1 -> -1 -> Lock -> SP -> TP2"
- restartCamera();
- setLock();
- startPreview();
- turnOnLight();
- takePicture();
- turnOffLight();
- setLock();
- startPreview();
- takePicture();
- releaseLock();
- startPreview();
- mReferenceCompareResults.add(true);
- mReferenceCompareResults.add(false);
- mReferenceLogs.add("Lock after first lock with changing light");
- ++mTestCount;
- }
-
- private void test14() {
- //"Restart -> Lock -> SP -> +1 -> TP1 -> Lock -> SP -> -1 -> TP2"
- restartCamera();
- setLock();
- startPreview();
- turnOnLight();
- takePicture();
- setLock();
- startPreview();
- turnOffLight();
- takePicture();
- releaseLock();
- startPreview();
- mReferenceCompareResults.add(true);
- mReferenceCompareResults.add(false);
- mReferenceLogs.add("Lock after first lock with changing light");
- ++mTestCount;
- }
-
- private void test15() {
- //"Restart -> Lock -> SP -> TP1 -> +1 -> Lock -> SP -> -1 -> TP2"
- restartCamera();
- setLock();
- startPreview();
- takePicture();
- turnOnLight();
- setLock();
- startPreview();
- turnOffLight();
- takePicture();
- releaseLock();
- startPreview();
- mReferenceCompareResults.add(false);
- mReferenceCompareResults.add(true);
- mReferenceLogs.add("Lock after first lock with changing light");
- ++mTestCount;
- }
-
- private void test16() {
- //"Restart -> Lock -> SP -> TP1 -> +1 -> Lock -> SP -> TP2"
- restartCamera();
- setLock();
- startPreview();
- takePicture();
- turnOnLight();
- setLock();
- startPreview();
- takePicture();
- turnOffLight();
- releaseLock();
- startPreview();
- mReferenceCompareResults.add(false);
- mReferenceCompareResults.add(false);
- mReferenceLogs.add("Lock after first lock with changing light");
- ++mTestCount;
- }
-
- private void test17() {
- //"Restart -> Lock -> SP -> TP1 -> Lock -> SP -> +1 -> TP2"
- restartCamera();
- setLock();
- startPreview();
- takePicture();
- setLock();
- startPreview();
- turnOnLight();
- takePicture();
- turnOffLight();
- releaseLock();
- startPreview();
- mReferenceCompareResults.add(false);
- mReferenceCompareResults.add(false);
- mReferenceLogs.add("Lock after first lock with changing light");
- ++mTestCount;
- }
-
- private void test18() {
- //"Restart -> Lock -> SP -> TP1 -> Lock -> SP -> TP2"
- restartCamera();
- setLock();
- startPreview();
- takePicture();
- setLock();
- startPreview();
- takePicture();
- releaseLock();
- startPreview();
- mReferenceCompareResults.add(false);
- mReferenceCompareResults.add(true);
- mReferenceLogs.add("Lock after first lock with changing light");
- ++mTestCount;
- }
-
- /**
- * Restarts the camera by releasing the current instance and get a new
- * instance. Also connects this new camera instance's preview to the proper
- * UI surfaceview.
- */
- private void restartCamera() {
- Log.v(TAG, "Restarting Camera");
-
- mTestCamera.release();
- Log.v(TAG, "Camera released");
-
- try {
- mTestCamera = Camera.open(mActivity.getCameraIdx());
- } catch (RuntimeException e) {
- throw new RuntimeException("Failed to open the camera", e);
- }
-
- Camera.Parameters params = mTestCamera.getParameters();
- params.setPictureFormat(ImageFormat.JPEG);
- params.setPictureSize(640, 480);
- mTestCamera.setParameters(params);
-
- try {
- mTestCamera.setPreviewDisplay(super.getCameraView().getHolder());
- } catch (IOException e) {
- throw new RuntimeException("Unable to connect camera to display: " + e);
- }
- }
-
- /**
- * Starts Camera preview with a delay of 2 seconds to let it adjust to
- * the lighting condition.
- */
- private void startPreview() {
- mTestCamera.startPreview();
- try{
- Log.v(TAG, "Waiting");
- Thread.sleep(2000);
- Log.v(TAG, "END Waiting");
- } catch (InterruptedException e){}
- }
-
- /**
- * Sends command to ADK to turn on all the LED lights to white.
- * Waits for 4 seconds for the camera to adjust to the new lighting.
- */
- private void turnOnLight() {
- Log.v(TAG, "Turn on light");
- if (mUsingUsb) {
- byte[] buffer = new byte[3];
-
- buffer[0] = (byte) 3;
- buffer[1] = (byte) 0;
- buffer[2] = (byte) 1;
- if (mOutputStream != null && buffer[1] != -1) {
- try {
- mOutputStream.write(buffer);
- } catch (IOException e) {
- Log.e(TAG, "write failed", e);
- }
- }
- } else {
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- Toast.makeText(mActivity.getApplicationContext(), "Turn on light!", 4).show();
-
- }
- });
- }
-
- try{
- Log.v(TAG, "Waiting, Please Turn on light");
- Thread.sleep(LONG_SLEEP);
- Log.v(TAG, "END Waiting");
- } catch (InterruptedException e){}
- }
-
- /**
- * Sends command to ADK to turn off all LED lights.
- * Waits for 4 seconds for the camera to adjust to the new lighting.
- */
- private void turnOffLight() {
- Log.v(TAG, "Turn off light");
- if (mUsingUsb) {
- byte[] buffer = new byte[3];
-
- buffer[0] = (byte) 3;
- buffer[1] = (byte) 0;
- buffer[2] = (byte) 0;
- if (mOutputStream != null && buffer[1] != -1) {
- try {
- mOutputStream.write(buffer);
- } catch (IOException e) {
- Log.e(TAG, "write failed", e);
- }
- }
- } else {
- mActivity.runOnUiThread(new Runnable() {
- public void run() {
- Toast.makeText(mActivity.getApplicationContext(), "Turn off light!", 4).show();
-
- }
- });
- }
-
- try{
- Log.v(TAG, "Waiting, Please Turn off light");
- Thread.sleep(LONG_SLEEP);
- Log.v(TAG, "END Waiting");
- } catch (InterruptedException e){}
- }
-
- /**
- * Sets the Auto Exposure Lock.
- * Waits for 2 seonds for the lock to function.
- */
- private void setLock() {
- Camera.Parameters params = mTestCamera.getParameters();
-
- params.setAutoExposureLock(true);
- params.setAutoWhiteBalanceLock(true);
- mTestCamera.setParameters(params);
- try{
- Log.v(TAG, "Waiting to set lock");
- Thread.sleep(2000);
- Log.v(TAG, "END Waiting");
- } catch (InterruptedException e){}
- }
-
- /**
- * Releases the Auto Exposure Lock.
- * Waits for 4 seconds afterwards for the Auto Exposure to be adjusted
- * to the lighting condition.
- */
- private void releaseLock() {
- Camera.Parameters params = mTestCamera.getParameters();
-
- params.setAutoExposureLock(false);
- params.setAutoWhiteBalanceLock(false);
- mTestCamera.setParameters(params);
- try{
- Log.v(TAG, "Waiting to release lock");
- Thread.sleep(LONG_SLEEP);
- Log.v(TAG, "END Waiting");
- } catch (InterruptedException e){}
-
- }
-
- /**
- * Takes a picture and locks thread until the picture callback finishes.
- */
- private void takePicture(){
- mTestCamera.takePicture(null, null, null, mTestJpegListener);
-
- synchronized (mProcessingImage) {
- try{
- Log.v(TAG, "Start waiting for Image");
- // System.gc();
- mProcessingImage.wait();
- } catch (InterruptedException e){
- Log.v(TAG, "Callback wait fails!");
- }
- }
- }
-
- /**
- * Prepare for the result to be shown in the UI. The result for each single
- * test is shown in green if it matches the reference result. It is shown
- * in red otherwise.
- */
- private void prepareDebugText(boolean[] testCompareResults, int index) {
- boolean groupTestPassed = true;
- for (int i = 0; i < mTestCount; ++i) {
- String testLog;
- boolean testPassed = true;
- testLog = mReferenceLogs.get(i);
- mDebugText += (testLog + "<br/>");
-
- if (testCompareResults[i * 2] == mReferenceCompareResults.get(i * 2)) {
- mDebugText += String.format(
- "Picture 1 brighter than Picture 2 is %b \n",
- testCompareResults[i * 2]);
- } else {
- mDebugText += String.format(
- "Picture 1 brighter than Picture 2 is %b \n",
- testCompareResults[i * 2]);
- testPassed = false;
- }
-
- if (testCompareResults[i * 2 + 1] == mReferenceCompareResults.get(i * 2 + 1)) {
- mDebugText += String.format(
- "Picture 1 is equivalent to Picture 2 is %b \n",
- testCompareResults[i * 2 + 1]);
- } else {
- mDebugText += String.format(
- "Picture 1 is equivalent to Picture 2 is %b \n",
- testCompareResults[i * 2 + 1]);
- testPassed = false;
- }
-
- if (testPassed) {
- mDebugText += "Test passed! \n";
- } else {
- mDebugText += "Test failed! \n";
- groupTestPassed = false;
- }
- }
- if (groupTestPassed) {
- mTestResults[index] = CameraTests.CAMERA_TEST_SUCCESS;
- } else {
- mTestResults[index] = CameraTests.CAMERA_TEST_FAILURE;
- }
- }
-
- /**
- * Clears the debug text so that new test results can be added.
- */
- public void clearDebugText() {
- mDebugText = "";
- }
-
- @Override
- public String getDebugText() {
- return mDebugText;
- }
-
- @Override
- public String getResultText() {
- return mDebugText;
- }
-
- @Override
- public String getTestName() {
- return "Auto Exposure Lock test: \n";
- }
-
- @Override
- public String getTestName(int index) {
- switch (index) {
- case 0:
- return "Run all tests";
- case 1:
- return "Compulsory tests";
- case 2:
- return "Recommended tests (preview behavior)";
- case 3:
- return "Optional tests (default lock)";
- default:
- return "";
- }
- }
-
- @Override
- public int getResult(int index) {
- return mTestResults[index];
- }
-
- @Override
- public int getNumTests() {
- return mNumTests;
- }
-
- private Camera.PictureCallback mTestJpegListener = new Camera.PictureCallback() {
- public void onPictureTaken(byte[] data, Camera mCamera) {
- Log.v(TAG, "Shutter pressed down!");
- Bitmap inputImage;
-
- // Decodes the camera input data into Bitmap.
- // Constructs a native image class with the image.
- inputImage = BitmapFactory.decodeByteArray(data, 0, data.length);
- long bufferAddress = findNative(inputImage);
- Log.v(TAG, "findNative method finishes");
-
- // Cleans up memory taken by the Bitmap.
- data = null;
- inputImage.recycle();
- inputImage = null;
- System.gc();
-
- // Passes data from the native image class to the native
- // test handler.
- createAutoLockClass(bufferAddress, mTestHandler,
- getCheckerCenter(), getCheckerRadius());
-
- // Unlocks the thread lock.
- synchronized (mProcessingImage) {
- mProcessingImage.notifyAll();
- }
- }
- };
-
- private native long createAutoLockTest();
-
- private native void createAutoLockClass(long bufferAddress, long handlerAddress,
- long checkerCenterAddress,
- long checkerRadiusAddress);
-
- private native void processAutoLockTest(long handlerAddress, boolean[] testCompareResults);
-
- static {
- System.loadLibrary("cameraanalyzer");
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/analyzer/CameraAnalyzerActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/analyzer/CameraAnalyzerActivity.java
deleted file mode 100644
index 34e8d2d..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/analyzer/CameraAnalyzerActivity.java
+++ /dev/null
@@ -1,500 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.cts.verifier.camera.analyzer;
-
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-import android.app.Activity;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Color;
-import android.graphics.ImageFormat;
-import android.hardware.Camera;
-import android.hardware.Camera.CameraInfo;
-import android.hardware.Camera.Size;
-import android.os.AsyncTask;
-import android.os.Bundle;
-import android.text.Html;
-import android.text.method.ScrollingMovementMethod;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.SurfaceHolder;
-import android.view.SurfaceView;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.ImageView;
-import android.widget.ListView;
-import android.widget.TextView;
-import android.widget.Button;
-import android.os.PowerManager;
-import android.os.PowerManager.WakeLock;
-import android.content.Context;
-
-import java.io.IOException;
-import java.lang.Thread;
-import java.util.List;
-
-/**
- * Controls the UI activities of the camera quality test app. It is created
- * as soon as the app started. Users can launch different quality tests with
- * the buttons in the UI. This class will manage the threading for different
- * tests. Also it will provide debug output or debug text results for tests.
- */
-public class CameraAnalyzerActivity extends PassFailButtons.Activity {
-
- private static final String TAG = "CameraAnalyzer";
- private SurfaceView mCameraView;
- private ImageView mResultView;
- private Button mFindCheckerButton;
- private Button mExposureCompensationButton;
- private Button mWhiteBalanceButton;
- private Button mAutoLockButton;
- private Button mMeteringButton;
- private ListView mTestList;
- private TwoColumnAdapter mAdapter;
-
- private Camera mCamera;
- private int mCameraIdx = 0;
- private boolean mIsCameraOpen = false;
-
- private PowerManager mPowerManager;
- private PowerManager.WakeLock mWakeLock;
-
- private boolean mProcessingPicture = false;
- private boolean mTestInProgress = false;
- private final Object mProcessingTest = new Object();
- private CameraTests mCurrentTest = null;
-
- private long mCheckerCenterAddress;
- private long mCheckerRadiusAddress;
-
- private String mResultReport = "";
- static final String[] TESTS = new String[] {"Test1", "Test2"};
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.ca_main);
- setPassFailButtonClickListeners();
- setInfoResources(R.string.camera_analyzer, R.string.ca_info, -1);
-
- mFindCheckerButton = (Button) findViewById(R.id.findcheckerboardbutton);
- mExposureCompensationButton = (Button) findViewById(R.id.exposurecompensationbutton);
- mWhiteBalanceButton = (Button) findViewById(R.id.whitebalancebutton);
- mAutoLockButton = (Button) findViewById(R.id.lockbutton);
- mMeteringButton = (Button) findViewById(R.id.meteringbutton);
- mCameraView = (SurfaceView) findViewById(R.id.cameraview);
- mResultView = (ImageView) findViewById(R.id.resultview);
- mTestList = (ListView) findViewById(R.id.ca_tests);
- mAdapter = new TwoColumnAdapter(this);
-
- // Initialize the list view.
- initializeAdapter();
- mTestList.setAdapter(mAdapter);
- mTestList.setOnItemClickListener(mListListener);
-
- mFindCheckerButton.setOnClickListener(mFindCheckerListener);
- mExposureCompensationButton.setOnClickListener(mExposureCompensationListener);
- mWhiteBalanceButton.setOnClickListener(mWhiteBalanceListener);
- mAutoLockButton.setOnClickListener(mAutoLockListener);
- mMeteringButton.setOnClickListener(mMeteringListener);
- mCameraView.getHolder().addCallback(mSurfaceChangeListener);
-
- // Disables all test buttons except the color checker test one.
- // They will be enabled after the color checker is located.
- mExposureCompensationButton.setEnabled(false);
- mWhiteBalanceButton.setEnabled(false);
- mAutoLockButton.setEnabled(false);
- mMeteringButton.setEnabled(false);
- }
-
- @Override
- public void onResume() {
- super.onResume();
-
- openCamera(mCameraIdx);
- Camera.Parameters params = mCamera.getParameters();
- params.setPictureFormat(ImageFormat.JPEG);
- params.setPictureSize(640, 480);
- mCamera.setParameters(params);
- Log.v(TAG, "Set resolution to 640*480");
- }
-
- @Override
- public void onPause() {
- super.onPause();
- CameraTests.getCamera().release();
- mIsCameraOpen = false;
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.ca_menu, menu);
-
- Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
- int cameraCount = Camera.getNumberOfCameras();
- for (int camIdx = 0; camIdx < cameraCount; ++camIdx) {
- MenuItem cameraMenuItem = menu.add(0, camIdx, Menu.NONE,
- String.format("Open Camera %d", camIdx));
- }
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (item.getItemId() != mCameraIdx) {
- mCameraIdx = item.getItemId();
- new SwitchCameraTask().execute(mCameraIdx);
- }
- return false;
- }
-
- private class SwitchCameraTask extends AsyncTask<Integer, Void, Void> {
- @Override
- protected Void doInBackground(Integer... camIdx) {
- if (mTestInProgress) {
- synchronized (mProcessingTest) {
- try{
- Log.v(TAG, "Waiting for test to finish");
- mProcessingTest.wait();
- } catch (InterruptedException e){
- Log.v(TAG, "test wait fails!");
- }
- }
- }
-
- openCamera((int)camIdx[0]);
- return null;
- }
- }
-
- private synchronized void openCamera(int camIdx) {
- if (mIsCameraOpen) {
- CameraTests.getCamera().release();
- Log.v(TAG, "Releasing the cameratests camera");
- }
- try {
- mCamera = Camera.open(camIdx);
- mIsCameraOpen = true;
- } catch (RuntimeException e) {
- throw new RuntimeException("Failed to open the camera", e);
- }
-
- try {
- mCamera.setPreviewDisplay(mCameraView.getHolder());
- } catch (IOException e) {
- throw new RuntimeException("Unable to connect camera to display: " + e);
- }
- mCamera.startPreview();
- CameraTests.setCamera(mCamera);
-
- ColorCheckerTest.getSingletonTest().updateCamera();
- WhiteBalanceTest.getSingletonTest().updateCamera();
- ExposureCompensationTest.getSingletonTest().updateCamera();
- MeteringTest.getSingletonTest().updateCamera();
- AutoLockTest.getSingletonTest().updateCamera();
- }
-
- public Camera getCameraInstance() {
- return mCamera;
- }
-
- public void disableAll() {
- mExposureCompensationButton.setEnabled(false);
- mWhiteBalanceButton.setEnabled(false);
- mAutoLockButton.setEnabled(false);
- mMeteringButton.setEnabled(false);
- mFindCheckerButton.setEnabled(false);
- }
-
- public void enableAll() {
- mExposureCompensationButton.setEnabled(true);
- mWhiteBalanceButton.setEnabled(true);
- mAutoLockButton.setEnabled(true);
- mMeteringButton.setEnabled(true);
- mFindCheckerButton.setEnabled(true);
- }
-
- /**
- * Provides an abstraction for the Camera tests. The camera tests will
- * run in the background and the results will be shown in the UI thread
- * after the tests are processed.
- */
- private class DebugOutputProcessingTask extends AsyncTask<Integer,
- Integer,
- Integer> {
- @Override
- protected Integer doInBackground(Integer... cameraTestIndex) {
- Log.v(TAG, "Do in Background started!");
-
- mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
- mWakeLock = mPowerManager.newWakeLock(
- PowerManager.SCREEN_DIM_WAKE_LOCK, "CameraQualityTest");
- mWakeLock.acquire();
-
- mTestInProgress = true;
-
- // Processes the camera tests one by one and publishes their
- // debug output or debug text results after each test is done.
- mCurrentTest.run((int)cameraTestIndex[0]);
- publishProgress(cameraTestIndex);
-
- Log.v(TAG, "Do in Background thread returns!");
- return cameraTestIndex[0];
- }
-
- @Override
- protected void onProgressUpdate(Integer... cameraTestIndex) {
- Log.v(TAG, "Prepare to get debug output!");
-
- // Copies the debug output image or text results to the UI.
- mResultView.setImageBitmap(mCurrentTest.getDebugOutput());
- mResultReport += (mCurrentTest.getTestName() + mCurrentTest.getDebugText());
- mAdapter.notifyDataSetChanged();
- }
-
- @Override
- protected void onPostExecute(Integer cameraTestIndex) {
-
- // If the test is to find the color checker, copy the memory
- // address of the found color checker centers and radius to the
- // CameraTests class' static fields.
- if (mCurrentTest.copyCheckerAddress()) {
- mCheckerCenterAddress = CameraTests.getCheckerCenter();
- mCheckerRadiusAddress = CameraTests.getCheckerRadius();
- }
-
- if (mCurrentTest.copyCheckerAddress() ||
- !mCurrentTest.getTestName().contains("Color Checker")) {
- // Enables the button of all other tests after the color checker
- // is found. Now the user can start all other available tests.
- enableAll();
- }
-
- mWakeLock.release();
- mTestInProgress = false;
- synchronized (mProcessingTest) {
- mProcessingTest.notifyAll();
- }
-
- }
- }
-
- // Creates and runs a new test to find color checker in the captured image.
- // It is invoked when users press the Find color checker button in the UI.
- private View.OnClickListener mFindCheckerListener = new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Log.v(TAG, "Running new color checker finding tests!");
- ColorCheckerTest colorCheckerTest = ColorCheckerTest.getSingletonTest();
-
- mCurrentTest = colorCheckerTest;
- initializeAdapter();
- }
- };
-
- // Creates and runs a new test to test the exposure compensation function.
- // It is invoked when users press the Exposure Compensation Test button
- // in the UI.
- private View.OnClickListener mExposureCompensationListener = new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Log.v(TAG, "Running new exposure compensation tests!");
-
- ExposureCompensationTest exposureCompensationTest =
- ExposureCompensationTest.getSingletonTest();
-
- mCurrentTest = exposureCompensationTest;
- initializeAdapter();
-
- // Loads the memory address of the checker centers and radius
- // from the this class and set the two values for the new test.
- ExposureCompensationTest.setCheckerAddress(mCheckerCenterAddress,
- mCheckerRadiusAddress);
- }
- };
-
- // Creates and runs a new test to test the white balance function.
- // It is invoked when users press the White Balance Test button in the UI.
- private View.OnClickListener mWhiteBalanceListener = new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Log.v(TAG, "Running new white balance tests!");
-
- WhiteBalanceTest whiteBalanceTest = WhiteBalanceTest.getSingletonTest();
-
- mCurrentTest = whiteBalanceTest;
- initializeAdapter();
-
- // Loads the memory address of the checker centers and radius
- // from the this class and set the two values for the new test.
- WhiteBalanceTest.setCheckerAddress(mCheckerCenterAddress, mCheckerRadiusAddress);
- }
- };
-
- // Creates and runs a new test to test the camera metering function.
- // It is invoked when users press the Metering Test button in the UI.
- private View.OnClickListener mMeteringListener = new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Log.v(TAG, "Running new metering tests!");
-
- MeteringTest meteringTest = MeteringTest.getSingletonTest();
-
- mCurrentTest = meteringTest;
- initializeAdapter();
-
- // Loads the memory address of the checker centers and radius
- // from the this class and set the two values for the new test.
- MeteringTest.setCheckerAddress(mCheckerCenterAddress, mCheckerRadiusAddress);
- }
- };
-
- // Creates and runs new tests to test the camera auto exposure lock.
- // It is invoked when users press the AWB and AE Lock Test button
- // in the UI.
- private View.OnClickListener mAutoLockListener = new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Log.v(TAG, "Running New auto exposure/wb lock tests!");
-
- // Loads the memory address of the checker centers and radius
- // from the this class and set the two values for the new test.
- AutoLockTest.setCheckerAddress(mCheckerCenterAddress, mCheckerRadiusAddress);
-
- // Construct all base case test scenearios for the Auto Lock test.
- // Detailed documentation on each test can be found in native code.
- AutoLockTest autoLockTest = AutoLockTest.getSingletonTest();
- autoLockTest.setActivity(CameraAnalyzerActivity.this);
-
- mCurrentTest = autoLockTest;
- initializeAdapter();
-
- }
- };
-
- // Creates a list listner that launches the experiment with the user's click
- private AdapterView.OnItemClickListener mListListener = new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- Log.v(TAG, String.format("Item %d selected!", position));
- if (!mTestInProgress) {
- DebugOutputProcessingTask captureTask = new DebugOutputProcessingTask();
- disableAll();
- captureTask.execute(position);
- }
- }
- };
-
- private SurfaceHolder.Callback mSurfaceChangeListener =
- new SurfaceHolder.Callback() {
-
- // Sets the aspect ratio of the camera preview to 4:3
- @Override
- public void surfaceChanged(SurfaceHolder holder,
- int format,
- int width,
- int height) {
- int x = mCameraView.getWidth();
- int y = mCameraView.getHeight();
- Log.v(TAG, String.format("Measures are %d, %d", x, y));
-
- if ( x > 4.0 / 3.0 * y) {
- android.view.ViewGroup.LayoutParams lp = mCameraView.getLayoutParams();
- lp.height = y;
- lp.width = (int)(4.0 / 3.0 * lp.height);
- Log.v(TAG, String.format("params are %d, %d", lp.width, lp.height));
- mCameraView.setLayoutParams(lp);
- }
-
- try {
- mCamera.setPreviewDisplay(mCameraView.getHolder());
- } catch (IOException e) {
- throw new RuntimeException("Unable to connect camera to display: " + e);
- }
- CameraTests.setCameraView(mCameraView);
- mCamera.startPreview();
- }
-
- @Override
- public void surfaceCreated(SurfaceHolder holder) {}
-
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {}
- };
-
- @Override
- public String getTestDetails() {
- return mResultReport;
- }
-
- class TwoColumnAdapter extends ArrayAdapter<String> {
- TwoColumnAdapter(Context context) {
- super(context, R.layout.ca_row);
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- LayoutInflater inflater = getLayoutInflater();
- View row = inflater.inflate(R.layout.ca_row, parent, false);
- ImageView iconField = (ImageView) row.findViewById(R.id.caTestIcon);
- TextView nameField = (TextView) row.findViewById(R.id.caTestName);
- TextView resultField = (TextView) row.findViewById(R.id.caTestResult);
- if (mCurrentTest != null) {
- nameField.setText(mCurrentTest.getTestName(position));
- int result = mCurrentTest.getResult(position);
- switch (result) {
- case CameraTests.CAMERA_TEST_SUCCESS:
- resultField.setText("Success");
- iconField.setBackgroundColor(Color.rgb(0x99,0xCC,00));
- resultField.setTextColor(Color.rgb(0x99,0xCC,00));
- break;
- case CameraTests.CAMERA_TEST_FAILURE:
- resultField.setText("Failed!");
- iconField.setBackgroundColor(Color.rgb(0xFF,0x44,0x44));
- resultField.setTextColor(Color.rgb(0xFF,0x44,0x44));
- break;
- case CameraTests.CAMERA_TEST_NOT_RUN:
- resultField.setText("Tap to run");
- iconField.setBackgroundColor(Color.rgb(0x00,0x99,0xCC));
- resultField.setTextColor(Color.rgb(0x33,0xB5,0xE5));
- break;
- }
- }
- return row;
- }
- }
-
- private void initializeAdapter() {
- mAdapter.clear();
- if (mCurrentTest != null) {
- for (int i = 0; i < mCurrentTest.getNumTests(); ++i) {
- mAdapter.add(mCurrentTest.getTestName(i));
- }
- }
- }
-
- public int getCameraIdx() {
- return mCameraIdx;
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/analyzer/CameraTests.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/analyzer/CameraTests.java
deleted file mode 100644
index ed99524..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/analyzer/CameraTests.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.verifier.camera.analyzer;
-
-import android.graphics.Bitmap;
-import android.hardware.Camera;
-import android.os.Environment;
-import android.util.Log;
-import android.view.SurfaceView;
-
-import java.io.FileOutputStream;
-import java.io.File;
-import java.lang.Runnable;
-
-/**
- * Provides an abstraction for all camera tests and allows communication
- * between camera test classes with the UI thread. This base class provides
- * functions to contruct and access debug output images. It can access and
- * set the pointer address of checkerboard centers and radius. It also provides
- * native methods to convert an image shot by the camera into a native
- * character array. Another native method it provides is to create a native
- * test handler with desired debug height and width.
- */
-public abstract class CameraTests{
-
- public static final int CAMERA_TEST_NOT_RUN = 0;
- public static final int CAMERA_TEST_SUCCESS = 1;
- public static final int CAMERA_TEST_FAILURE = 2;
-
- private static final String TAG = "CameraTests";
-
- /** Memory address of the color checker centers. */
- private static long sCheckerCenterAddress = 0;
- /** Memory address of the color checker radius. */
- private static long sCheckerRadiusAddress = 0;
- /** The surface view linked with the camera preview. */
- private static SurfaceView sCameraView;
- /** Image debug output. */
- private Bitmap mDebugOutput;
- /** Shared camera instance. */
- protected static Camera mTestCamera = null;
-
- /**
- * Constructs the base CameraTests class.
- */
- public CameraTests() {}
-
- /**
- * Returns debug Bitmap image. In the test to find the color checker,
- * the debug image will be the captured image with a matched color checker
- * overlay on top. In the exposure compensation test, the debug image
- * will be the response curve of the camera.
- * @return A low-resolution Bitmap to be displayed in the UI.
- */
- public Bitmap getDebugOutput() {
- return mDebugOutput;
- }
-
- public String getDebugText() {
- return "";
- }
-
- public abstract String getTestName();
-
- /**
- * Gets the detailed report for CTS output.
- */
- public String getResultText(){
- return "Details not available \n";
- }
-
- /**
- * Provides a polymorphism to start the run() method for all child classes.
- */
- public abstract void run(int index);
-
- public SurfaceView getCameraView() {
- return sCameraView;
- }
-
- public static void setCameraView(SurfaceView cameraView) {
- sCameraView = cameraView;
- }
-
- /**
- * Refreshes the camera instance when the activity opens a new camera.
- */
- public static void setCamera(Camera newCamera) {
- mTestCamera = newCamera;
- }
-
- public static Camera getCamera() {
- return mTestCamera;
- }
-
- /**
- * Sets the memory address of the checker centers and checker radius.
- *
- * @param inputCenterAddress the new memory address of
- * the color checker centers
- * @param inputRadiusAddress the new memory address of
- * the color checker radius
- */
- public static void setCheckerAddress(long inputCenterAddress, long inputRadiusAddress) {
- sCheckerCenterAddress = inputCenterAddress;
- sCheckerRadiusAddress = inputRadiusAddress;
- }
-
- /**
- * Provides polymorphism to indicate whether the checker memory addresses
- * should be copied.
- *
- * @return <code>true</code> if the class invoking the method needs to
- * update the memory address of the color checker
- * centers and radius;
- * <code>false</code> if the class invoking the method does NOT
- * update the memory address of the color checker
- * centers and radius.
- */
- public boolean copyCheckerAddress() {
- return false;
- }
-
- public void cleanUp() {
- }
-
- public static long getCheckerCenter() {
- return sCheckerCenterAddress;
- }
-
- public static long getCheckerRadius() {
- return sCheckerRadiusAddress;
- }
-
- public abstract String getTestName(int index);
-
- public abstract int getResult(int index);
-
- public abstract int getNumTests();
-
- /**
- * Provides a native method to convert the input Bitmap of the captured
- * image into a native character array and constructs a native image class
- * with this character array. This method currently supports conversion
- * of Bitmaps in the formats of RGB_565 and RGB_8888.
- *
- * @param input the input Bitmap, which is decoded from the camrea data.
- *
- * @return the memory address of the native image class which contains
- * the character array.
- */
- public native long findNative(Bitmap input);
-
- /**
- * Provides a native method to create a native image handler class. The
- * native image handler class is the base class for all test classes and
- * contains the debug output as a character array.
- *
- * @param outputHeight the desired height for the debug output
- * @param outputWidth the desired width for the debug output
- *
- * @return the memory address of the native test handler class.
- */
- public native long createImageTestHandler(int outputHeight, int outputWidth);
-
- /**
- * Provides a native method to clean up the memory taken by the handler.
- *
- * @param handlerAddress the memory address of the native test handler,
- * which contains the debug output.
- */
- public native void cleanUpHandler(long handlerAddress);
-
- /**
- * Provides a native method to convert the native debug output from
- * character array back to Bitmap and copy it to the debug output of this
- * class.
- *
- * @param handlerAddress the memory address of the native test handler,
- * which contains the debug output.
- */
- public native void displayHandlerDebugOutput(long handlerAddress);
-
- static {
- System.loadLibrary("cameraanalyzer");
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/analyzer/ColorCheckerTest.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/analyzer/ColorCheckerTest.java
deleted file mode 100644
index ad171b4..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/analyzer/ColorCheckerTest.java
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.verifier.camera.analyzer;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.hardware.Camera;
-import android.util.Log;
-import android.widget.ImageView;
-
-import java.util.List;
-
-/** Locates a Xrite Classic Color Checker grid pattern in an image, stores the
- * center positions and the color checker radius, and provides a function to
- * get the memory address of these two properties.
- *
- * The pattern is a 6x4 grid of square color patches. The detection routine
- * assumes the pattern is placed roughly facing the camera, with the long size
- * roughly horizontal. It also assumes that the grey squares are in the bottom
- * row.
- */
-public class ColorCheckerTest extends CameraTests {
-
- private static final String TAG = "ColorCheckerTest";
-
- /** Memory address of the image class instance that contains the image. */
- private long mClassAddress;
- /** Memory address of the image test class instance. */
- private long mTestHandler;
- /** Thread lock. */
- private final Object mProcessingImage = new Object();
- /** Boolean to tell whether auto focus has succeded.*/
- private boolean mAutoFocusSuccess;
- /** Boolean to tell whether auto focus is supported.*/
- private boolean mAutoFocusEnabled = false;
- /** Singleton instance of the class.*/
- private static ColorCheckerTest singletonTest = null;
-
- private boolean mFindCheckerSuccess = false;
- private boolean mHasRunOnce = false;
-
- /**
- * Constructs a <code>ColorCheckerTest</code> instance with a given
- * Camera pointer.
- */
- private ColorCheckerTest() {
- super();
- }
-
- /**
- * Updates the camera and parameter when the activity switches camera.
- */
- public void updateCamera() {
- Camera.Parameters params = mTestCamera.getParameters();
- List<String> supportedFocusModes = params.getSupportedFocusModes();
-
- // Sets camera focus mode to Auto focus if it is supported.
- if (supportedFocusModes.contains(params.FOCUS_MODE_AUTO)) {
- Log.v(TAG, "Auto focus possible");
- params.setFocusMode(params.FOCUS_MODE_AUTO);
- mTestCamera.setParameters(params);
- mAutoFocusEnabled = true;
- } else {
- mAutoFocusEnabled = false;
- }
- }
-
- public static synchronized ColorCheckerTest getSingletonTest() {
- if (singletonTest == null) {
- Log.v(TAG, "Creating a new ColorCheckerTest instance");
- singletonTest = new ColorCheckerTest();
- singletonTest.initializeTest();
- }
- return singletonTest;
- }
-
- private void initializeTest() {
- // Creates a native test handler with a 120x160 pixel debug output
- mTestHandler = createColorCheckerTest(120, 160);
- }
-
- @Override
- public synchronized void run(int index) {
- Log.v(TAG, "ColorCheckerTest thread started!");
- mAutoFocusSuccess = false;
- mFindCheckerSuccess = false;
- mHasRunOnce = true;
- // Sets camera focus mode to Auto focus if it is supported.
- if (mAutoFocusEnabled) {
- while (!mAutoFocusSuccess) {
- // Starts the auto focus process of the camera.
- mTestCamera.autoFocus(mAutoFocusListener);
-
- // Locks thread until the camera finishes taking picture.
- synchronized (mProcessingImage) {
- try{
- Log.v(TAG, "Start waiting for Image");
- mProcessingImage.wait();
- } catch (InterruptedException e) {
- Log.v(TAG, "Callback wait fails!");
- }
- }
- }
- } else {
- mTestCamera.takePicture(null, null, null, mTestJpegListener);
- synchronized (mProcessingImage) {
- try{
- Log.v(TAG, "Start waiting for Image");
- mProcessingImage.wait();
- } catch (InterruptedException e) {
- Log.v(TAG, "Callback wait fails!");
- }
- }
- }
-
- // Launches the native method to find the color checker in the image.
- mFindCheckerSuccess = processColorCheckerTest(mTestHandler);
- // Displays the debug output from the native test handler instance.
- displayHandlerDebugOutput(mTestHandler);
-
- Log.v(TAG, "Callback has returned!");
- }
-
- private Camera.AutoFocusCallback mAutoFocusListener = new Camera.AutoFocusCallback() {
- public void onAutoFocus(boolean mSuccess, Camera mCamera) {
- if (mSuccess) {
- mAutoFocusSuccess = true;
- Log.v(TAG, "Autofocus success!");
- mCamera.takePicture(null, null, null, mTestJpegListener);
- } else {
- try{
- Log.v(TAG, "Autofocus failed. Please adjust!");
- Thread.sleep(4000);
- Log.v(TAG, "END Waiting");
- } catch (InterruptedException e){}
-
- synchronized (mProcessingImage) {
- mProcessingImage.notifyAll();
- }
- }
- }
- };
-
- private Camera.PictureCallback mTestJpegListener = new Camera.PictureCallback() {
- public void onPictureTaken(byte[] data, Camera mCamera) {
- Log.v(TAG, "Shutter pressed down!");
-
- // Changes the focus mode to fixed to avoid focus shift after
- // auto focus is successful.
- //Camera.Parameters params = mCamera.getParameters();
- //params.setFocusMode(params.FOCUS_MODE_FIXED);
- //mCamera.setParameters(params);
-
- // Decodes the camera data to Bitmap and creates a native image
- // class with the Bitmap.
- Bitmap inputImage;
- inputImage = BitmapFactory.decodeByteArray(data, 0, data.length);
- long bufferAddress = findNative(inputImage);
- Log.v(TAG, "findNative method finishes");
-
- // Cleans up the Bitmap memory space.
- inputImage.recycle();
- data = null;
- inputImage = null;
- System.gc();
-
- // Constructs a test handler class to handle the image.
- createColorCheckerClass(bufferAddress, mTestHandler);
-
- mCamera.startPreview();
-
- // Notifies the thread lock the image capture is done.
- synchronized (mProcessingImage) {
- mProcessingImage.notifyAll();
- }
- }
- };
-
- /**
- * Overrides the base class method and use the memory addresses of the
- * checker centers and radius computed by the native test handler class
- * to update the values stored in the base class.
- *
- * @return <code>true</code> indicating a memory address upload is needed.
- */
- @Override
- public boolean copyCheckerAddress() {
- if (mFindCheckerSuccess) {
- setCheckerAddress(getColorCheckerCenterAdd(mTestHandler),
- getColorCheckerRadiusAdd(mTestHandler));
- return true;
- } else {
- return false;
- }
- }
-
- @Override
- public void cleanUp() {
- cleanUpHandler(mTestHandler);
- }
-
- @Override
- public String getTestName() {
- return "Color Checker test: \n";
- }
-
- @Override
- public String getTestName(int index) {
- return "Find color checker";
- }
-
- @Override
- public int getResult(int index) {
- if (mFindCheckerSuccess) {
- return CameraTests.CAMERA_TEST_SUCCESS;
- } else {
- if (mHasRunOnce) {
- return CameraTests.CAMERA_TEST_FAILURE;
- } else {
- return CameraTests.CAMERA_TEST_NOT_RUN;
- }
- }
- }
-
- @Override
- public int getNumTests() {
- return 1;
- }
-
- /**
- * Gets the memory address of the vector storing the color checker centers
- * from the native test handler instance.
- *
- * @param handlerAddress the memory address of the native test handler
- * instance
- *
- * @return memory address of the native vector storing the color checker
- * centers' coordinates
- */
- private native long getColorCheckerRadiusAdd(long handlerAddress);
-
- /**
- * Gets the memory address of the vector storing the color checker radius
- * from the native test handler instance.
- *
- * @param handlerAddress the memory address of the native test handler
- * instance.
- *
- * @return memory address of the native vector storing the color checker
- * centers' coordinates
- */
- private native long getColorCheckerCenterAdd(long handlerAddress);
-
- /**
- * Creates a native color checker test handler instance.
- *
- * @param outputWidth the desired width for the debug output
- * @param outputHeight the desired height of the debug output
- *
- * @return memory address of the native test handler instance
- */
- private native long createColorCheckerTest(int outputWidth, int outputHeight);
-
- /**
- * Loads a native image class instances and extracts data from it to add
- * to the test handler.
- *
- * @param bufferAddress the memory address of the image class instance
- * @param handlerAddress the memory address of the test handler instance
- */
- private native void createColorCheckerClass(long bufferAddress, long handlerAddress);
-
- /**
- * Processes the data in the native test handler instance. Computes test
- * results with all the data and construct a debug image or debug text
- * outputs.
- *
- * @param handlerAddress the memory address of the test handler instance
- */
- private native boolean processColorCheckerTest(long handlerAddress);
-
- static {
- System.loadLibrary("cameraanalyzer");
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/analyzer/ExposureCompensationTest.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/analyzer/ExposureCompensationTest.java
deleted file mode 100644
index 9a8d9f0..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/analyzer/ExposureCompensationTest.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.verifier.camera.analyzer;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.ImageFormat;
-import android.hardware.Camera;
-import android.util.Log;
-import android.widget.ImageView;
-
-import java.io.FileOutputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.Random;
-
-public class ExposureCompensationTest extends CameraTests {
-
- private static final String TAG = "ExposureCompensationTest";
-
- /** Records the current exposure level. */
- private float mExposureLevel;
- /** Lock for the camera object.*/
- private final Object mProcessingImage = new Object();
- /** Lock for the camera's auto focusing task.*/
- private final Object mAutoFocusing = new Object();
- /** Memory address of the native test handler.*/
- private long mTestHandler;
- /** Test results. */
- private int[] mTestResults;
- /** Number of sub-tests. */
- private int mNumTests;
- /** Camera Parameters. */
- private Camera.Parameters mParams;
- /** Debug results in text. */
- private String mDebugText;
-
- private static ExposureCompensationTest singletonTest = null;
-
- private ExposureCompensationTest(){
- super();
- }
-
- /** Prepares the camera and the related parameters for the test.*/
- public void updateCamera() {
- mParams = mTestCamera.getParameters();
- Log.v(TAG, String.format("Exposure level is from %d to %d",
- mParams.getMinExposureCompensation(),
- mParams.getMaxExposureCompensation()));
- mNumTests = (int) ((float) (mParams.getMaxExposureCompensation() -
- mParams.getMinExposureCompensation())
- * mParams.getExposureCompensationStep());
- mTestResults = new int[mNumTests + 1];
- for (int i = 0; i < mNumTests + 1; ++i) {
- mTestResults[i] = CameraTests.CAMERA_TEST_NOT_RUN;
- }
- }
-
- public static synchronized ExposureCompensationTest getSingletonTest() {
- if (singletonTest == null) {
- Log.v(TAG, "Creating a new ExposureCompensationTest instance");
- singletonTest = new ExposureCompensationTest();
- singletonTest.initializeTest();
- }
- return singletonTest;
- }
-
- private void initializeTest() {
- mDebugText = new String();
- // Creates a native test handler with a 120x160 pixel debug output
- mTestHandler = createExposureCompensationTest(200, 280);
- }
-
- @Override
- public synchronized void run(int index){
- Log.v(TAG, "ExposureCompensationTest thread started!");
-
- int testRangeMin, testRangeMax;
- if (index == 0) {
- testRangeMin = mParams.getMinExposureCompensation();
- testRangeMax = mParams.getMaxExposureCompensation();
- } else {
- testRangeMin = (int) ((float)(index - 1) / mParams.getExposureCompensationStep())
- + mParams.getMinExposureCompensation();
- testRangeMax = (int) ((float)(index) / mParams.getExposureCompensationStep())
- + mParams.getMinExposureCompensation();
- }
-
- /** Checks for each exposure compensation setting within the test range.*/
- for (int i = testRangeMin;
- i <= testRangeMax; i += 1){
- mExposureLevel = i * mParams.getExposureCompensationStep();
- Log.v(TAG, String.format("Current exposure level is %d", i));
- int mCameraExposure;
-
- do{
- mParams.setExposureCompensation(i);
- mTestCamera.setParameters(mParams);
-
- try{
- Log.v(TAG, "Waiting");
- Thread.sleep(4000);
- Log.v(TAG, "END Waiting");
- } catch (InterruptedException e){
- //TODO: error handling.
- }
-
- mParams = mTestCamera.getParameters();
- mCameraExposure = mParams.getExposureCompensation();
- Log.v(TAG, String.format("Camera exposure level is %d", mCameraExposure));
- } while (mCameraExposure != i);
-
- mTestCamera.takePicture(null, null, null, mTestJpegListener);
-
- synchronized (mProcessingImage) {
- try{
- Log.v(TAG, "Start waiting for Image");
- mProcessingImage.wait();
- } catch (InterruptedException e){
- Log.v(TAG, "Callback wait fails!");
- }
- }
- }
-
- mDebugText = processExposureCompensationTest(mTestHandler);
- displayHandlerDebugOutput(mTestHandler);
-
- Log.v(TAG, "Callback has returned!");
- mParams.setExposureCompensation(0);
- mTestCamera.setParameters(mParams);
- }
-
- private Camera.PictureCallback mTestJpegListener = new Camera.PictureCallback() {
- public void onPictureTaken(byte[] data, Camera mCamera) {
- Log.v(TAG, "Shutter pressed down!");
- Log.v(TAG, String.format("Current exposure is %f", mExposureLevel));
-
- Bitmap inputImage;
-
- inputImage = BitmapFactory.decodeByteArray(data, 0, data.length);
- long bufferAddress = findNative(inputImage);
- Log.v(TAG, "findNative method finishes");
-
- inputImage.recycle();
- data = null;
- inputImage = null;
- System.gc();
-
- createExposureCompensationClass(bufferAddress, mTestHandler,
- getCheckerCenter(), getCheckerRadius(),
- mExposureLevel);
- mCamera.startPreview();
-
- synchronized (mProcessingImage) {
- mProcessingImage.notifyAll();
- }
- }
- };
-
- @Override
- public String getTestName(int index) {
- switch (index) {
- case 0:
- return "EC All Range";
- default:
- return String.format("EC %d -> %d", (index - mNumTests / 2 - 1) * 10,
- (index - mNumTests / 2) * 10);
- }
- }
-
- @Override
- public int getResult(int index) {
- return mTestResults[index];
- }
-
- @Override
- public int getNumTests() {
- return mNumTests + 1;
- }
-
- @Override
- public String getTestName() {
- return "Exposure Compensation Test: \n";
- }
-
- @Override
- public String getDebugText() {
- return mDebugText;
- }
-
- private native long createExposureCompensationTest(int outputHeight, int outputWidth);
-
- private native void createExposureCompensationClass(long bufferAddress, long handlerAddress,
- long checkerCenterAddress, long checkerAadiusAddress, float mExposureLevel);
-
- private native String processExposureCompensationTest(long handlerAddress);
-
- static {
- System.loadLibrary("cameraanalyzer");
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/analyzer/MeteringTest.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/analyzer/MeteringTest.java
deleted file mode 100644
index 9ff559f..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/analyzer/MeteringTest.java
+++ /dev/null
@@ -1,685 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.verifier.camera.analyzer;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.ImageFormat;
-import android.graphics.Rect;
-import android.hardware.Camera;
-import android.hardware.Camera.Area;
-import android.util.Log;
-import android.widget.ImageView;
-
-import java.io.FileOutputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-
-/**
- * Implements a test to verify whether the camera metering system works as
- * described in the API.
- *
- * The test consists two sub-categories. The first one has tests with only
- * one metering area defined. The second one has tests with two metering areas
- * defined. For each single sub-test, we use a random number generator to
- * decide where to put some of the metering areas to and how much weight should
- * be assigned to each area. For different tests, we use different ways to
- * define other metering areas and their weight, in order to cover all possible
- * fail cases. The metering areas are contrained to the grey squares in the
- * bottom of the color checker.
- */
-public class MeteringTest extends CameraTests {
-
- private static final String TAG = "MeteringTest";
-
- /** A long wait.*/
- private static final int LONG_SLEEP = 4000;
- /** Debug result in text. */
- private String mDebugText;
- /** Thread lock. */
- private final Object mProcessingImage = new Object();
- /** Memory address of the native test handler. */
- private long mTestHandler;
- /** The maximum number of metering area the device supports. */
- private int mMaxNumMeteringArea;
- /** The metering areas. */
- private List<Camera.Area> mGreyAreas;
- /** The coordinates of the grey squares on the color checker. */
- private int[] mGreyCoordinates = new int[24];
- /** Random number generator. */
- private final Random mRandomGenerator = new Random();
- /** Reference comparison result for tests. */
- private ArrayList<Boolean> mReferenceCompareResults;
- /** Number of tests in the same instance. */
- private int mTestCount;
- /** Reference test logs. */
- private ArrayList<String> mReferenceLogs;
- /** Test result to show. */
- private int[] mTestResults;
- /** Number of tests. */
- private int mNumTests;
- /** Camera Parameters. */
- private Camera.Parameters mParams;
- /** Singleton test instance. */
- private static MeteringTest singletonTest = null;
-
- /** Constructs a <code>MeteringTest</code> instance with the given
- * camera pointer.
- */
- private MeteringTest() {
- super();
- }
-
- public void updateCamera() {
- // Looks up how many metering area the device supports.
- mParams = mTestCamera.getParameters();
- mMaxNumMeteringArea = mParams.getMaxNumMeteringAreas();
- Log.v(TAG, String.format("Maximum number if metering area is %d", mMaxNumMeteringArea));
- if (mMaxNumMeteringArea == 0) {
- mDebugText = "Custom Metering not supported!";
- Log.v(TAG, "Custom Metering not supported");
- }
- }
-
- public static synchronized MeteringTest getSingletonTest() {
- if (singletonTest == null) {
- Log.v(TAG, "Creating a new MeteringTest instance");
- singletonTest = new MeteringTest();
- singletonTest.initializeTest();
- }
- return singletonTest;
- }
-
- private void initializeTest() {
- // Creates a native metering test handler.
- mTestHandler = createMeteringTest();
- mDebugText = new String();
- mReferenceCompareResults = new ArrayList<Boolean>();
- mReferenceLogs = new ArrayList<String>();
- mNumTests = 3;
- mTestResults = new int[mNumTests];
- for (int i = 0; i < mNumTests; ++i) {
- mTestResults[i] = CameraTests.CAMERA_TEST_NOT_RUN;
- }
- }
-
- /**
- * Runs the metering test instance.
- */
- @Override
- public synchronized void run(int index) {
- if (index == 0) {
- run(1);
- run(2);
- return;
- }
- Log.v(TAG, "MeteringTest thread started!");
-
- // Finds the coordinates of the grey squares on the color checker.
- // The coordinate system has (-1000, -1000) on the upper left corner.
- // And (1000, 1000) on the bottom right corner.
- findGreyCoordinates(mGreyCoordinates, getCheckerCenter(), getCheckerRadius());
-
- if (mMaxNumMeteringArea > 0) {
- mTestCount = 0;
- // Runs the metering tests category by category.
- switch (index) {
- case 1:
- runOneAreaTest();
- break;
- case 2:
- if (mMaxNumMeteringArea > 1) {
- runTwoAreasTest();
- }
- break;
- default:
- break;
- }
- }
-
- mParams = mTestCamera.getParameters();
- mParams.setMeteringAreas(null);
- mTestCamera.setParameters(mParams);
-
- boolean[] testCompareResults = new boolean[2 * mTestCount];
-
- // Processes the image data taken so far and stores the test results.
- processMeteringTest(mTestHandler, testCompareResults);
- // Prepares debug output based on the test results.
- prepareDebugText(testCompareResults, index);
-
- mReferenceCompareResults.clear();
- mReferenceLogs.clear();
- }
-
- /**
- * Prepares the test results in HTML text string to show in the UI.
- *
- * If the test result is the same as the reference result, the text will be
- * shown in green. Otherwise it would be shown as red.
- *
- * @param testCompareResults the array storing the comparison results from
- * the data taken by the camera so far.
- */
- private void prepareDebugText(boolean[] testCompareResults, int index) {
- mDebugText = "";
- boolean groupTestPassed = true;
- for (int i = 0; i < mTestCount; ++i) {
- String testLog;
- boolean testPassed = true;
- testLog = mReferenceLogs.get(i);
- mDebugText += (testLog + "<br/>");
-
- if (testCompareResults[i * 2] == mReferenceCompareResults.get(i * 2)) {
- mDebugText += String.format(
- "Picture 1 equivalent to Picture 2 is %b \n",
- testCompareResults[i * 2]);
- } else {
- mDebugText += String.format(
- "Picture 1 equivalent to Picture 2 is %b \n",
- testCompareResults[i * 2]);
- testPassed = false;
- }
-
- if (testCompareResults[i * 2 + 1] == mReferenceCompareResults.get(i * 2 + 1)) {
- mDebugText += String.format(
- "Picture 1 darker than Picture 2 is %b \n",
- testCompareResults[i * 2 + 1]);
- } else {
- mDebugText += String.format(
- "Picture 1 darker than Picture 2 is %b \n",
- testCompareResults[i * 2 + 1]);
- testPassed = false;
- }
-
- if (testPassed) {
- mDebugText += "Test passed! \n";
- } else {
- mDebugText += "Test failed! \n";
- groupTestPassed = false;
- }
- Log.v(TAG, String.format("%s", mDebugText));
- }
-
- if (groupTestPassed) {
- mTestResults[index] = CameraTests.CAMERA_TEST_SUCCESS;
- } else {
- mTestResults[index] = CameraTests.CAMERA_TEST_FAILURE;
- }
-
- }
-
- /**
- * Runs tests to check whether the metering functionalities work properly
- * when one metering area is added.
- */
- private void runOneAreaTest() {
- int weight1;
- int weight2;
- int square1;
- int square2;
-
- Log.v(TAG, "Running one area Test");
-
- // Test case 1: Two images have the same metering area. Image 1 has
- // a diffent weight than Image 2. The result images should be
- // identical.
- // Tests whether weight normalization works.
- square1 = mRandomGenerator.nextInt(6);
- weight1 = mRandomGenerator.nextInt(100) + 1;
- runSingleTest(square1, square1, weight1);
-
- square2 = square1;
- weight2 = mRandomGenerator.nextInt(100) + 901;
- runSingleTest(square2, square2, weight2);
- mReferenceCompareResults.add(true);
- mReferenceCompareResults.add(false);
- Log.v(TAG, String.format("Running test for %d square with weights %d, %d",
- square1, weight1, weight2));
- mReferenceLogs.add(String.format(
- "Running test for %d 1x1 square with weights %d, %d", square1, weight1, weight2));
- ++mTestCount;
-
- // Test case 2: Two images have different metering areas. Image 1 has
- // one of the grey squares as its metering area. Image 2 has a darker
- // grey square as its metering area. The weights for both images are
- // the same. Image 1 is expected to be darker than Image 2.
- // Tests whether metering on uni-brightness patches work.
- square1 = mRandomGenerator.nextInt(5);
- weight1 = mRandomGenerator.nextInt(1000) + 1;
- runSingleTest(square1, square1, weight1);
-
- square2 = mRandomGenerator.nextInt(6 - square1 - 1) + square1 + 1;
- weight2 = weight1;
- runSingleTest(square2, square2, weight2);
- mReferenceCompareResults.add(false);
- mReferenceCompareResults.add(true);
- mReferenceLogs.add(String.format(
- "Running test for %d, %d 1x1 square with weight %d", square1, square2, weight1));
- ++mTestCount;
-
- // Test case 3: Two images have different metering areas. Image one has
- // one of the grey squares as its metering area. Image 2 has a
- // rectangle which contains Image 1's metering area and the neighboring
- // darker grey square. The weights for both tests are the same. Image 1
- // is expected to be darker than Image 2.
- // Tests whether metering on patches with different brightness works.
- square1 = mRandomGenerator.nextInt(5);
- weight1 = mRandomGenerator.nextInt(1000) + 1;
- runSingleTest(square1, square1, weight1);
-
- square2 = square1;
- weight2 = weight1;
- runSingleTest(square2, square2 + 1, weight2);
- mReferenceCompareResults.add(false);
- mReferenceCompareResults.add(true);
- mReferenceLogs.add(String.format(
- "Running test for %d 1x1, 1x2 square with weight %d", square1, weight1));
- ++mTestCount;
-
- // Test case 4: Two images have different metering areas. Image one has
- // two neighboring grey squares as its metering area. Image 2 has two
- // darker neighboring grey squares as its metering area. Weights are
- // the same for both images. Image 1 is expected to be darker than
- // Image 2.
- // Tests whether metering on two mixed-brightness patches work.
- square1 = mRandomGenerator.nextInt(4);
- weight1 = mRandomGenerator.nextInt(1000) + 1;
- runSingleTest(square1, square1 + 1, weight1);
-
- square2 = mRandomGenerator.nextInt(5 - square1 - 1) + square1 + 1;
- weight2 = weight1;
- runSingleTest(square2, square2 + 1, weight2);
- mReferenceCompareResults.add(false);
- mReferenceCompareResults.add(true);
- mReferenceLogs.add(String.format(
- "Running test for %d, %d 1x2 square with weight %d", square1, square2, weight1));
- ++mTestCount;
-
- // Test case 5: Two images have different metering areas. Image one has
- // three neighboring grey squares as its metering area. Image 2 has
- // three darker neighboring grey squares as its metering area. Weights
- // are the same. Image 1 is expected to be darker than Image 2.
- // Tests whether metering on three mixed-brightness patches work.
- square1 = mRandomGenerator.nextInt(3);
- weight1 = mRandomGenerator.nextInt(1000) + 1;
- runSingleTest(square1, square1 + 2, weight1);
-
- square2 = mRandomGenerator.nextInt(4 - square1 - 1) + square1 + 1;
- weight2 = weight1;
- runSingleTest(square2, square2 + 2, weight2);
- mReferenceCompareResults.add(false);
- mReferenceCompareResults.add(true);
- mReferenceLogs.add(String.format(
- "Running test for %d, %d 1x3 square with weight %d", square1, square2, weight1));
- ++mTestCount;
- }
-
- /**
- * Runs metering tests to verify the functionalities when there are two
- * areas set as the metering area.
- */
- private void runTwoAreasTest() {
- int[] weight1 = new int[2];
- int[] weight2 = new int[2];
- int[] square1Start = new int[2];
- int[] square2Start = new int[2];
- int[] square1End = new int[2];
- int[] square2End = new int[2];
-
- Log.v(TAG, "Running two-area Test");
-
- // Test case 1: Image 1 has two metering areas. They are two adjacent
- // grey squares (each set as a metering area). The two areas have the
- // same weight. Image 2 has one metering area, which is the combination
- // of Image 1's two metering areas as a rectangle. The weight is the
- // same as that of Image 1's individual area. Image 1 is expected to
- // be equivalent to Image 2.
- // Tests whether having seperating a metering area into two will yield
- // the same result.
- square1Start[0] = mRandomGenerator.nextInt(5);
- square1End[0] = square1Start[0];
- weight1[0] = mRandomGenerator.nextInt(1000) + 1;
- square1Start[1] = square1Start[0] + 1;
- square1End[1] = square1Start[1];
- weight1[1] = weight1[0];
- runMultipleAreaTest(square1Start, square1End, weight1);
-
- square2Start[0] = square1Start[0];
- weight2[0] = weight1[0];
- runSingleTest(square2Start[0], square2Start[0] + 1, weight2[0]);
- mReferenceCompareResults.add(true);
- mReferenceCompareResults.add(false);
- mReferenceLogs.add(String.format(
- "Running test for %d, %d 1x1 square with weight %d",
- square1Start[0], square1Start[1], weight1[0]));
- ++mTestCount;
-
- // Test case 2: Image 1 has two metering areas. They are two random
- // grey squareson the color checker. The brighter square has a larger
- // weight than the darker square. Image 2 has the same two metering
- // areas as Image 1. The weights for both are equal to the weight of
- // the darker square in Image 1, which is smaller than the weight of
- // the brighter square in Image 1. Image 1 is expected to be darker
- // than Image 2.
- // Tests whether giving one of the two metering areas a different
- // weight would change the image in the correct way.
- square1Start[0] = mRandomGenerator.nextInt(4);
- square1End[0] = square1Start[0];
- weight1[0] = mRandomGenerator.nextInt(100) + 901;
- square1Start[1] = mRandomGenerator.nextInt(5 - square1Start[0] - 1) + square1Start[0] + 1;
- square1End[1] = square1Start[1];
- weight1[1] = mRandomGenerator.nextInt(100) + 1;
- runMultipleAreaTest(square1Start, square1End, weight1);
-
- square2Start[0] = square1Start[0];
- square2End[0] = square2Start[0];
- weight2[0] = weight1[1];
- square2Start[1] = square1Start[1];
- square2End[1] = square1End[1];
- weight2[1] = weight2[0];
- runMultipleAreaTest(square2Start, square2End, weight2);
- mReferenceCompareResults.add(false);
- mReferenceCompareResults.add(true);
- mReferenceLogs.add(String.format(
- "Running test for %d, %d 1x1 square with weight %d, %d",
- square1Start[0], square1Start[1], weight1[0], weight2[1]));
- ++mTestCount;
-
- // Test case 3: Image 1 has two metering areas. Both are set to the
- // same random grey square on the color checker. The weight for both
- // are the same. Image 2 has one meterig area, which is the same as
- // Image 1's chosen grey square. The weight for it is the same as
- // Image 1's weight for one metering area. Image 1 is expected to be
- // equivalent to Image 2.
- // Tests whether defining overlapping metering area works.
- square1Start[0] = mRandomGenerator.nextInt(6);
- square1End[0] = square1Start[0];
- weight1[0] = mRandomGenerator.nextInt(1000) + 1;
- square1Start[1] = square1Start[0];
- square1End[1] = square1Start[1];
- weight1[1] = weight1[0];
- runMultipleAreaTest(square1Start, square1End, weight1);
-
- square2Start[0] = square1Start[0];
- square2End[0] = square2Start[0];
- weight2[0] = weight1[0];
- runSingleTest(square2Start[0], square2End[0], weight2[0]);
- mReferenceCompareResults.add(true);
- mReferenceCompareResults.add(false);
- mReferenceLogs.add(String.format(
- "Running test for %d 1x1 square with weight %d,", square1Start[0], weight1[0]));
- ++mTestCount;
-
- // Test case 4: Image 1 has two metering areas. The first one is a
- // grey square on the color checker. The second one is a rectangle
- // containing the first metering area's grey square and its neighboring
- // darker square. The weights for both metering area are the same.
- // Image 2 has two metering areas. The first one is the same grey
- // square as Image 1's first metering area. The second one is the
- // neighboring darker grey square. The weight for the brighter square
- // is double the weight of Image 1's weights for each metering area.
- // The weight for the Image 2's darker grey square is the same as
- // Image 1's weight for each of its metering areas. Image 1 is expected
- // to be equivalent to Image 2.
- // Tests whether the weights for overlapping metering area add up.
- square1Start[0] = mRandomGenerator.nextInt(2);
- square1End[0] = square1Start[0];
- weight1[0] = mRandomGenerator.nextInt(500) + 1;
- square1Start[1] = square1Start[0];
- square1End[1] = square1Start[1] + 1;
- weight1[1] = weight1[0];
- runMultipleAreaTest(square1Start, square1End, weight1);
-
- square2Start[0] = square1Start[0];
- square2End[0] = square1End[0];
- weight2[0] = weight1[0] * 2;
- square2Start[1] = square2Start[0] + 1;
- square2End[1] = square2Start[1];
- weight2[1] = weight1[1];
- runMultipleAreaTest(square2Start, square2End, weight2);
- mReferenceCompareResults.add(true);
- mReferenceCompareResults.add(false);
- mReferenceLogs.add(String.format(
- "Running test for %d 1x2 1x1 and 1x2 square with weight %d,",
- square1Start[0], weight1[0]));
- ++mTestCount;
- }
-
- /**
- * Runs the metering test when multiple metering areas are defined.
- *
- * @param startIndex the array storing the index of the grey square where
- * one metering area starts
- * @param endIndex the array storing the index of the grey square where one
- * metering area ends.
- * @param weight the array storing the weight for each metering area.
- */
- private void runMultipleAreaTest(int[] startIndex, int[] endIndex, int[] weight) {
- int numAreas = startIndex.length;
- mParams = mTestCamera.getParameters();
- List<Camera.Area> meteringAreas = new ArrayList<Camera.Area>();
-
- for (int i = 0; i < numAreas; ++i) {
- meteringAreas.add(makeArea(startIndex[i], endIndex[i], weight[i]));
- Log.v(TAG, String.format("Add metering area for %d, %d, %d",
- startIndex[i], endIndex[i], weight[i]));
- }
- mParams.setMeteringAreas(meteringAreas);
- mTestCamera.setParameters(mParams);
- takePicture();
- }
-
- /**
- * Runs the metering test when one metering area is defined.
- *
- * @param startIndex the index of the grey square where the metering area
- * starts
- * @param endIndex the index of the grey square where the metering area
- * ends.
- * @param weight the weight for the metering area.
- */
- private void runSingleTest(int startIndex, int endIndex, int weight) {
- mParams = mTestCamera.getParameters();
- List<Camera.Area> meteringAreas = new ArrayList<Camera.Area>();
-
- Log.v(TAG, String.format("Single test for %d, %d, %d", startIndex, endIndex, weight));
- meteringAreas.add(makeArea(startIndex, endIndex, weight));
- mParams.setMeteringAreas(meteringAreas);
- mTestCamera.setParameters(mParams);
- takePicture();
- }
-
- /**
- * Takes picture with the camera instance linked to this test class.
- */
- private void takePicture() {
- // Waits for the metering to be stable
- try{
- Log.v(TAG, "Waiting for metering");
- Thread.sleep(LONG_SLEEP);
- Log.v(TAG, "END Waiting");
- } catch (InterruptedException e) {}
-
- mTestCamera.takePicture(null, null, null, mTestJpegListener);
-
- // Locks thread until picture is taken and ready for processing.
- synchronized (mProcessingImage) {
- try{
- Log.v(TAG, "Start waiting for Image");
-
- mProcessingImage.wait();
- } catch (InterruptedException e) {
- Log.v(TAG, "Callback wait fails!");
- }
- }
- }
-
- /**
- * Constructs a <code>Camera.Area</code> object of the metering area.
- * Given the start and end index of one metering area, it takes the upper
- * left corner of the starting square and the bottom right corner of the
- * end square to construct an Area.
- *
- * @param startIndex the index of the grey square where the metering area
- * starts
- * @param endIndex the index of the grey square where the metering area
- * ends
- * @param weight the weight of this metering area.
- *
- * @return a <code>Camera.Area</code> object which represents this metering
- * area
- */
- private Camera.Area makeArea(int startIndex, int endIndex, int weight) {
- Rect areaRect = new Rect(mGreyCoordinates[startIndex * 4],
- mGreyCoordinates[startIndex * 4 + 1],
- mGreyCoordinates[endIndex * 4 + 2],
- mGreyCoordinates[endIndex * 4 + 3]);
- Camera.Area area = new Camera.Area(areaRect, weight);
-
- return area;
- }
-
- @Override
- public String getDebugText() {
- return mDebugText;
- }
-
- @Override
- public String getResultText() {
- return mDebugText;
- }
-
- @Override
- public String getTestName() {
- return "Metering Test: \n";
- }
-
- @Override
- public String getTestName(int index) {
- switch (index) {
- case 0:
- return "Run all tests";
- case 1:
- return "One metering area tests";
- case 2:
- return "Multiple metering areas tests";
- default:
- return "";
- }
- }
-
- @Override
- public int getResult(int index) {
- return mTestResults[index];
- }
-
- @Override
- public int getNumTests() {
- return mNumTests;
- }
-
- private Camera.PictureCallback mTestJpegListener = new Camera.PictureCallback() {
- public void onPictureTaken(byte[] data, Camera mCamera) {
- Log.v(TAG, "Shutter pressed down!");
- Bitmap inputImage;
- try {
- FileOutputStream outStream = new FileOutputStream(
- String.format("/sdcard/metering%d.jpg", System.currentTimeMillis()));
- outStream.write(data);
- outStream.close();
- } catch (FileNotFoundException e) {
- } catch (IOException e) {}
-
- // Decodes the input data of the camera.
- inputImage = BitmapFactory.decodeByteArray(data, 0, data.length);
-
- // Records the memory address of the native image class instance.
- long bufferAddress = findNative(inputImage);
- Log.v(TAG, "findNative method finishes");
-
- // Cleans up the memory taken by the bitmap.
- inputImage.recycle();
- data = null;
- inputImage = null;
- System.gc();
-
- // Add the image data to the native test handler.
- createMeteringClass(bufferAddress, mTestHandler,
- getCheckerCenter(), getCheckerRadius());
- mCamera.startPreview();
-
- // Releases thread lock after the image is processed.
- synchronized (mProcessingImage) {
- mProcessingImage.notifyAll();
- }
- }
- };
-
- /**
- * Finds the coordinates of the grey squares on the color checker.
- * The coordinates are computed by using the checker center and radius.
- * The coordinates are converted to a system with (-1000, -1000) in the
- * upper left corner and (1000, 1000) in the bottom right corner.
- *
- * @param greyCoordinates the array to store the coordinates of the grey
- * squares
- * @param checkerCenterAddress the memory address pointing to the vector
- * storing the color checker's centers.
- * @param checkerRadiusAddress the memory address pointing to the vetor
- * storing the color checker's radius.
- */
- private native void findGreyCoordinates(int[] greyCoordinates,
- long checkerCenterAddress, long checkerRadiusAddress);
-
- /**
- * Creates the native metering test handler with no debug image.
- *
- * @return the memory address pointing to the native test handler instance
- */
- private native long createMeteringTest();
-
- /**
- * Adds the data from the native image class instance to the native test
- * handler.
- *
- * @param bufferAddress the meory address of the native image class
- * @param handlerAddress the memory address of the native test handler
- * @param checkerCenterAddress the memory address of the checker cneters
- * @param checkerRadiusAddress the meory address of the checker radius
- */
- private native void createMeteringClass(long bufferAddress, long handlerAddress,
- long checkerCenterAddress,
- long checkerRadiusAddress);
-
- /**
- * Process the data stored in the native test handler and stores the
- * comparison results.
- *
- * @param handlerAddress the memory address of the native test handler
- * @param testCompareResults the boolean array to store the test comparison
- * results
- */
- private native void processMeteringTest(long handlerAddress, boolean[] testCompareResults);
-
- static {
- System.loadLibrary("cameraanalyzer");
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/analyzer/WhiteBalanceTest.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/analyzer/WhiteBalanceTest.java
deleted file mode 100644
index a4111eb..0000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/analyzer/WhiteBalanceTest.java
+++ /dev/null
@@ -1,398 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.verifier.camera.analyzer;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.ImageFormat;
-import android.hardware.Camera;
-import android.util.Log;
-import android.widget.ImageView;
-import java.io.FileOutputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-
-import java.util.List;
-
-/**
- * Implements a test to verify whether the correlated color temperatures (CTT)
- * of the supported white balance modes are inside the range camera
- * manufacturers generally agree on.
- *
- * The test assumes that the Daylight white balance mode has a CCT of 5200K,
- * which is widely agreed in industry and academics. It then use this as a
- * benchmark and compare images taken with other white balance settings.
- * Using the pixel values of the grey squares on the color checker, the CCT
- * of other white balance modes can be computed. The reference ranges were
- * summarized with the help of online resources. For the Auto mode, the
- * reference CCT is computed as the CCT that will keep the grey squares appear
- * grey in the result image.
- */
-public class WhiteBalanceTest extends CameraTests {
-
- private static final String TAG = "WhiteBalanceTest";
-
- /** Current white balance mode. */
- private String mWhiteBalance;
- /** Array to store the reference CCT's of each mode. */
- private int[][] mReferenceTemperature;
- /** List of supported white balance mode on a device. */
- private List<String> mWhiteBalanceList;
- /** The index of the white balance mode "Auto". */
- private int mAutoId;
-
- /** Debug results in text. */
- private String mDebugText;
- /** Memory address of the native test handler instance. */
- private long mTestHandler;
- /** Thread lock. */
- private final Object mProcessingImage = new Object();
- /** Test result to show. */
- private int[] mTestResults;
- /** Number of test. */
- private int mNumTests;
- /** Camera Parameters. */
- private Camera.Parameters mParams;
- /** Singleton test instance. */
- private static WhiteBalanceTest singletonTest = null;
- /** Boolean to check whehter daylight wb has been recorded. */
- private boolean mHasDaylight = false;
-
- /**
- * Constructs a <code>WhiteBalanceTest</code> instance with a given
- * Camera pointer.
- */
- private WhiteBalanceTest() {
- super();
- }
-
- public void updateCamera() {
- mAutoId = 0;
- mHasDaylight = false;
- mParams = mTestCamera.getParameters();
- mWhiteBalanceList = mParams.getSupportedWhiteBalance();
- mNumTests = mWhiteBalanceList.size() + 1;
- mTestResults = new int[mNumTests];
- for (int i = 0; i < mNumTests; ++i) {
- mTestResults[i] = CameraTests.CAMERA_TEST_NOT_RUN;
- }
-
- if (mWhiteBalanceList != null) {
- mReferenceTemperature = new int[mWhiteBalanceList.size()][2];
-
- // Sets the reference CCT of the supported white balance modes
- for (int i = 0; i < mWhiteBalanceList.size(); i++) {
- setReferenceTemperature(i, mWhiteBalanceList.get(i));
- if (mWhiteBalanceList.get(i).equals("auto")) {
- mAutoId = i;
- }
- }
- }
- }
-
- public static synchronized WhiteBalanceTest getSingletonTest() {
- if (singletonTest == null) {
- Log.v(TAG, "Creating a new WhiteBalanceTest instance");
- singletonTest = new WhiteBalanceTest();
- singletonTest.initializeTest();
- }
- return singletonTest;
- }
-
- private void initializeTest() {
- mDebugText = new String();
- // Creates a native white balance test handler.
- // mTestHandler stores the memory address of this instance.
- mTestHandler = createWhiteBalanceTest();
- }
-
- private void initializeWhiteBalanceTest() {
- mWhiteBalance = "daylight";
- takePicture(mWhiteBalance);
- int colorTemperature = processWhiteBalanceTest(mTestHandler);
-
- setReferenceTemperature(mAutoId, colorTemperature);
- mHasDaylight = true;
- }
-
- private void takePicture(String whiteBalance) {
- mParams.setWhiteBalance(whiteBalance);
- mTestCamera.setParameters(mParams);
-
- try{
- Log.v(TAG, "Waiting for white balance to adjust");
- Thread.sleep(4000);
- Log.v(TAG, "END Waiting");
- } catch (InterruptedException e) {}
-
- mTestCamera.takePicture(null, null, null, mTestJpegListener);
-
- // Thread locks until image capture is done
- synchronized (mProcessingImage) {
- try{
- Log.v(TAG, "Start waiting for Image");
- mProcessingImage.wait();
- } catch (InterruptedException e) {
- Log.v(TAG, "Callback wait fails!");
- }
- }
- }
-
- /**
- * Runs the white balance camera test instance.
- */
- @Override
- public synchronized void run(int index) {
- Log.v(TAG, "WhiteBalanceTest thread started!");
-
- if (!mHasDaylight) {
- initializeWhiteBalanceTest();
- }
-
- if (index != 0) {
- // Retrieves the list of supported white balance mode.
- mParams = mTestCamera.getParameters();
-
- int i = index - 1;
- mWhiteBalance = mWhiteBalanceList.get(i);
-
- Log.v(TAG, "Current white balance is " + mWhiteBalance);
-
- takePicture(mWhiteBalance);
-
- // Processes the white balance test data in the native code.
- // Returns an array of CCT of each white balance modes, given the CCT
- // of the "Daylight" mode is 5200K.
- int colorTemperature = 0;
-
- Log.v(TAG, "Finished taking picture, ready to process");
- colorTemperature = processWhiteBalanceTest(mTestHandler);
-
- // Records the index of the "Auto" white balance mode
- if (mWhiteBalance.equals("daylight")) {
- setReferenceTemperature(mAutoId, colorTemperature);
- prepareDebugText(5200, index);
- // Computes the reference CCT range of the "Auto" mode. Assuming that
- // all grey squares on the color checker should be imaged as grey under
- // a CCT, this CCT is used as a middle point to provide a range.
- //setReferenceTemperature(mAutoId, colorTemperature[mWhiteBalanceList.size()]);
- } else {
- // Prepares the debug output.
- prepareDebugText(colorTemperature, index);
- }
- } else {
- for (int i = 0; i < mWhiteBalanceList.size(); i++) {
- run(i + 1);
- }
- }
-
- mParams.setWhiteBalance("auto");
- mTestCamera.setParameters(mParams);
- }
-
- /**
- * Prepares the debug results in HTML text. For each white balance mode,
- * the CCT will be printed in green if it is in the reference range and
- * red otherwise. The reference CCT range is also printed below, with
- * green meaning the CCT range is satisfied and red otherwise.
- *
- * @param colorTemperature the CCT of the supported white balance modes
- */
- private void prepareDebugText(int colorTemperature, int index) {
- mDebugText += String.format("CCT Ref is %d, %d, and CCT is %d",
- mReferenceTemperature[index - 1][0],
- mReferenceTemperature[index - 1][1],
- colorTemperature);
- Log.v(TAG, String.format("CCT Ref is %d, %d, and CCT is %d",
- mReferenceTemperature[index - 1][0],
- mReferenceTemperature[index - 1][1],
- colorTemperature));
- if ((colorTemperature >= mReferenceTemperature[index - 1][0]) &&
- (colorTemperature <= mReferenceTemperature[index - 1][1])) {
- mTestResults[index] = CameraTests.CAMERA_TEST_SUCCESS;
- } else {
- mTestResults[index] = CameraTests.CAMERA_TEST_FAILURE;
- }
-
- }
-
- @Override
- public String getDebugText() {
- return mDebugText;
- }
-
- @Override
- public String getResultText() {
- return mDebugText;
- }
-
- @Override
- public String getTestName() {
- return "White Balance Test: \n";
- }
-
- @Override
- public String getTestName(int index) {
- if (index != 0){
- return String.format("%s mode test", mWhiteBalanceList.get(index - 1));
- } else {
- return "Run all tests";
- }
- }
-
- @Override
- public int getResult(int index) {
- return mTestResults[index];
- }
-
- @Override
- public int getNumTests() {
- return mNumTests;
- }
-
- /**
- * Sets the reference temperatures for the white balance modes of
- * incandescent, fluorescent, warm-fluorescent, daylight, cloudy, shade
- * and twilight. These are the currently supported White balance mode
- * listed on the Android camera API.
- *
- * The reference range are summarized based on the published settings of
- * Canon, Nikon and the references from Wikipedia on color temperature.
- *
- * @param i the index of the current white balance mode
- * @param referenceWhiteBalance the name of the white balance mode.
- */
- private void setReferenceTemperature(int i, String referenceWhiteBalance) {
- if (referenceWhiteBalance.equals("incandescent")) {
- mReferenceTemperature[i][0] = 2500;
- mReferenceTemperature[i][1] = 3500;
- } else if (referenceWhiteBalance.equals("fluorescent")) {
- mReferenceTemperature[i][0] = 3000;
- mReferenceTemperature[i][1] = 6500;
- } else if (referenceWhiteBalance.equals("warm-fluorescent")) {
- mReferenceTemperature[i][0] = 2500;
- mReferenceTemperature[i][1] = 3000;
- } else if (referenceWhiteBalance.equals("daylight")) {
- mReferenceTemperature[i][0] = 5000;
- mReferenceTemperature[i][1] = 5400;
- } else if (referenceWhiteBalance.equals("cloudy-daylight")) {
- mReferenceTemperature[i][0] = 5500;
- mReferenceTemperature[i][1] = 7500;
- } else if (referenceWhiteBalance.equals("shade")) {
- mReferenceTemperature[i][0] = 6800;
- mReferenceTemperature[i][1] = 8000;
- } else if (referenceWhiteBalance.equals("twilight")) {
- mReferenceTemperature[i][0] = 10000;
- mReferenceTemperature[i][1] = 14000;
- }
- }
-
- /** Sets a reference range of CCT based on a given middle point CCT.
- * The rerence range is from -10% of the CCT value to +10%.
- *
- * @param i the index of the current white balance mode
- * @param t the middle point CCT.
- */
- private void setReferenceTemperature(int i, int t) {
- mReferenceTemperature[i][0] = (int)((double)t * 0.9);
- mReferenceTemperature[i][1] = (int)((double)t * 1.1);
- }
-
- private Camera.PictureCallback mTestJpegListener = new Camera.PictureCallback() {
- public void onPictureTaken(byte[] data, Camera mCamera) {
- Log.v(TAG, "Shutter pressed down!");
- Bitmap inputImage;
- try {
- FileOutputStream outStream = new FileOutputStream(
- String.format("/sdcard/wb%d.jpg", System.currentTimeMillis()));
- outStream.write(data);
- outStream.close();
- } catch (FileNotFoundException e) {
- } catch (IOException e) {}
- // Decodes the camera data to Bitmap and creates a native image
- // class with the Bitmap.
- inputImage = BitmapFactory.decodeByteArray(data, 0, data.length);
- long bufferAddress = findNative(inputImage);
- Log.v(TAG, "findNative method finishes");
-
- // Cleans up the Bitmap memory space.
- inputImage.recycle();
- data = null;
- inputImage = null;
- System.gc();
-
- // Adds the data from the current image base class to the native
- // white balance test handler.
- createWhiteBalanceClass(bufferAddress, mTestHandler,
- getCheckerCenter(), getCheckerRadius(), mWhiteBalance);
-
- mCamera.startPreview();
-
- // Notifies the thread lock that the image capture is finished
- synchronized (mProcessingImage) {
- mProcessingImage.notifyAll();
- }
- }
- };
-
- /**
- * Creates a native white balance test handler.
- *
- * @return the memory address of the test handler
- */
- private native long createWhiteBalanceTest();
-
- /**
- * Adds the data of interest from the image class pointed by
- * <code>bufferAddress</code> to the handler class pointed by
- * <code>handlerAddress</code> by using the color checker coordinates.
- * Also sets the white balance of this test.
- *
- * @param bufferAddress the memory address of the native image class
- * containing the current camera captured image
- * @param handlerAddress the memory address of the native white balance
- * test handler instance
- * @param checkerCenterAddress the memory address of the color checker
- * center coordinates
- * @param checkerRadiusAddress the memory address of the color checker
- * radius
- * @param whiteBalance the white balance mode used for shooting the image
- */
- private native void createWhiteBalanceClass(long bufferAddress, long handlerAddress,
- long checkerCenterAddress,
- long checkerRadiusAddress,
- String whiteBalance);
-
- /**
- * Processes the white balance test in the native code. This is executed
- * after the images are taken with all possible white balance modes. It
- * uses the "Daylight" white balance mode as reference and computes the
- * CCT of other white balance modes.
- *
- * @param handlerAddress the memory address of the native white balance
- * test handler instance.
- * @param colorTemperature the array to store the computed CCT of all white
- * balance modes.
- */
- private native int processWhiteBalanceTest(long handlerAddress);
-
- private native int getAutoTemperature(long handlerAddress);
-
- static {
- System.loadLibrary("cameraanalyzer");
- }
-}
diff --git a/build/test_deqp_package.mk b/build/test_deqp_package.mk
index b07876d..58df98f 100644
--- a/build/test_deqp_package.mk
+++ b/build/test_deqp_package.mk
@@ -39,6 +39,6 @@
| grep --only-matching -e " abis=\"[^\"]*\""))
# Patch xml caselist with supported abi
- $(hide) $(SED_EXTENDED) -e 's:^<Test (.*)/>$$:<Test \1 $(supported_abi_attr) />:' \
+ $(hide) $(SED_EXTENDED) -e 's:^<Test ((.[^/]|[^/])*)(/?)>$$:<Test \1 $(supported_abi_attr) \3>:' \
< $(MUSTPASS_XML_FILE) \
> $@
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/Android.mk b/hostsidetests/devicepolicy/app/DeviceOwner/Android.mk
index e621933..bd0089f 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/Android.mk
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/Android.mk
@@ -26,6 +26,8 @@
LOCAL_JAVA_LIBRARIES := android.test.runner cts-junit
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+
LOCAL_SDK_VERSION := current
include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml b/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml
index dfc7e9c..6aa6bbb 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/AndroidManifest.xml
@@ -61,7 +61,7 @@
android:name="com.android.cts.deviceowner.ApplicationRestrictionActivity" />
</application>
- <instrumentation android:name="android.test.InstrumentationTestRunner"
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.cts.deviceowner"
android:label="Device Owner CTS tests"/>
</manifest>
diff --git a/hostsidetests/devicepolicy/app/IntentSender/Android.mk b/hostsidetests/devicepolicy/app/IntentSender/Android.mk
index e45ec31..e5246c5 100644
--- a/hostsidetests/devicepolicy/app/IntentSender/Android.mk
+++ b/hostsidetests/devicepolicy/app/IntentSender/Android.mk
@@ -26,7 +26,7 @@
LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 ctstestrunner
LOCAL_SDK_VERSION := current
diff --git a/hostsidetests/devicepolicy/app/IntentSender/AndroidManifest.xml b/hostsidetests/devicepolicy/app/IntentSender/AndroidManifest.xml
index 070ef40..cc27298 100644
--- a/hostsidetests/devicepolicy/app/IntentSender/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/IntentSender/AndroidManifest.xml
@@ -52,7 +52,7 @@
</application>
<instrumentation
- android:name="android.test.InstrumentationTestRunner"
+ android:name="android.support.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.cts.intent.sender"
android:label="Intent Sender CTS Tests" />
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk b/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk
index 46e3cf7..f4adb31 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/Android.mk
@@ -26,7 +26,7 @@
LOCAL_JAVA_LIBRARIES := android.test.runner cts-junit
-LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4
+LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4 ctstestrunner
LOCAL_SDK_VERSION := current
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml b/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
index 301f90b..84cb6f2 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
@@ -73,7 +73,7 @@
<activity android:name=".TestActivity" />
</application>
- <instrumentation android:name="android.test.InstrumentationTestRunner"
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.cts.managedprofile"
android:label="Managed Profile CTS Tests"/>
</manifest>
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ManagedProfileTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ManagedProfileTest.java
index 47ecfcb..e655d7b 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ManagedProfileTest.java
@@ -21,6 +21,7 @@
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.test.ActivityInstrumentationTestCase2;
+import android.support.test.InstrumentationRegistry;
import static com.android.cts.managedprofile.BaseManagedProfileTest.ADMIN_RECEIVER_COMPONENT;
@@ -43,6 +44,10 @@
@Override
protected void setUp() throws Exception {
super.setUp();
+ // As the way to access Instrumentation is changed in the new runner, we need to inject it
+ // manually into ActivityInstrumentationTestCase2. ActivityInstrumentationTestCase2 will
+ // be marked as deprecated and replaced with ActivityTestRule.
+ injectInstrumentation(InstrumentationRegistry.getInstrumentation());
mPackageManager = getActivity().getPackageManager();
mDevicePolicyManager = (DevicePolicyManager)
getActivity().getSystemService(Context.DEVICE_POLICY_SERVICE);
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserTest.java
index 40ff6c5..4163ba8 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserTest.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/PrimaryUserTest.java
@@ -20,6 +20,7 @@
import android.content.Intent;
import android.content.pm.PackageManager;
import android.test.ActivityInstrumentationTestCase2;
+import android.support.test.InstrumentationRegistry;
/**
* Test for {@link DevicePolicyManager#addCrossProfileIntentFilter} API, for
@@ -43,6 +44,10 @@
@Override
protected void setUp() throws Exception {
super.setUp();
+ // As the way to access Instrumentation is changed in the new runner, we need to inject it
+ // manually into ActivityInstrumentationTestCase2. ActivityInstrumentationTestCase2 will
+ // be marked as deprecated and replaced with ActivityTestRule.
+ injectInstrumentation(InstrumentationRegistry.getInstrumentation());
mPackageManager = getActivity().getPackageManager();
}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
index c35246d..bd9c8e0 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -47,13 +47,13 @@
*/
public class BaseDevicePolicyTest extends DeviceTestCase implements IBuildReceiver {
+ private static final String RUNNER = "android.support.test.runner.AndroidJUnitRunner";
+
protected static final String MANAGED_PROFILE_PKG = "com.android.cts.managedprofile";
protected static final String MANAGED_PROFILE_APK = "CtsManagedProfileApp.apk";
protected static final String ADMIN_RECEIVER_TEST_CLASS =
MANAGED_PROFILE_PKG + ".BaseManagedProfileTest$BasicAdminReceiver";
- private static final String RUNNER = "android.test.InstrumentationTestRunner";
-
private static final String[] REQUIRED_DEVICE_FEATURES = new String[] {
"android.software.managed_users",
"android.software.device_admin" };
@@ -305,7 +305,6 @@
return Integer.parseInt(tokens[tokens.length-1]);
}
-
protected int getUserSerialNumber(int userId) throws DeviceNotAvailableException{
// dumpsys user return lines like "UserInfo{0:Owner:13} serialNo=0"
String commandOutput = getDevice().executeShellCommand("dumpsys user");
@@ -327,7 +326,7 @@
protected void setProfileOwner(String componentName, int userId)
throws DeviceNotAvailableException {
- String command = "dpm set-profile-owner '" + componentName + "' " + userId;
+ String command = "dpm set-profile-owner --user " + userId + " '" + componentName + "'";
String commandOutput = getDevice().executeShellCommand(command);
CLog.logAndDisplay(LogLevel.INFO, "Output for command " + command + ": " + commandOutput);
assertTrue(commandOutput + " expected to start with \"Success:\"",
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
index 2ef7cad..fe6d592 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
@@ -188,6 +188,9 @@
if (!mHasFeature) {
return;
}
+ // If adb is running as root, then the adb uid is 0 instead of SHELL_UID,
+ // so the DISALLOW_DEBUGGING_FEATURES restriction does not work and this test
+ // fails.
String restriction = "no_debugging_features"; // UserManager.DISALLOW_DEBUGGING_FEATURES
String command = "add-restriction";
diff --git a/libs/commonutil/src/com/android/cts/util/ReportLog.java b/libs/commonutil/src/com/android/cts/util/ReportLog.java
index 56b431a..dd4b414 100644
--- a/libs/commonutil/src/com/android/cts/util/ReportLog.java
+++ b/libs/commonutil/src/com/android/cts/util/ReportLog.java
@@ -42,26 +42,55 @@
/**
* print array of values to output log
+ * <p>Note: test identifier is inferred from call stack trace based on class and method name
*/
public void printArray(String message, double[] values, ResultType type, ResultUnit unit) {
doPrintArray(message, values, type, unit);
}
/**
+ * print array of values to output log
+ */
+ public void printArray(String testId, String message,
+ double[] values, ResultType type, ResultUnit unit) {
+ doPrintArray(testId, message, values, type, unit);
+ }
+
+ /**
* Print a value to output log
+ * <p>Note: test identifier is inferred from call stack trace based on class and method name
*/
public void printValue(String message, double value, ResultType type, ResultUnit unit) {
double[] vals = { value };
doPrintArray(message, vals, type, unit);
}
+ /**
+ * Print a value to output log
+ */
+ public void printValue(String testId, String message,
+ double value, ResultType type, ResultUnit unit) {
+ double[] vals = { value };
+ doPrintArray(testId, message, vals, type, unit);
+ }
+
private void doPrintArray(String message, double[] values, ResultType type, ResultUnit unit) {
+ doPrintArray(getClassMethodNames(mDepth + 1, true), message, values, type, unit);
+ }
+
+ private void doPrintArray(String testId, String message,
+ double[] values, ResultType type, ResultUnit unit) {
StringBuilder builder = new StringBuilder();
// note mDepth + 1 as this function will be called by printVaue or printArray
// and we need caller of printValue / printArray
- builder.append(getClassMethodNames(mDepth + 1, true) + LOG_ELEM_SEPARATOR + message +
- LOG_ELEM_SEPARATOR + type.getXmlString() + LOG_ELEM_SEPARATOR +
- unit.getXmlString() + LOG_ELEM_SEPARATOR);
+ builder.append(testId);
+ builder.append(LOG_ELEM_SEPARATOR);
+ builder.append(message);
+ builder.append(LOG_ELEM_SEPARATOR);
+ builder.append(type.getXmlString());
+ builder.append(LOG_ELEM_SEPARATOR);
+ builder.append(unit.getXmlString());
+ builder.append(LOG_ELEM_SEPARATOR);
for (double v : values) {
builder.append(v);
builder.append(" ");
diff --git a/libs/deviceutil/src/android/cts/util/SystemUtil.java b/libs/deviceutil/src/android/cts/util/SystemUtil.java
index e6222cb..6e7fd38 100644
--- a/libs/deviceutil/src/android/cts/util/SystemUtil.java
+++ b/libs/deviceutil/src/android/cts/util/SystemUtil.java
@@ -18,9 +18,14 @@
import android.app.ActivityManager;
import android.app.ActivityManager.MemoryInfo;
+import android.app.Instrumentation;
import android.content.Context;
+import android.os.ParcelFileDescriptor;
import android.os.StatFs;
+import java.io.FileInputStream;
+import java.io.IOException;
+
public class SystemUtil {
public static long getFreeDiskSize(Context context) {
StatFs statFs = new StatFs(context.getFilesDir().getAbsolutePath());
@@ -40,4 +45,28 @@
activityManager.getMemoryInfo(info);
return info.totalMem; // TODO totalMem N/A in ICS.
}
+
+ /**
+ * Executes a shell command using shell user identity, and return the standard output in string
+ * <p>Note: calling this function requires API level 21 or above
+ * @param instrumentation {@link Instrumentation} instance, obtained from a test running in
+ * instrumentation framework
+ * @param cmd the command to run
+ * @return the standard output of the command
+ * @throws Exception
+ */
+ public static String runShellCommand(Instrumentation instrumentation, String cmd)
+ throws IOException {
+ ParcelFileDescriptor pfd = instrumentation.getUiAutomation().executeShellCommand(cmd);
+ byte[] buf = new byte[512];
+ int bytesRead;
+ FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
+ StringBuffer stdout = new StringBuffer();
+ while ((bytesRead = fis.read(buf)) != -1) {
+ stdout.append(new String(buf, 0, bytesRead));
+ }
+ fis.close();
+ return stdout.toString();
+ }
+
}
diff --git a/tests/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index 3b2e3f0..6bad84f 100644
--- a/tests/expectations/knownfailures.txt
+++ b/tests/expectations/knownfailures.txt
@@ -7,13 +7,6 @@
bug: 17536113
},
{
- description: "the ConnectivityConstraintTest are not yet stable",
- names: [
- "android.jobscheduler.cts.ConnectivityConstraintTest"
- ],
- bug: 18117279
-},
-{
description: "tests a fragile by nature as they rely on hardcoded behavior",
names: [
"android.accessibilityservice.cts.AccessibilityTextTraversalTest#testActionNextAndPreviousAtGranularityPageOverText",
@@ -76,6 +69,26 @@
bug: 16720689
},
{
+ description: "test can only run properly on a user build device when the bug is resolved",
+ names: [
+ "android.appwidget.cts.AppWidgetTest#testAppWidgetProviderCallbacks",
+ "android.appwidget.cts.AppWidgetTest#testBindAppWidget",
+ "android.appwidget.cts.AppWidgetTest#testCollectionWidgets",
+ "android.appwidget.cts.AppWidgetTest#testDeleteHost",
+ "android.appwidget.cts.AppWidgetTest#testDeleteHosts",
+ "android.appwidget.cts.AppWidgetTest#testGetAppWidgetIds",
+ "android.appwidget.cts.AppWidgetTest#testGetAppWidgetInfo",
+ "android.appwidget.cts.AppWidgetTest#testGetAppWidgetOptions",
+ "android.appwidget.cts.AppWidgetTest#testPartiallyUpdateAppWidgetViaWidgetId",
+ "android.appwidget.cts.AppWidgetTest#testPartiallyUpdateAppWidgetViaWidgetIds",
+ "android.appwidget.cts.AppWidgetTest#testTwoAppWidgetProviderCallbacks",
+ "android.appwidget.cts.AppWidgetTest#testUpdateAppWidgetViaComponentName",
+ "android.appwidget.cts.AppWidgetTest#testUpdateAppWidgetViaWidgetId",
+ "android.appwidget.cts.AppWidgetTest#testUpdateAppWidgetViaWidgetIds"
+ ],
+ bug: 17993121
+},
+{
description: "A few WebGL tests are known to fail in WebView",
names: [
"android.webgl.cts.WebGLTest#test_conformance_extensions_oes_texture_float_with_video_html",
diff --git a/tests/print/Android.mk b/tests/print/Android.mk
deleted file mode 100644
index fea7dc0..0000000
--- a/tests/print/Android.mk
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright (C) 2014 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-##################################################
-# Build the print instrument library
-##################################################
-include $(CLEAR_VARS)
-LOCAL_MODULE := CtsPrintInstrument
-LOCAL_SRC_FILES := $(call all-subdir-java-files) \
- src/android/print/cts/IPrivilegedOperations.aidl
-LOCAL_MODULE_TAGS := optional
-LOCAL_DEX_PREOPT := false
-
-include $(BUILD_JAVA_LIBRARY)
-
-# Copy the shell script to run the print instrument Jar to the CTS out folder.
-$(CTS_TESTCASES_OUT)/$(LOCAL_MODULE).jar : $(LOCAL_BUILT_MODULE) | $(ACP)
- $(copy-file-to-target)
-
-# Copy the built print instrument library Jar to the CTS out folder.
-$(CTS_TESTCASES_OUT)/print-instrument : $(LOCAL_PATH)/print-instrument | $(ACP)
- $(copy-file-to-target)
-
diff --git a/tests/print/print-instrument b/tests/print/print-instrument
deleted file mode 100755
index a79cb8a..0000000
--- a/tests/print/print-instrument
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright (C) 2014 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Script to start "print-instrument" on the device
-#
-# The script sets up an alternative dalvik cache when running as
-# non-root. Jar files needs to be dexopt'd to run in Dalvik. For
-# plain jar files, this is done at first use. shell user does not
-# have write permission to default system Dalvik cache so we
-# redirect to an alternative cache.
-
-RUN_BASE=/data/local/tmp
-
-# If not running as root, use an alternative dex cache.
-if [ ${USER_ID} -ne 0 ]; then
- tmp_cache=${RUN_BASE}/dalvik-cache
- if [ ! -d ${tmp_cache} ]; then
- mkdir -p ${tmp_cache}
- fi
- export ANDROID_DATA=${RUN_BASE}
-fi
-
-# Run print-instrument.
-export CLASSPATH=${RUN_BASE}/CtsPrintInstrument.jar
-
-exec app_process ${RUN_BASE} android.print.cts.PrintInstrument ${@}
diff --git a/tests/print/src/android/print/cts/PrintInstrument.java b/tests/print/src/android/print/cts/PrintInstrument.java
deleted file mode 100644
index 1c568a1..0000000
--- a/tests/print/src/android/print/cts/PrintInstrument.java
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.print.cts;
-
-import android.app.ActivityManagerNative;
-import android.app.IActivityManager;
-import android.app.IInstrumentationWatcher;
-import android.app.Instrumentation;
-import android.app.UiAutomationConnection;
-import android.content.ComponentName;
-import android.content.pm.IPackageDataObserver;
-import android.os.Binder;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.UserHandle;
-import android.util.AndroidException;
-import android.view.IWindowManager;
-
-import com.android.internal.os.BaseCommand;
-
-import java.io.PrintStream;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-public final class PrintInstrument extends BaseCommand {
-
- private static final String ARG_PRIVILEGED_OPS = "ARG_PRIVILEGED_OPS";
-
- private IActivityManager mAm;
-
- public static void main(String[] args) {
- PrintInstrument instrumenter = new PrintInstrument();
- instrumenter.run(args);
- }
-
- @Override
- public void onRun() throws Exception {
- mAm = ActivityManagerNative.getDefault();
- if (mAm == null) {
- System.err.println(NO_SYSTEM_ERROR_CODE);
- throw new AndroidException("Can't connect to activity manager;"
- + " is the system running?");
- }
-
- String op = nextArgRequired();
-
- if (op.equals("instrument")) {
- runInstrument();
- } else {
- showError("Error: unknown command '" + op + "'");
- }
- }
-
- @Override
- public void onShowUsage(PrintStream out) {
- /* do nothing */
- }
-
- @SuppressWarnings("deprecation")
- private void runInstrument() throws Exception {
- String profileFile = null;
- boolean wait = false;
- boolean rawMode = false;
- boolean no_window_animation = false;
- int userId = UserHandle.USER_CURRENT;
- Bundle args = new Bundle();
- String argKey = null, argValue = null;
- IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
-
- String opt;
- while ((opt=nextOption()) != null) {
- if (opt.equals("-p")) {
- profileFile = nextArgRequired();
- } else if (opt.equals("-w")) {
- wait = true;
- } else if (opt.equals("-r")) {
- rawMode = true;
- } else if (opt.equals("-e")) {
- argKey = nextArgRequired();
- argValue = nextArgRequired();
- args.putString(argKey, argValue);
- } else if (opt.equals("--no_window_animation")
- || opt.equals("--no-window-animation")) {
- no_window_animation = true;
- } else if (opt.equals("--user")) {
- userId = parseUserArg(nextArgRequired());
- } else {
- System.err.println("Error: Unknown option: " + opt);
- return;
- }
- }
-
- if (userId == UserHandle.USER_ALL) {
- System.err.println("Error: Can't start instrumentation with user 'all'");
- return;
- }
-
- String cnArg = nextArgRequired();
- ComponentName cn = ComponentName.unflattenFromString(cnArg);
- if (cn == null) throw new IllegalArgumentException("Bad component name: " + cnArg);
-
- InstrumentationWatcher watcher = null;
- UiAutomationConnection connection = null;
- if (wait) {
- watcher = new InstrumentationWatcher();
- watcher.setRawOutput(rawMode);
- connection = new UiAutomationConnection();
- }
-
- float[] oldAnims = null;
- if (no_window_animation) {
- oldAnims = wm.getAnimationScales();
- wm.setAnimationScale(0, 0.0f);
- wm.setAnimationScale(1, 0.0f);
- }
-
- args.putIBinder(ARG_PRIVILEGED_OPS, new PrivilegedOperations(mAm));
-
- if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher, connection, userId, null)) {
- throw new AndroidException("INSTRUMENTATION_FAILED: " + cn.flattenToString());
- }
-
- if (watcher != null) {
- if (!watcher.waitForFinish()) {
- System.out.println("INSTRUMENTATION_ABORTED: System has crashed.");
- }
- }
-
- if (oldAnims != null) {
- wm.setAnimationScales(oldAnims);
- }
- }
-
- private int parseUserArg(String arg) {
- int userId;
- if ("all".equals(arg)) {
- userId = UserHandle.USER_ALL;
- } else if ("current".equals(arg) || "cur".equals(arg)) {
- userId = UserHandle.USER_CURRENT;
- } else {
- userId = Integer.parseInt(arg);
- }
- return userId;
- }
-
- private class InstrumentationWatcher extends IInstrumentationWatcher.Stub {
- private boolean mFinished = false;
- private boolean mRawMode = false;
-
- /**
- * Set or reset "raw mode". In "raw mode", all bundles are dumped. In "pretty mode",
- * if a bundle includes Instrumentation.REPORT_KEY_STREAMRESULT, just print that.
- * @param rawMode true for raw mode, false for pretty mode.
- */
- public void setRawOutput(boolean rawMode) {
- mRawMode = rawMode;
- }
-
- @Override
- public void instrumentationStatus(ComponentName name, int resultCode, Bundle results) {
- synchronized (this) {
- // pretty printer mode?
- String pretty = null;
- if (!mRawMode && results != null) {
- pretty = results.getString(Instrumentation.REPORT_KEY_STREAMRESULT);
- }
- if (pretty != null) {
- System.out.print(pretty);
- } else {
- if (results != null) {
- for (String key : results.keySet()) {
- System.out.println(
- "INSTRUMENTATION_STATUS: " + key + "=" + results.get(key));
- }
- }
- System.out.println("INSTRUMENTATION_STATUS_CODE: " + resultCode);
- }
- notifyAll();
- }
- }
-
- @Override
- public void instrumentationFinished(ComponentName name, int resultCode,
- Bundle results) {
- synchronized (this) {
- // pretty printer mode?
- String pretty = null;
- if (!mRawMode && results != null) {
- pretty = results.getString(Instrumentation.REPORT_KEY_STREAMRESULT);
- }
- if (pretty != null) {
- System.out.println(pretty);
- } else {
- if (results != null) {
- for (String key : results.keySet()) {
- System.out.println(
- "INSTRUMENTATION_RESULT: " + key + "=" + results.get(key));
- }
- }
- System.out.println("INSTRUMENTATION_CODE: " + resultCode);
- }
- mFinished = true;
- notifyAll();
- }
- }
-
- public boolean waitForFinish() {
- synchronized (this) {
- while (!mFinished) {
- try {
- if (!mAm.asBinder().pingBinder()) {
- return false;
- }
- wait(1000);
- } catch (InterruptedException e) {
- throw new IllegalStateException(e);
- }
- }
- }
- return true;
- }
- }
-
- private static final class PrivilegedOperations extends IPrivilegedOperations.Stub {
- private final IActivityManager mAm;
-
- public PrivilegedOperations(IActivityManager am) {
- mAm = am;
- }
-
- @Override
- public boolean clearApplicationUserData(final String clearedPackageName)
- throws RemoteException {
- final long identity = Binder.clearCallingIdentity();
- try {
- final AtomicBoolean success = new AtomicBoolean();
- final CountDownLatch completionLatch = new CountDownLatch(1);
-
- mAm.clearApplicationUserData(clearedPackageName,
- new IPackageDataObserver.Stub() {
- @Override
- public void onRemoveCompleted(String packageName, boolean succeeded) {
- if (clearedPackageName.equals(packageName) && succeeded) {
- success.set(true);
- } else {
- success.set(false);
- }
- completionLatch.countDown();
- }
- }, UserHandle.USER_CURRENT);
-
- try {
- completionLatch.await();
- } catch (InterruptedException ie) {
- /* ignore */
- }
-
- return success.get();
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
- }
-}
diff --git a/apps/CtsVerifier/lib/colorchecker/vec2.cpp b/tests/tests/graphics/res/drawable/inset_mutate.xml
similarity index 70%
rename from apps/CtsVerifier/lib/colorchecker/vec2.cpp
rename to tests/tests/graphics/res/drawable/inset_mutate.xml
index 29736bb..ba613e9 100644
--- a/apps/CtsVerifier/lib/colorchecker/vec2.cpp
+++ b/tests/tests/graphics/res/drawable/inset_mutate.xml
@@ -1,5 +1,6 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,11 +13,7 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
- */
-#define LOG_NDEBUG 0
+ -->
-#define LOG_TAG "Vec2"
-#include <utils/Log.h>
-#include <utils/Timers.h>
-
-#include "vec2.h"
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:drawable="@drawable/inset_mutate_testimage" />
diff --git a/tests/tests/graphics/res/drawable/inset_mutate_testimage.jpg b/tests/tests/graphics/res/drawable/inset_mutate_testimage.jpg
new file mode 100644
index 0000000..754df0c
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/inset_mutate_testimage.jpg
Binary files differ
diff --git a/tests/tests/graphics/res/drawable/vector_icon_clip_path_1.xml b/tests/tests/graphics/res/drawable/vector_icon_clip_path_1.xml
index c2ab429..53a9660 100644
--- a/tests/tests/graphics/res/drawable/vector_icon_clip_path_1.xml
+++ b/tests/tests/graphics/res/drawable/vector_icon_clip_path_1.xml
@@ -14,10 +14,10 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="64dp"
- android:width="64dp"
- android:viewportHeight="12.25"
- android:viewportWidth="7.30625" >
+ android:height="64dp"
+ android:viewportHeight="12.25"
+ android:viewportWidth="7.30625"
+ android:width="64dp" >
<group
android:pivotX="3.65"
@@ -31,14 +31,18 @@
l 0, 12.25
l -7.3, 0
z" />
- </group>
- <group>
- <path
- android:name="one"
- android:fillColor="#ff88ff"
- android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0-6.671875 -2.109375,0.421875 0.0-1.078125
+
+ <group
+ android:pivotX="3.65"
+ android:pivotY="6.125"
+ android:rotation="30" >
+ <path
+ android:name="one"
+ android:fillColor="#ff88ff"
+ android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0-6.671875 -2.109375,0.421875 0.0-1.078125
l 2.09375-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
l -5.046875,0.0 0.0-1.0Z" />
+ </group>
</group>
<group
android:pivotX="3.65"
@@ -52,12 +56,15 @@
l 0, 6.125
l -7.3, 0
z" />
- </group>
- <group>
- <path
- android:name="two"
- android:fillColor="#ff88ff"
- android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0-1.0q 0.671875-0.6875 1.828125-1.859375
+
+ <group
+ android:pivotX="3.65"
+ android:pivotY="6.125"
+ android:rotation="30" >
+ <path
+ android:name="two"
+ android:fillColor="#ff88ff"
+ android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0-1.0q 0.671875-0.6875 1.828125-1.859375
q 1.1718752-1.1875 1.4687502-1.53125 0.578125-0.625 0.796875-1.0625
q 0.234375-0.453125 0.234375-0.875 0.0-0.703125 -0.5-1.140625
q -0.484375-0.4375 -1.2656252-0.4375 -0.5625,0.0 -1.1875,0.1875
@@ -66,6 +73,7 @@
q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
q -0.78125024,0.8125 -2.2187502,2.265625Z" />
+ </group>
</group>
</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_delete.xml b/tests/tests/graphics/res/drawable/vector_icon_delete.xml
index 8d9c21c..7b8f2aa 100644
--- a/tests/tests/graphics/res/drawable/vector_icon_delete.xml
+++ b/tests/tests/graphics/res/drawable/vector_icon_delete.xml
@@ -24,6 +24,6 @@
<path
android:fillColor="#FF000000"
- android:pathData="M6.0,19.0c0.0,1.104 0.896,2.0 2.0,2.0l8.0,0.0c1.104,0.0 2.0-0.896 2.0-2.0l0.0-12.0L6.0,7.0L6.0,19.0zM18.0,4.0l-2.5,0.0l-1.0-1.0l-5.0,0.0l-1.0,1.0L6.0,4.0C5.4469986,4.0 5.0,4.4469986 5.0,5.0l0.0,1.0l14.0,0.0l0.0-1.0C19.0,4.4469986 18.552002,4.0 18.0,4.0z" />
+ android:pathData="M6.0,19.0c0.0,1.104 896e-3,2.0 2.0,2.0l8.0,0.0c1.104,0.0 2.0-896e-3 2.0-2.0l0.0-12.0L6.0,7.0L6.0,19.0zM18.0,4.0l-2.5,0.0l-1.0-1.0l-5.0,0.0l-1.0,1.0L6.0,4.0C5.4469986,4.0 5.0,4.4469986 5.0,5.0l0.0,1.0l14.0,0.0l0.0-1.0C19.0,4.4469986 18.552002,4.0 18.0,4.0z" />
</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/drawable/vector_icon_heart.xml b/tests/tests/graphics/res/drawable/vector_icon_heart.xml
index ff55fe5..ad991c9 100644
--- a/tests/tests/graphics/res/drawable/vector_icon_heart.xml
+++ b/tests/tests/graphics/res/drawable/vector_icon_heart.xml
@@ -24,6 +24,6 @@
<path
android:fillColor="#FF000000"
- android:pathData="M16.0,5.0c-1.955,0.0 -3.83,1.268 -4.5,3.0c-0.67-1.732 -2.547-3.0 -4.5-3.0C4.4570007,5.0 2.5,6.931999 2.5,9.5c0.0,3.529 3.793,6.258 9.0,11.5c5.207-5.242 9.0-7.971 9.0-11.5C20.5,6.931999 18.543,5.0 16.0,5.0z" />
+ android:pathData="M16.0,5.0c-1.955.0 -3.83,1.268 -4.5,3.0c-0.67-1.732 -2.547-3.0 -4.5-3.0C4.4570007,5.0 2.5,6.931999 2.5,9.5c0.0,3.529 3.793,6.258 9.0,11.5c5.207-5.242 9.0-7.971 9.0-11.5C20.5,6.931999 18.543,5.0 16.0,5.0z" />
</vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/src/android/graphics/cts/PaintTest.java b/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
index 1f709d3..bac72b2 100644
--- a/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
@@ -19,6 +19,7 @@
import android.graphics.ColorFilter;
import android.graphics.MaskFilter;
+import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.Cap;
@@ -28,6 +29,8 @@
import android.graphics.PathEffect;
import android.graphics.Rasterizer;
import android.graphics.Shader;
+import android.graphics.Bitmap;
+import android.graphics.BitmapShader;
import android.graphics.Typeface;
import android.graphics.Xfermode;
import android.os.Build;
@@ -190,7 +193,7 @@
assertEquals(m, p2.getMaskFilter());
assertEquals(e, p2.getPathEffect());
assertEquals(r, p2.getRasterizer());
- assertNotSame(s, p2.getShader());
+ assertEquals(s, p2.getShader());
assertEquals(t, p2.getTypeface());
assertEquals(x, p2.getXfermode());
@@ -199,7 +202,7 @@
assertEquals(m, p2.getMaskFilter());
assertEquals(e, p2.getPathEffect());
assertEquals(r, p2.getRasterizer());
- assertNotSame(s, p2.getShader());
+ assertEquals(s, p2.getShader());
assertEquals(t, p2.getTypeface());
assertEquals(x, p2.getXfermode());
@@ -271,6 +274,35 @@
assertNull(p.getShader());
}
+ public void testShaderLocalMatrix() {
+ int width = 80;
+ int height = 120;
+ int[] color = new int[width * height];
+ Bitmap bitmap = Bitmap.createBitmap(color, width, height, Bitmap.Config.RGB_565);
+
+ Paint p = new Paint();
+ Matrix m = new Matrix();
+ Shader s = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
+
+ // set the shaders matrix to a non identity value and attach to paint
+ m.setScale(10, 0);
+ s.setLocalMatrix(m);
+ p.setShader(s);
+
+ Matrix m2 = new Matrix();
+ assertTrue(p.getShader().getLocalMatrix(m2));
+ assertEquals(m, m2);
+
+ // updated the matrix again and set it on the shader but NOT the paint
+ m.setScale(0, 10);
+ s.setLocalMatrix(m);
+
+ // assert that the matrix on the paint's shader also changed
+ Matrix m3 = new Matrix();
+ assertTrue(p.getShader().getLocalMatrix(m3));
+ assertEquals(m, m3);
+ }
+
public void testSetAntiAlias() {
Paint p = new Paint();
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/InsetDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/InsetDrawableTest.java
index 1edd36e..3caf2ba 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/InsetDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/InsetDrawableTest.java
@@ -24,8 +24,11 @@
import android.content.res.Resources;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.InsetDrawable;
@@ -317,6 +320,24 @@
assertNotNull(constantState);
}
+ public void testMutate() {
+ // Obtain the first instance, then mutate and modify a property held by
+ // constant state. If mutate() works correctly, the property should not
+ // be modified on the second or third instances.
+ Resources res = mContext.getResources();
+ InsetDrawable first = (InsetDrawable) res.getDrawable(R.drawable.inset_mutate, null);
+ InsetDrawable pre = (InsetDrawable) res.getDrawable(R.drawable.inset_mutate, null);
+
+ first.mutate().setAlpha(128);
+
+ assertEquals("Modified first loaded instance", 128, first.getDrawable().getAlpha());
+ assertEquals("Did not modify pre-mutate() instance", 255, pre.getDrawable().getAlpha());
+
+ InsetDrawable post = (InsetDrawable) res.getDrawable(R.drawable.inset_mutate, null);
+
+ assertEquals("Did not modify post-mutate() instance", 255, post.getDrawable().getAlpha());
+ }
+
private class MockInsetDrawable extends InsetDrawable {
public MockInsetDrawable(Drawable drawable, int inset) {
super(drawable, inset);
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/BurstCaptureRawTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/BurstCaptureRawTest.java
new file mode 100644
index 0000000..a64ceb9
--- /dev/null
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/BurstCaptureRawTest.java
@@ -0,0 +1,721 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2.cts;
+
+import static android.hardware.camera2.cts.CameraTestUtils.*;
+
+import android.graphics.ImageFormat;
+import android.graphics.Rect;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureRequest.Builder;
+import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.cts.CameraTestUtils.SimpleCaptureCallback;
+import android.hardware.camera2.cts.CameraTestUtils.SimpleImageReaderListener;
+import android.hardware.camera2.cts.testcases.Camera2SurfaceViewTestCase;
+import android.hardware.camera2.params.StreamConfigurationMap;
+import android.media.Image;
+import android.util.Log;
+import android.util.Range;
+import android.util.Size;
+
+import java.util.ArrayList;
+
+/**
+ * Basic tests for burst capture in RAW10/16.
+ */
+public class BurstCaptureRawTest extends Camera2SurfaceViewTestCase {
+ private static final String TAG = "BurstCaptureRawTest";
+ private static final int RAW_FORMATS[] = {
+ ImageFormat.RAW10, ImageFormat.RAW_SENSOR };
+ private static final long EXPOSURE_MULTIPLIERS[] = {
+ 1, 3, 5 };
+ private static final int SENSITIVITY_MLTIPLIERS[] = {
+ 1, 3, 5 };
+ private static final int MAX_FRAMES_BURST =
+ EXPOSURE_MULTIPLIERS.length * SENSITIVITY_MLTIPLIERS.length;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Verify raw sensor size information is correctly configured.
+ */
+ public void testRawSensorSize() throws Exception {
+ Log.i(TAG, "Begin testRawSensorSize");
+ for (String id : mCameraIds) {
+ try {
+ openDevice(id);
+
+ ArrayList<Integer> supportedRawList = new ArrayList<Integer>(RAW_FORMATS.length);
+ if (!checkCapability(supportedRawList)) {
+ Log.i(TAG, "Capability is not supported on camera " + id
+ + ". Skip the test.");
+ continue;
+ }
+
+ Size[] rawSizes = mStaticInfo.getRawOutputSizesChecked();
+ assertTrue("No capture sizes available for RAW format!", rawSizes.length != 0);
+
+ Rect activeArray = mStaticInfo.getActiveArraySizeChecked();
+ Size size = new Size(activeArray.width(), activeArray.height());
+ mCollector.expectTrue("Missing ActiveArraySize",
+ activeArray.width() > 0 && activeArray.height() > 0);
+ mCollector.expectContains(
+ "Available sizes for RAW format must include ActiveArraySize",
+ rawSizes, size);
+
+ } finally {
+ closeDevice();
+ }
+ }
+ Log.i(TAG, "End testRawSensorSize");
+ }
+
+ /**
+ * Round [exposure, gain] down, rather than to the nearest, in RAW 10/16
+ * <p>
+ * Verify the value of metadata (exposure and sensitivity) is rounded down if the request cannot
+ * be honored.
+ * </p>
+ */
+ public void testMetadataRoundDown() throws Exception {
+ Log.i(TAG, "Begin testMetadataRoundDown");
+
+ performTestRoutine(new TestMetaDataRoundDownRoutine());
+
+ Log.i(TAG, "End testMetadataRoundDown");
+ }
+
+ /**
+ * Manual and Auto setting test in RAW10/16
+ * <p>
+ * Make sure switching between manual and auto setting would not make the capture results out of
+ * sync.
+ * </p>
+ */
+ public void testManualAutoSwitch() throws Exception {
+ Log.i(TAG, "Begin testManualAutoSwitch");
+
+ performTestRoutine(new TestManualAutoSwitch());
+
+ Log.i(TAG, "End testManualAutoSwitch");
+ }
+
+ /**
+ * Per frame timestamp test in RAW10/16
+ */
+ public void testTimestamp() throws Exception {
+ Log.i(TAG, "Begin testTimestamp");
+
+ performTestRoutine(new TestTimestamp());
+
+ Log.i(TAG, "End testTimestamp");
+ }
+
+ /*
+ * Below are private infrastructure for all tests
+ */
+
+ /**
+ * A structure encapsulates all the parameters for setting up preview, and RAW capture.
+ */
+ class CaptureSetup
+ {
+ public CaptureSetup(Size previewCaptureSize, Size rawCaptureSize,
+ CaptureRequest.Builder previewRequestBuilder,
+ CaptureRequest.Builder rawRequestBuilder,
+ SimpleCaptureCallback previewCaptureCallback,
+ SimpleCaptureCallback rawCaptureCallback,
+ SimpleImageReaderListener rawReaderListener)
+ {
+ mPreviewCaptureSize = previewCaptureSize;
+ mRawCaptureSize = rawCaptureSize;
+ mPreviewRequestBuilder = previewRequestBuilder;
+ mRawRequestBuilder = rawRequestBuilder;
+ mPreviewCaptureCallback = previewCaptureCallback;
+ mRawCaptureCallback = rawCaptureCallback;
+ mRawReaderListener = rawReaderListener;
+ }
+
+ public Size getPreviewCaptureSize()
+ {
+ return mPreviewCaptureSize;
+ }
+
+ public Size getRawCaptureSize()
+ {
+ return mRawCaptureSize;
+ }
+
+ public CaptureRequest.Builder getPreviewRequestBuilder()
+ {
+ return mPreviewRequestBuilder;
+ }
+
+ public CaptureRequest.Builder getRawRequestBuilder() {
+ return mRawRequestBuilder;
+ }
+
+ public SimpleCaptureCallback getPreviewCaptureCallback() {
+ return mPreviewCaptureCallback;
+ }
+
+ public SimpleCaptureCallback getRawCaptureCallback() {
+ return mRawCaptureCallback;
+ }
+
+ public SimpleImageReaderListener getRawReaderListener() {
+ return mRawReaderListener;
+ }
+
+ private Size mPreviewCaptureSize;
+ private Size mRawCaptureSize;
+ private CaptureRequest.Builder mPreviewRequestBuilder;
+ private CaptureRequest.Builder mRawRequestBuilder;
+
+ /** all the non-testing requests are sent to here */
+ private SimpleCaptureCallback mPreviewCaptureCallback;
+ /** all the testing requests are sent to here */
+ private SimpleCaptureCallback mRawCaptureCallback;
+ /** all the testing framebuffers are sent to here */
+ private SimpleImageReaderListener mRawReaderListener;
+ }
+
+ /**
+ * Interface for the test routines that are being called by performTestRoutines(). Implement
+ * different test cases in execute().
+ */
+ interface TestRoutine {
+ public void execute(CaptureRequest.Builder rawBurstBuilder,
+ SimpleCaptureCallback rawCaptureCallback,
+ SimpleImageReaderListener rawReaderListener, int rawFormat) throws Exception;
+ }
+
+ /**
+ * Implementation of metadata round down test.
+ */
+ class TestMetaDataRoundDownRoutine implements TestRoutine
+ {
+ @Override
+ public void execute(CaptureRequest.Builder rawBurstBuilder,
+ SimpleCaptureCallback rawCaptureCallback,
+ SimpleImageReaderListener rawReaderListener, int rawFormat) throws Exception
+ {
+ // build burst capture
+ ArrayList<CaptureRequest> rawRequestList = createBurstRequest(rawBurstBuilder);
+
+ // submit captrue
+ Log.i(TAG, "Submitting Burst Request.");
+ mSession.captureBurst(rawRequestList, rawCaptureCallback, mHandler);
+
+ // verify metadata
+ for (int i = 0; i < MAX_FRAMES_BURST; i++) {
+ CaptureResult result = rawCaptureCallback.getCaptureResult(
+ CAPTURE_IMAGE_TIMEOUT_MS);
+
+ long resultExposure = result.get(CaptureResult.SENSOR_EXPOSURE_TIME);
+ int resultSensitivity = result.get(CaptureResult.SENSOR_SENSITIVITY);
+ long desiredExposure = rawRequestList.get(i).get(
+ CaptureRequest.SENSOR_EXPOSURE_TIME);
+ int desiredSensitivity = rawRequestList.get(i).get(
+ CaptureRequest.SENSOR_SENSITIVITY);
+
+ Log.i(TAG, String.format(
+ "Received capture result, exposure = %d, sensitivity = %d. "
+ + "Requested exposure = %d, sensitivity = %d.",
+ resultExposure,
+ resultSensitivity, desiredExposure, desiredSensitivity));
+
+ mCollector.expectTrue(
+ String.format("Exposure value is greater than requested: "
+ + "requested = %d, result = %d.",
+ desiredExposure, resultExposure),
+ resultExposure <= desiredExposure);
+
+ mCollector.expectTrue(
+ String.format("Sensitivity value is greater than requested: "
+ + "requested = %d, result = %d.",
+ desiredSensitivity, resultSensitivity),
+ resultSensitivity <= desiredSensitivity);
+ }
+ }
+ }
+
+ /**
+ * Implementation of manual-auto switching test.
+ */
+ class TestManualAutoSwitch implements TestRoutine
+ {
+ @Override
+ public void execute(CaptureRequest.Builder rawBurstBuilder,
+ SimpleCaptureCallback rawCaptureCallback,
+ SimpleImageReaderListener rawReaderListener, int rawFormat) throws Exception
+ {
+ // create a capture request builder to preserve all the original values
+ CaptureRequest.Builder originBuilder = mCamera.createCaptureRequest(
+ CameraDevice.TEMPLATE_STILL_CAPTURE);
+ copyBurstRequetBuilder(originBuilder, rawBurstBuilder);
+
+ // build burst capture
+ ArrayList<CaptureRequest> rawRequestList = createBurstRequest(rawBurstBuilder);
+
+ // submit captrue but ignore
+ mSession.captureBurst(rawRequestList, rawCaptureCallback, mHandler);
+
+ // drain the capture result
+ drainQueues(rawReaderListener, rawCaptureCallback);
+
+ // reset and build capture with 3A
+ copyBurstRequetBuilder(rawBurstBuilder, originBuilder);
+ rawRequestList = createBurstRequestWith3A(rawBurstBuilder);
+
+ // submit captrue but ignore
+ mSession.captureBurst(rawRequestList, rawCaptureCallback, mHandler);
+
+ // drain the capture result
+ drainQueues(rawReaderListener, rawCaptureCallback);
+
+ // reset and rebuild manual raw burst capture
+ copyBurstRequetBuilder(rawBurstBuilder, originBuilder);
+ rawRequestList = createBurstRequest(rawBurstBuilder);
+
+ // submit capture
+ Log.i(TAG, "Submitting Burst Request.");
+ mSession.captureBurst(rawRequestList, rawCaptureCallback, mHandler);
+
+ // verify metadata
+ for (int i = 0; i < MAX_FRAMES_BURST; i++) {
+ CaptureResult result = rawCaptureCallback.getCaptureResult(
+ CAPTURE_IMAGE_TIMEOUT_MS);
+
+ long resultExposure = result.get(CaptureResult.SENSOR_EXPOSURE_TIME);
+ int resultSensitivity = result.get(CaptureResult.SENSOR_SENSITIVITY);
+ int resultEdgeMode = result.get(CaptureResult.EDGE_MODE);
+ int resultNoiseReductionMode = result.get(
+ CaptureResult.NOISE_REDUCTION_MODE);
+ long desiredExposure = rawRequestList.get(i).get(
+ CaptureRequest.SENSOR_EXPOSURE_TIME);
+ int desiredSensitivity = rawRequestList.get(i).get(
+ CaptureRequest.SENSOR_SENSITIVITY);
+
+ Log.i(TAG, String.format(
+ "Received capture result, exposure = %d, sensitivity = %d. "
+ + "Requested exposure = %d, sensitivity = %d.",
+ resultExposure,
+ resultSensitivity, desiredExposure, desiredSensitivity));
+
+ mCollector.expectTrue(String.format("Edge mode is not turned off."),
+ resultEdgeMode == CaptureRequest.EDGE_MODE_OFF);
+
+ mCollector.expectTrue(String.format("Noise reduction is not turned off."),
+ resultNoiseReductionMode
+ == CaptureRequest.NOISE_REDUCTION_MODE_OFF);
+
+ mCollector.expectTrue(
+ String.format("Exposure value is greater than requested: "
+ + "requested = %d, result = %d.",
+ desiredExposure, resultExposure),
+ resultExposure <= desiredExposure);
+
+ mCollector.expectTrue(
+ String.format("Sensitivity value is greater than requested: "
+ + "requested = %d, result = %d.",
+ desiredSensitivity, resultSensitivity),
+ resultSensitivity <= desiredSensitivity);
+ }
+
+ }
+ }
+
+ /**
+ * Implementation of timestamp test
+ */
+ class TestTimestamp implements TestRoutine
+ {
+ private final double THRESHOLD = 5000000.0; // 5ms
+ private final long EXPOSURE_MULTIPLIERS_PRIVATE[] = {
+ 1, 1, 1 };
+ private final int SENSITIVITY_MLTIPLIERS_PRIVATE[] = {
+ 1, 1, 1 };
+ private final int MAX_FRAMES_BURST_PRIVATE =
+ EXPOSURE_MULTIPLIERS_PRIVATE.length * SENSITIVITY_MLTIPLIERS_PRIVATE.length;
+
+ @Override
+ public void execute(Builder rawBurstBuilder, SimpleCaptureCallback rawCaptureCallback,
+ SimpleImageReaderListener rawReaderListener, int rawFormat) throws Exception {
+ // prepare some local variables
+ ArrayList<Long> sensorTime = new ArrayList<Long>(MAX_FRAMES_BURST_PRIVATE);
+
+ // build burst capture
+ ArrayList<CaptureRequest> rawRequestList = createBurstRequest(rawBurstBuilder,
+ EXPOSURE_MULTIPLIERS_PRIVATE, SENSITIVITY_MLTIPLIERS_PRIVATE);
+
+ // submit capture while recording timestamp
+ Log.i(TAG, "Submitting Burst Request.");
+ mSession.captureBurst(rawRequestList, rawCaptureCallback, mHandler);
+
+ // receive frames while recording timestamp
+ for (int i = 0; i < MAX_FRAMES_BURST_PRIVATE; i++) {
+ CaptureResult result = rawCaptureCallback.getCaptureResult(
+ CAPTURE_IMAGE_TIMEOUT_MS);
+ long resultExposure = result.get(CaptureResult.SENSOR_EXPOSURE_TIME);
+ int resultSensitivity = result.get(CaptureResult.SENSOR_SENSITIVITY);
+ long resultTimestamp = result.get(CaptureResult.SENSOR_TIMESTAMP);
+ Log.i(TAG, String.format(
+ "Received capture result, exposure = %d, sensitivity = %d, timestamp = %d",
+ resultExposure, resultSensitivity, resultTimestamp));
+
+ sensorTime.add(resultTimestamp);
+ }
+
+ // compare sensor time and compute the difference
+ ArrayList<Long> deltaList = new ArrayList<Long>();
+ for (int i = 1; i < MAX_FRAMES_BURST_PRIVATE; i++)
+ {
+ deltaList.add(sensorTime.get(i) - sensorTime.get(i - 1));
+ }
+
+ // compute the average and standard deviation of the differences
+ double average = 0.0;
+ for (int i = 0; i < deltaList.size(); i++)
+ {
+ average += deltaList.get(i);
+ }
+ average /= deltaList.size();
+
+ double stddev = 0.0;
+ for (int i = 0; i < deltaList.size(); i++)
+ {
+ double diff = deltaList.get(i) - average;
+ stddev += diff * diff;
+ }
+ stddev = Math.sqrt(stddev / deltaList.size());
+
+ Log.i(TAG, String.format("average = %.2f, stddev = %.2f", average, stddev));
+
+ StringBuilder sensorTimestampMessage = new StringBuilder();
+ for (int i = 0; i < sensorTime.size(); i++)
+ {
+ sensorTimestampMessage.append("frame [");
+ sensorTimestampMessage.append(i);
+ sensorTimestampMessage.append("] SENSOR_TIMESTAMP = ");
+ sensorTimestampMessage.append(sensorTime.get(i));
+ sensorTimestampMessage.append("\n");
+ }
+
+ mCollector.expectLessOrEqual(
+ "The standard deviation of frame interval is larger then threshold: " +
+ String.format("stddev = %.2f, threshold = %.2f.\n", stddev, THRESHOLD) +
+ sensorTimestampMessage.toString(),
+ THRESHOLD, stddev);
+ }
+ }
+
+ /**
+ * Check sensor capability prior to the test.
+ *
+ * @return true if the it is has the capability to execute the test.
+ */
+ private boolean checkCapability(ArrayList<Integer> supportedRawList) {
+ // make sure the sensor has manual support
+ if (!mStaticInfo.isCapabilitySupported(
+ CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL)) {
+ Log.w(TAG, "Full hardware level is not supported");
+ return false;
+ }
+
+ // get the list of supported RAW format
+ StreamConfigurationMap config = mStaticInfo.getValueFromKeyNonNull(
+ CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+
+ // check for the RAW support
+ supportedRawList.clear();
+ for (int rawFormat : RAW_FORMATS) {
+ if (!config.isOutputSupportedFor(rawFormat)) {
+ continue;
+ }
+ supportedRawList.add(rawFormat);
+ }
+
+ if (supportedRawList.size() == 0)
+ {
+ Log.w(TAG, "RAW output is not supported!");
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Return the sensor format to human readable string.
+ *
+ * @param format Sensor image format.
+ * @return Human readable string.
+ */
+ private String imageFormatToString(int format) {
+ switch (format) {
+ case ImageFormat.RAW10:
+ return "RAW10";
+ case ImageFormat.RAW_SENSOR:
+ return "RAW_SENSOR";
+ }
+
+ return "Unknown";
+ }
+
+ /**
+ * Setting up various classes prior to the request, e.g.: capture size, builder, callback and
+ * listener
+ *
+ * @return initialized variables that can be directly fed into prepareCaptureAndStartPreview().
+ */
+ private CaptureSetup initCaptureSetupForPreviewAndRaw() throws Exception
+ {
+ // capture size
+ Size previewSize = mOrderedPreviewSizes.get(0);
+ Rect activeArray = mStaticInfo.getActiveArraySizeChecked();
+ Size rawSize = new Size(activeArray.width(), activeArray.height());
+
+ // builder
+ CaptureRequest.Builder previewCaptureBuilder = mCamera.createCaptureRequest(
+ CameraDevice.TEMPLATE_PREVIEW);
+ CaptureRequest.Builder rawCaptureBuilder = mCamera.createCaptureRequest(
+ CameraDevice.TEMPLATE_STILL_CAPTURE);
+
+ // callback
+ SimpleCaptureCallback previewCaptureCallback = new SimpleCaptureCallback();
+ SimpleCaptureCallback rawCaptureCallback = new SimpleCaptureCallback();
+ SimpleImageReaderListener rawReaderListener = new SimpleImageReaderListener();
+
+ CaptureSetup setup = new CaptureSetup(previewSize, rawSize, previewCaptureBuilder,
+ rawCaptureBuilder, previewCaptureCallback, rawCaptureCallback, rawReaderListener);
+
+ return setup;
+ }
+
+ /**
+ * Construct an array of burst request with manual exposure and sensitivity.
+ * <p>
+ * For each capture request, 3A and post processing (noise reduction, sharpening, etc) will be
+ * turned off. Then exposure and sensitivity value will be configured, which are determined by
+ * EXPOSURE_MULIPLIERS and SENSITIVITY_MULTIPLIERS.
+ * </p>
+ *
+ * @param rawBurstBuilder The builder needs to have targets setup.
+ * @return An array list capture request for burst.
+ */
+ private ArrayList<CaptureRequest> createBurstRequest(CaptureRequest.Builder rawBurstBuilder)
+ {
+ return createBurstRequest(rawBurstBuilder, EXPOSURE_MULTIPLIERS, SENSITIVITY_MLTIPLIERS);
+ }
+
+ private ArrayList<CaptureRequest> createBurstRequest(CaptureRequest.Builder rawBurstBuilder,
+ long[] exposureMultipliers, int[] sensitivityMultipliers) {
+ // set manual mode
+ rawBurstBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);
+ rawBurstBuilder.set(CaptureRequest.CONTROL_AWB_MODE, CaptureRequest.CONTROL_AWB_MODE_OFF);
+ rawBurstBuilder.set(CaptureRequest.NOISE_REDUCTION_MODE,
+ CaptureRequest.NOISE_REDUCTION_MODE_OFF);
+ rawBurstBuilder.set(CaptureRequest.EDGE_MODE, CaptureRequest.EDGE_MODE_OFF);
+ // exposure has higher priority over frame duration; therefore the frame readout time:
+ // exposure time + overhead
+ rawBurstBuilder.set(CaptureRequest.SENSOR_FRAME_DURATION, 0L);
+
+ // get the exposure and sensitivity range
+ Range<Long> exposureRangeNs = new Range<Long>(mStaticInfo.getExposureMinimumOrDefault(),
+ mStaticInfo.getExposureMaximumOrDefault());
+
+ Range<Integer> isoRange = new Range<Integer>(mStaticInfo.getSensitivityMinimumOrDefault(),
+ mStaticInfo.getSensitivityMaximumOrDefault());
+
+ Log.i(TAG, String.format("Exposure time - max: %d, min: %d.", exposureRangeNs.getUpper(),
+ exposureRangeNs.getLower()));
+ Log.i(TAG, String.format("Sensitivity - max: %d, min: %d.", isoRange.getUpper(),
+ isoRange.getLower()));
+
+ // building burst request
+ int maxFramesBurst = exposureMultipliers.length * sensitivityMultipliers.length;
+ Log.i(TAG, String.format("Setting up burst = %d frames.", maxFramesBurst));
+ ArrayList<CaptureRequest> rawRequestList = new ArrayList<CaptureRequest>(maxFramesBurst);
+
+ for (int i = 0; i < exposureMultipliers.length; i++) {
+ for (int j = 0; j < sensitivityMultipliers.length; j++) {
+ long desiredExposure = Math.min(
+ exposureRangeNs.getLower() * exposureMultipliers[i],
+ exposureRangeNs.getUpper());
+
+ int desiredSensitivity =
+ Math.min(isoRange.getLower() * sensitivityMultipliers[j],
+ isoRange.getUpper());
+
+ rawBurstBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, desiredExposure);
+ rawBurstBuilder.set(CaptureRequest.SENSOR_SENSITIVITY, desiredSensitivity);
+
+ rawRequestList.add(rawBurstBuilder.build());
+ }
+ }
+ return rawRequestList;
+ }
+
+ /**
+ * Construct an array of burst request with 3A
+ * <p>
+ * For each capture request, 3A and post processing (noise reduction, sharpening, etc) will be
+ * turned on.
+ * </p>
+ *
+ * @param rawBurstBuilder The builder needs to have targets setup.
+ * @return An array list capture request for burst.
+ */
+ private ArrayList<CaptureRequest> createBurstRequestWith3A(
+ CaptureRequest.Builder rawBurstBuilder)
+ {
+ // set 3A mode to simulate regular still capture
+ rawBurstBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
+ rawBurstBuilder.set(CaptureRequest.CONTROL_AWB_MODE, CaptureRequest.CONTROL_AWB_MODE_AUTO);
+ rawBurstBuilder.set(CaptureRequest.NOISE_REDUCTION_MODE,
+ CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITY);
+ rawBurstBuilder.set(CaptureRequest.EDGE_MODE, CaptureRequest.EDGE_MODE_HIGH_QUALITY);
+
+ // building burst request
+ Log.i(TAG, String.format("Setting up burst = %d frames.", MAX_FRAMES_BURST));
+ ArrayList<CaptureRequest> rawRequestList = new ArrayList<CaptureRequest>(MAX_FRAMES_BURST);
+
+ for (int i = 0; i < MAX_FRAMES_BURST; i++) {
+ rawRequestList.add(rawBurstBuilder.build());
+ }
+
+ return rawRequestList;
+ }
+
+ /**
+ * An utility method to copy capture request builders. This is used for recovery purpose to
+ * reverse the changes we made to the builder.
+ *
+ * @param dst the builder to write into.
+ * @param src the builder that needs to be copied.
+ */
+ private void copyBurstRequetBuilder(CaptureRequest.Builder dst, CaptureRequest.Builder src)
+ {
+ dst.set(CaptureRequest.CONTROL_AE_MODE, src.get(CaptureRequest.CONTROL_AE_MODE));
+ dst.set(CaptureRequest.CONTROL_AWB_MODE, src.get(CaptureRequest.CONTROL_AWB_MODE));
+ dst.set(CaptureRequest.NOISE_REDUCTION_MODE, src.get(CaptureRequest.NOISE_REDUCTION_MODE));
+ dst.set(CaptureRequest.EDGE_MODE, src.get(CaptureRequest.EDGE_MODE));
+ dst.set(CaptureRequest.SENSOR_FRAME_DURATION,
+ src.get(CaptureRequest.SENSOR_FRAME_DURATION));
+ dst.set(CaptureRequest.SENSOR_EXPOSURE_TIME, src.get(CaptureRequest.SENSOR_EXPOSURE_TIME));
+ dst.set(CaptureRequest.SENSOR_SENSITIVITY, src.get(CaptureRequest.SENSOR_SENSITIVITY));
+ }
+
+ /**
+ * Draining the image reader and capture callback queue
+ *
+ * @param readerListener Image reader listener needs to be drained.
+ * @param captureCallback Capture callback needs to be drained.
+ * @throws Exception Exception from the queue.
+ */
+ private void drainQueues(SimpleImageReaderListener readerListener,
+ SimpleCaptureCallback captureCallback) throws Exception
+ {
+ for (int i = 0; i < MAX_FRAMES_BURST; i++) {
+ Image image = readerListener.getImage(CAPTURE_IMAGE_TIMEOUT_MS);
+ image.close();
+
+ CaptureResult result = captureCallback.getCaptureResult(
+ CAPTURE_IMAGE_TIMEOUT_MS);
+ long timestamp = result.get(CaptureResult.SENSOR_TIMESTAMP);
+ Log.d(TAG, String.format("timestamp = %d", timestamp));
+ }
+ }
+
+ /**
+ * Stop preview and remove the target surfaces inside the CaptureRequest.Builder.
+ *
+ * @param previewBuilder Configured builder for preview.
+ * @param rawBurstBuilder Configured builder for RAW.
+ * @throws Exception Exceptions from stopPreview.
+ */
+ private void stopPreviewAndClearSurface(CaptureRequest.Builder previewBuilder,
+ CaptureRequest.Builder rawBurstBuilder) throws Exception
+ {
+ previewBuilder.removeTarget(mPreviewSurface);
+ rawBurstBuilder.removeTarget(mPreviewSurface);
+ rawBurstBuilder.removeTarget(mReaderSurface);
+
+ stopPreview();
+ }
+
+ private void performTestRoutine(TestRoutine routine) throws Exception
+ {
+ for (String id : mCameraIds) {
+ try {
+ openDevice(id);
+
+ ArrayList<Integer> supportedRawList = new ArrayList<Integer>(RAW_FORMATS.length);
+ if (!checkCapability(supportedRawList)) {
+ Log.i(TAG, "Capability is not supported on camera " + id
+ + ". Skip the test.");
+ continue;
+ }
+
+ // test each supported RAW format
+ for (int rawFormat : supportedRawList) {
+ Log.i(TAG, "Testing format " + imageFormatToString(rawFormat) + ".");
+
+ // prepare preview and still RAW capture
+ CaptureSetup captureSetup = initCaptureSetupForPreviewAndRaw();
+
+ Size previewCaptureSize = captureSetup.getPreviewCaptureSize();
+ Size rawCaptureSize = captureSetup.getRawCaptureSize();
+
+ CaptureRequest.Builder previewBuilder = captureSetup.getPreviewRequestBuilder();
+ CaptureRequest.Builder rawBurstBuilder = captureSetup.getRawRequestBuilder();
+
+ SimpleCaptureCallback previewCaptureCallback =
+ captureSetup.getPreviewCaptureCallback();
+ SimpleCaptureCallback rawCaptureCallback = captureSetup.getRawCaptureCallback();
+ SimpleImageReaderListener rawReaderListener = captureSetup
+ .getRawReaderListener();
+
+ // start preview and prepare RAW capture
+ prepareCaptureAndStartPreview(previewBuilder, rawBurstBuilder,
+ previewCaptureSize, rawCaptureSize, rawFormat, previewCaptureCallback,
+ MAX_FRAMES_BURST, rawReaderListener);
+
+ // execute test routine
+ routine.execute(rawBurstBuilder, rawCaptureCallback, rawReaderListener,
+ rawFormat);
+
+ // clear out the surface and camera session
+ stopPreviewAndClearSurface(previewBuilder, rawBurstBuilder);
+ closeImageReader();
+ }
+ } finally {
+ closeDevice();
+ }
+ }
+ }
+}
diff --git a/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java b/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
index 67473e1..dbb609d 100644
--- a/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
+++ b/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
@@ -1310,13 +1310,11 @@
/* test if the explicitly named codec is present on the system */
if (explicitCodecName != null) {
- try {
- MediaCodec codec = MediaCodec.createByCodecName(explicitCodecName);
- if (codec != null) {
- codec.release();
- add(new Codec(explicitCodecName, null, mediaList));
- }
- } catch (Exception e) {}
+ MediaCodec codec = MediaCodec.createByCodecName(explicitCodecName);
+ if (codec != null) {
+ codec.release();
+ add(new Codec(explicitCodecName, null, mediaList));
+ }
}
} catch (Throwable t) {
Log.wtf("Constructor failed", t);
diff --git a/tests/tests/media/src/android/media/cts/AudioManagerTest.java b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
index f58e6ab..412d0ac 100644
--- a/tests/tests/media/src/android/media/cts/AudioManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
@@ -45,6 +45,7 @@
import android.media.MediaPlayer;
import android.os.Vibrator;
import android.provider.Settings;
+import android.provider.Settings.System;
import android.telephony.TelephonyManager;
import android.test.AndroidTestCase;
import android.view.SoundEffectConstants;
@@ -457,6 +458,88 @@
assertFalse(mAudioManager.isMusicActive());
}
+ public void testMute() {
+ int[] streams = {
+ AudioManager.STREAM_VOICE_CALL,
+ AudioManager.STREAM_MUSIC,
+ AudioManager.STREAM_RING,
+ AudioManager.STREAM_ALARM,
+ AudioManager.STREAM_NOTIFICATION,
+ AudioManager.STREAM_SYSTEM };
+
+ int muteAffectedStreams = System.getInt(mContext.getContentResolver(),
+ System.MUTE_STREAMS_AFFECTED,
+ // Same defaults as in AudioService. Should be kept in
+ // sync.
+ ((1 << AudioManager.STREAM_MUSIC) |
+ (1 << AudioManager.STREAM_RING) |
+ (1 << AudioManager.STREAM_NOTIFICATION) |
+ (1 << AudioManager.STREAM_SYSTEM)));
+ if (mUseFixedVolume) {
+ for (int i = 0; i < streams.length; i++) {
+ mAudioManager.adjustStreamVolume(streams[i], AudioManager.ADJUST_MUTE, 0);
+ assertFalse("Muting should not affect a fixed volume device.",
+ mAudioManager.isStreamMute(streams[i]));
+
+ mAudioManager.adjustStreamVolume(streams[i], AudioManager.ADJUST_TOGGLE_MUTE, 0);
+ assertFalse("Toggling mute should not affect a fixed volume device.",
+ mAudioManager.isStreamMute(streams[i]));
+
+ mAudioManager.setStreamMute(streams[i], true);
+ assertFalse("Muting should not affect a fixed volume device.",
+ mAudioManager.isStreamMute(streams[i]));
+ }
+ return;
+ }
+ // This ensures we're out of vibrate or silent modes.
+ mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+ for (int i = 0; i < streams.length; i++) {
+ // ensure each stream is on and turned up.
+ mAudioManager.setStreamVolume(streams[i], mAudioManager.getStreamMaxVolume(streams[i]),
+ 0);
+ if (((1 << streams[i]) & muteAffectedStreams) == 0) {
+ mAudioManager.adjustStreamVolume(streams[i], AudioManager.ADJUST_MUTE, 0);
+ assertFalse("Stream " + streams[i] + " should not be affected by mute.",
+ mAudioManager.isStreamMute(streams[i]));
+ mAudioManager.setStreamMute(streams[i], true);
+ assertFalse("Stream " + streams[i] + " should not be affected by mute.",
+ mAudioManager.isStreamMute(streams[i]));
+ mAudioManager.adjustStreamVolume(streams[i], AudioManager.ADJUST_TOGGLE_MUTE, 0);
+ assertFalse("Stream " + streams[i] + " should not be affected by mute.",
+ mAudioManager.isStreamMute(streams[i]));
+ continue;
+ }
+ mAudioManager.adjustStreamVolume(streams[i], AudioManager.ADJUST_MUTE, 0);
+ assertTrue("Muting stream " + streams[i] + " failed.",
+ mAudioManager.isStreamMute(streams[i]));
+
+ mAudioManager.adjustStreamVolume(streams[i], AudioManager.ADJUST_UNMUTE, 0);
+ assertFalse("Unmuting stream " + streams[i] + " failed.",
+ mAudioManager.isStreamMute(streams[i]));
+
+ mAudioManager.adjustStreamVolume(streams[i], AudioManager.ADJUST_TOGGLE_MUTE, 0);
+ assertTrue("Toggling mute on stream " + streams[i] + " failed.",
+ mAudioManager.isStreamMute(streams[i]));
+
+ mAudioManager.adjustStreamVolume(streams[i], AudioManager.ADJUST_TOGGLE_MUTE, 0);
+ assertFalse("Toggling mute on stream " + streams[i] + " failed.",
+ mAudioManager.isStreamMute(streams[i]));
+
+ mAudioManager.setStreamMute(streams[i], true);
+ assertTrue("Muting stream " + streams[i] + " using setStreamMute failed",
+ mAudioManager.isStreamMute(streams[i]));
+
+ // mute it three more times to verify the ref counting is gone.
+ mAudioManager.setStreamMute(streams[i], true);
+ mAudioManager.setStreamMute(streams[i], true);
+ mAudioManager.setStreamMute(streams[i], true);
+
+ mAudioManager.setStreamMute(streams[i], false);
+ assertFalse("Unmuting stream " + streams[i] + " using setStreamMute failed.",
+ mAudioManager.isStreamMute(streams[i]));
+ }
+ }
+
public void testSetInvalidRingerMode() {
int ringerMode = mAudioManager.getRingerMode();
mAudioManager.setRingerMode(-1337);
diff --git a/tests/tests/media/src/android/media/cts/AudioTrackTest.java b/tests/tests/media/src/android/media/cts/AudioTrackTest.java
index 4f6d27f..cea6b81 100644
--- a/tests/tests/media/src/android/media/cts/AudioTrackTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioTrackTest.java
@@ -1396,18 +1396,18 @@
final long MILLISECONDS_PER_SECOND = 1000;
AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR,
TEST_CONF, TEST_FORMAT, bufferSize, TEST_MODE);
- assertEquals(TEST_NAME, track.getState(), AudioTrack.STATE_NO_STATIC_DATA);
+ assertEquals(TEST_NAME, AudioTrack.STATE_NO_STATIC_DATA, track.getState());
// -------- test --------------
// test setLoopPoints and setPosition can be called here.
assertEquals(TEST_NAME,
- track.setPlaybackHeadPosition(bufferFrames/2),
- android.media.AudioTrack.SUCCESS);
+ android.media.AudioTrack.SUCCESS,
+ track.setPlaybackHeadPosition(bufferFrames/2));
assertEquals(TEST_NAME,
+ android.media.AudioTrack.SUCCESS,
track.setLoopPoints(
- 0 /*startInFrames*/, bufferFrames, 10 /*loopCount*/),
- android.media.AudioTrack.SUCCESS);
+ 0 /*startInFrames*/, bufferFrames, 10 /*loopCount*/));
// only need to write once to the static track
switch (TEST_FORMAT) {
case AudioFormat.ENCODING_PCM_8BIT: {
@@ -1415,35 +1415,35 @@
bufferSamples, TEST_SR,
testFrequency, TEST_SWEEP);
assertEquals(TEST_NAME,
- track.write(data, 0 /*offsetInBytes*/, data.length),
- bufferSamples);
+ bufferSamples,
+ track.write(data, 0 /*offsetInBytes*/, data.length));
} break;
case AudioFormat.ENCODING_PCM_16BIT: {
short data[] = createSoundDataInShortArray(
bufferSamples, TEST_SR,
testFrequency, TEST_SWEEP);
assertEquals(TEST_NAME,
- track.write(data, 0 /*offsetInBytes*/, data.length),
- bufferSamples);
+ bufferSamples,
+ track.write(data, 0 /*offsetInBytes*/, data.length));
} break;
case AudioFormat.ENCODING_PCM_FLOAT: {
float data[] = createSoundDataInFloatArray(
bufferSamples, TEST_SR,
testFrequency, TEST_SWEEP);
assertEquals(TEST_NAME,
+ bufferSamples,
track.write(data, 0 /*offsetInBytes*/, data.length,
- AudioTrack.WRITE_BLOCKING),
- bufferSamples);
+ AudioTrack.WRITE_BLOCKING));
} break;
}
- assertEquals(TEST_NAME, track.getState(), AudioTrack.STATE_INITIALIZED);
+ assertEquals(TEST_NAME, AudioTrack.STATE_INITIALIZED, track.getState());
// test setLoopPoints and setPosition can be called here.
assertEquals(TEST_NAME,
- track.setPlaybackHeadPosition(0 /*positionInFrames*/),
- android.media.AudioTrack.SUCCESS);
+ android.media.AudioTrack.SUCCESS,
+ track.setPlaybackHeadPosition(0 /*positionInFrames*/));
assertEquals(TEST_NAME,
- track.setLoopPoints(0 /*startInFrames*/, bufferFrames, TEST_LOOPS),
- android.media.AudioTrack.SUCCESS);
+ android.media.AudioTrack.SUCCESS,
+ track.setLoopPoints(0 /*startInFrames*/, bufferFrames, TEST_LOOPS));
track.play();
Thread.sleep(seconds * MILLISECONDS_PER_SECOND * (TEST_LOOPS + 1));
@@ -1452,7 +1452,7 @@
// Check position after looping. AudioTrack.getPlaybackHeadPosition() returns
// the running count of frames played, not the actual static buffer position.
int position = track.getPlaybackHeadPosition();
- assertEquals(TEST_NAME, position, bufferFrames * (TEST_LOOPS + 1));
+ assertEquals(TEST_NAME, bufferFrames * (TEST_LOOPS + 1), position);
track.stop();
Thread.sleep(WAIT_MSEC);
@@ -1802,6 +1802,70 @@
}
}
+ public void testVariableRatePlayback() throws Exception {
+ final String TEST_NAME = "testVariableRatePlayback";
+ final int TEST_SR = 24000;
+ final int TEST_FINAL_SR = 96000;
+ final int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
+ final int TEST_FORMAT = AudioFormat.ENCODING_PCM_8BIT; // required for test
+ final int TEST_MODE = AudioTrack.MODE_STATIC; // required for test
+ final int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+
+ final int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+ final int bufferSizeInBytes = minBuffSize * 100;
+ final int numChannels = AudioFormat.channelCountFromOutChannelMask(TEST_CONF);
+ final int bytesPerSample = AudioFormat.getBytesPerSample(TEST_FORMAT);
+ final int bytesPerFrame = numChannels * bytesPerSample;
+ final int frameCount = bufferSizeInBytes / bytesPerFrame;
+
+ AudioTrack track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF,
+ TEST_FORMAT, bufferSizeInBytes, TEST_MODE);
+
+ // create byte array and write it
+ byte[] vai = createSoundDataInByteArray(bufferSizeInBytes, TEST_SR, 600);
+ assertEquals(vai.length, track.write(vai, 0 /* offsetInBytes */, vai.length));
+
+ // sweep up test and sweep down test
+ int[] sampleRates = {TEST_SR, TEST_FINAL_SR};
+ int[] deltaMss = {10, 10};
+ int[] deltaFreqs = {200, -200};
+
+ for (int i = 0; i < 2; ++i) {
+ int remainingTime;
+ int sampleRate = sampleRates[i];
+ final int deltaMs = deltaMss[i];
+ final int deltaFreq = deltaFreqs[i];
+ final int lastCheckMs = 500; // check the last 500 ms
+
+ assertEquals(TEST_NAME, AudioTrack.SUCCESS, track.setPlaybackRate(sampleRate));
+ track.play();
+ do {
+ Thread.sleep(deltaMs);
+ final int position = track.getPlaybackHeadPosition();
+ sampleRate += deltaFreq;
+ sampleRate = Math.min(TEST_FINAL_SR, Math.max(TEST_SR, sampleRate));
+ assertEquals(TEST_NAME, AudioTrack.SUCCESS, track.setPlaybackRate(sampleRate));
+ remainingTime = (int)((double)(frameCount - position) * 1000
+ / sampleRate / bytesPerFrame);
+ } while (remainingTime >= lastCheckMs + deltaMs);
+
+ // ensure the final frequency set is constant and plays frames as expected
+ final int position1 = track.getPlaybackHeadPosition();
+ Thread.sleep(lastCheckMs);
+ final int position2 = track.getPlaybackHeadPosition();
+
+ final int tolerance60MsInFrames = sampleRate * 60 / 1000;
+ final int expected = lastCheckMs * sampleRate / 1000;
+ final int actual = position2 - position1;
+
+ // Log.d(TAG, "Variable Playback: expected(" + expected + ") actual(" + actual
+ // + ") diff(" + (expected - actual) + ")");
+ assertEquals(expected, actual, tolerance60MsInFrames);
+ track.stop();
+ }
+ track.release();
+ }
+
/* Do not run in JB-MR1. will be re-opened in the next platform release.
public void testResourceLeakage() throws Exception {
final int BUFFER_SIZE = 600 * 1024;
diff --git a/tests/tests/media/src/android/media/cts/AudioTrack_ListenerTest.java b/tests/tests/media/src/android/media/cts/AudioTrack_ListenerTest.java
index eb675fc..88ac4b4 100644
--- a/tests/tests/media/src/android/media/cts/AudioTrack_ListenerTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioTrack_ListenerTest.java
@@ -16,7 +16,9 @@
package android.media.cts;
+import java.util.Vector;
+import android.cts.util.CtsAndroidTestCase;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
@@ -24,17 +26,24 @@
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
-import android.test.AndroidTestCase;
+import android.util.Log;
+import com.android.cts.util.ReportLog;
+import com.android.cts.util.ResultType;
+import com.android.cts.util.ResultUnit;
-public class AudioTrack_ListenerTest extends AndroidTestCase {
- private boolean mOnMarkerReachedCalled;
- private boolean mOnPeriodicNotificationCalled;
+public class AudioTrack_ListenerTest extends CtsAndroidTestCase {
+ private final static String TAG = "AudioTrack_ListenerTest";
+ private final static int TEST_SR = 11025;
+ private final static int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
+ private final static int TEST_FORMAT = AudioFormat.ENCODING_PCM_8BIT;
+ private final static int TEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;
+ private final static int TEST_LOOP_FACTOR = 2; // # loops (>= 1) for static tracks
+ // simulated for streaming.
+ private final static int TEST_BUFFER_FACTOR = 25;
private boolean mIsHandleMessageCalled;
- private final int TEST_SR = 11025;
- private final int TEST_CONF = AudioFormat.CHANNEL_CONFIGURATION_MONO;
- private final int TEST_FORMAT = AudioFormat.ENCODING_PCM_8BIT;
- private final int TEST_MODE = AudioTrack.MODE_STREAM;
- private final int TEST_STREAM_TYPE1 = AudioManager.STREAM_MUSIC;
+ private int mMarkerPeriodInFrames;
+ private int mMarkerPosition;
+ private int mFrameCount;
private Handler mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
@@ -42,73 +51,199 @@
super.handleMessage(msg);
}
};
- private final int mMinBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
- private AudioTrack mAudioTrack;
- private OnPlaybackPositionUpdateListener mListener =
- new MockOnPlaybackPositionUpdateListener();
- private MakeSomethingAsynchronouslyAndLoop<AudioTrack> mMakeSomething;
-
- @Override
- protected void setUp() throws Exception
- {
- super.setUp();
- if (mAudioTrack == null) {
- mMakeSomething = new MakeSomethingAsynchronouslyAndLoop<AudioTrack>(
- new MakesSomething<AudioTrack>() {
- @Override
- public AudioTrack makeSomething()
- {
- return new AudioTrack(TEST_STREAM_TYPE1, TEST_SR, TEST_CONF,
- TEST_FORMAT, 2 * mMinBuffSize, TEST_MODE);
- }
- }
- );
- mAudioTrack = mMakeSomething.make();
- }
- }
public void testAudioTrackCallback() throws Exception {
- mAudioTrack.setPlaybackPositionUpdateListener(mListener);
- doTest(false /*customHandler*/);
+ doTest("Streaming Local Looper", true /*localTrack*/, false /*customHandler*/,
+ 30 /*periodsPerSecond*/, 2 /*markerPeriodsPerSecond*/, AudioTrack.MODE_STREAM);
}
public void testAudioTrackCallbackWithHandler() throws Exception {
- mAudioTrack.setPlaybackPositionUpdateListener(mListener, mHandler);
- doTest(true /*customHandler*/);
- // ToBeFixed: Handler#handleMessage() is never called
- // FIXME possibly because the new Handler() is missing the Looper parameter
+ // with 100 periods per second, trigger back-to-back notifications.
+ doTest("Streaming Private Handler", false /*localTrack*/, true /*customHandler*/,
+ 100 /*periodsPerSecond*/, 10 /*markerPeriodsPerSecond*/, AudioTrack.MODE_STREAM);
+ // verify mHandler is used only for accessing its associated Looper
assertFalse(mIsHandleMessageCalled);
}
- private void doTest(boolean customHandler) throws Exception {
- mOnMarkerReachedCalled = false;
- mOnPeriodicNotificationCalled = false;
- byte[] vai = AudioTrackTest.createSoundDataInByteArray(2 * mMinBuffSize, TEST_SR, 1024);
- int markerInFrames = vai.length / 4;
- assertEquals(AudioTrack.SUCCESS, mAudioTrack.setNotificationMarkerPosition(markerInFrames));
- int periodInFrames = vai.length / 2;
- assertEquals(AudioTrack.SUCCESS, mAudioTrack.setPositionNotificationPeriod(periodInFrames));
+ public void testStaticAudioTrackCallback() throws Exception {
+ doTest("Static", false /*localTrack*/, false /*customHandler*/,
+ 100 /*periodsPerSecond*/, 10 /*markerPeriodsPerSecond*/, AudioTrack.MODE_STATIC);
+ }
- boolean hasPlayed = false;
- int written = 0;
- while (written < vai.length) {
- written += mAudioTrack.write(vai, written, vai.length - written);
- if (!hasPlayed) {
- mAudioTrack.play();
- hasPlayed = true;
+ public void testStaticAudioTrackCallbackWithHandler() throws Exception {
+ doTest("Static Private Handler", false /*localTrack*/, true /*customHandler*/,
+ 30 /*periodsPerSecond*/, 2 /*markerPeriodsPerSecond*/, AudioTrack.MODE_STATIC);
+ // verify mHandler is used only for accessing its associated Looper
+ assertFalse(mIsHandleMessageCalled);
+ }
+
+ private class Stat {
+ public void add(double value) {
+ final double absValue = Math.abs(value);
+ mSum += value;
+ mSumAbs += absValue;
+ mMaxAbs = Math.max(mMaxAbs, absValue);
+ ++mCount;
+ }
+
+ public double getAvg() {
+ if (mCount == 0) {
+ return 0;
}
+ return mSum / mCount;
}
- final int numChannels = (TEST_CONF == AudioFormat.CHANNEL_CONFIGURATION_STEREO) ? 2 : 1;
- final int bytesPerSample = (TEST_FORMAT == AudioFormat.ENCODING_PCM_16BIT) ? 2 : 1;
- final int bytesPerFrame = numChannels * bytesPerSample;
- final int sampleLengthMs = (int)(1000 * ((float)vai.length / TEST_SR / bytesPerFrame));
- Thread.sleep(sampleLengthMs + 1000);
- if (!customHandler) {
- assertTrue(mOnMarkerReachedCalled);
- assertTrue(mOnPeriodicNotificationCalled);
+ public double getAvgAbs() {
+ if (mCount == 0) {
+ return 0;
+ }
+ return mSumAbs / mCount;
}
- mAudioTrack.stop();
+
+ public double getMaxAbs() {
+ return mMaxAbs;
+ }
+
+ private int mCount = 0;
+ private double mSum = 0;
+ private double mSumAbs = 0;
+ private double mMaxAbs = 0;
+ }
+
+ private void doTest(String reportName, boolean localTrack, boolean customHandler,
+ int periodsPerSecond, int markerPeriodsPerSecond, final int mode) throws Exception {
+ mIsHandleMessageCalled = false;
+ final int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);
+ final int bufferSizeInBytes;
+ if (mode == AudioTrack.MODE_STATIC && TEST_LOOP_FACTOR > 1) {
+ // use setLoopPoints for static mode
+ bufferSizeInBytes = minBuffSize * TEST_BUFFER_FACTOR;
+ mFrameCount = bufferSizeInBytes * TEST_LOOP_FACTOR;
+ } else {
+ bufferSizeInBytes = minBuffSize * TEST_BUFFER_FACTOR * TEST_LOOP_FACTOR;
+ mFrameCount = bufferSizeInBytes;
+ }
+
+ final AudioTrack track;
+ final MakeSomethingAsynchronouslyAndLoop<AudioTrack> makeSomething;
+ if (localTrack) {
+ makeSomething = null;
+ track = new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF,
+ TEST_FORMAT, bufferSizeInBytes, mode);
+ } else {
+ makeSomething =
+ new MakeSomethingAsynchronouslyAndLoop<AudioTrack>(
+ new MakesSomething<AudioTrack>() {
+ @Override
+ public AudioTrack makeSomething() {
+ return new AudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF,
+ TEST_FORMAT, bufferSizeInBytes, mode);
+ }
+ }
+ );
+ // create audiotrack on different thread's looper.
+ track = makeSomething.make();
+ }
+ final MockOnPlaybackPositionUpdateListener listener;
+ if (customHandler) {
+ listener = new MockOnPlaybackPositionUpdateListener(track, mHandler);
+ } else {
+ listener = new MockOnPlaybackPositionUpdateListener(track);
+ }
+
+ byte[] vai = AudioTrackTest.createSoundDataInByteArray(bufferSizeInBytes, TEST_SR, 1024);
+ int markerPeriods = Math.max(3, mFrameCount * markerPeriodsPerSecond / TEST_SR);
+ mMarkerPeriodInFrames = mFrameCount / markerPeriods;
+ markerPeriods = mFrameCount / mMarkerPeriodInFrames; // recalculate due to round-down
+ mMarkerPosition = mMarkerPeriodInFrames;
+ assertEquals(AudioTrack.SUCCESS,
+ track.setNotificationMarkerPosition(mMarkerPosition));
+ int updatePeriods = Math.max(3, mFrameCount * periodsPerSecond / TEST_SR);
+ final int updatePeriodInFrames = mFrameCount / updatePeriods;
+ updatePeriods = mFrameCount / updatePeriodInFrames; // recalculate due to round-down
+ assertEquals(AudioTrack.SUCCESS,
+ track.setPositionNotificationPeriod(updatePeriodInFrames));
+ // set NotificationPeriod before running to ensure better period positional accuracy.
+
+ if (mode == AudioTrack.MODE_STATIC && TEST_LOOP_FACTOR > 1) {
+ track.setLoopPoints(0, vai.length, TEST_LOOP_FACTOR - 1);
+ }
+ // write data with single blocking write, then play.
+ assertEquals(vai.length, track.write(vai, 0 /* offsetInBytes */, vai.length));
+ track.play();
+
+ // sleep until track completes playback - it must complete within 1 second
+ // of the expected length otherwise the periodic test should fail.
+ final int numChannels = AudioFormat.channelCountFromOutChannelMask(TEST_CONF);
+ final int bytesPerSample = AudioFormat.getBytesPerSample(TEST_FORMAT);
+ final int bytesPerFrame = numChannels * bytesPerSample;
+ final int trackLengthMs = (int)((double)mFrameCount * 1000 / TEST_SR / bytesPerFrame);
+ Thread.sleep(trackLengthMs + 1000);
+
+ // stop listening - we should be done.
+ listener.stop();
+
+ // Beware: stop() resets the playback head position for both static and streaming
+ // audio tracks, so stop() cannot be called while we're still logging playback
+ // head positions. We could recycle the track after stop(), which isn't done here.
+ track.stop();
+
+ // clean up
+ if (makeSomething != null) {
+ makeSomething.join();
+ }
+ listener.release();
+ track.release();
+
+ // collect statistics
+ final Vector<Integer> markerList = listener.getMarkerList();
+ final Vector<Integer> periodicList = listener.getPeriodicList();
+ // verify count of markers and periodic notifications.
+ assertEquals(markerPeriods, markerList.size());
+ assertEquals(updatePeriods, periodicList.size());
+ // verify actual playback head positions returned.
+ // the max diff should really be around 24 ms,
+ // but system load and stability will affect this test;
+ // we use 80ms limit here for failure.
+ final int tolerance80MsInFrames = TEST_SR * 80 / 1000;
+
+ Stat markerStat = new Stat();
+ for (int i = 0; i < markerPeriods; ++i) {
+ final int expected = mMarkerPeriodInFrames * (i + 1) * 1;
+ final int actual = markerList.get(i);
+ // Log.d(TAG, "Marker: expected(" + expected + ") actual(" + actual
+ // + ") diff(" + (actual - expected) + ")");
+ assertEquals(expected, actual, tolerance80MsInFrames);
+ markerStat.add((double)(actual - expected) * 1000 / TEST_SR);
+ }
+
+ Stat periodicStat = new Stat();
+ for (int i = 0; i < updatePeriods; ++i) {
+ final int expected = updatePeriodInFrames * (i + 1);
+ final int actual = periodicList.get(i);
+ // Log.d(TAG, "Update: expected(" + expected + ") actual(" + actual
+ // + ") diff(" + (actual - expected) + ")");
+ assertEquals(expected, actual, tolerance80MsInFrames);
+ periodicStat.add((double)(actual - expected) * 1000 / TEST_SR);
+ }
+
+ // report this
+ ReportLog log = getReportLog();
+ log.printValue(reportName + ": Average Marker diff", markerStat.getAvg(),
+ ResultType.LOWER_BETTER, ResultUnit.MS);
+ log.printValue(reportName + ": Maximum Marker abs diff", markerStat.getMaxAbs(),
+ ResultType.LOWER_BETTER, ResultUnit.MS);
+ log.printValue(reportName + ": Average Marker abs diff", markerStat.getAvgAbs(),
+ ResultType.LOWER_BETTER, ResultUnit.MS);
+ log.printValue(reportName + ": Average Periodic diff", periodicStat.getAvg(),
+ ResultType.LOWER_BETTER, ResultUnit.MS);
+ log.printValue(reportName + ": Maximum Periodic abs diff", periodicStat.getMaxAbs(),
+ ResultType.LOWER_BETTER, ResultUnit.MS);
+ log.printValue(reportName + ": Average Periodic abs diff", periodicStat.getAvgAbs(),
+ ResultType.LOWER_BETTER, ResultUnit.MS);
+ log.printSummary(reportName + ": Unified abs diff",
+ (periodicStat.getAvgAbs() + markerStat.getAvgAbs()) / 2,
+ ResultType.LOWER_BETTER, ResultUnit.MS);
}
// lightweight java.util.concurrent.Future*
@@ -195,27 +330,58 @@
private class MockOnPlaybackPositionUpdateListener
implements OnPlaybackPositionUpdateListener {
-
- public void onMarkerReached(AudioTrack track) {
- mOnMarkerReachedCalled = true;
+ public MockOnPlaybackPositionUpdateListener(AudioTrack track) {
+ mAudioTrack = track;
+ track.setPlaybackPositionUpdateListener(this);
}
- public void onPeriodicNotification(AudioTrack track) {
- mOnPeriodicNotificationCalled = true;
+ public MockOnPlaybackPositionUpdateListener(AudioTrack track, Handler handler) {
+ mAudioTrack = track;
+ track.setPlaybackPositionUpdateListener(this, handler);
}
- }
-
- @Override
- protected void tearDown() throws Exception {
- if (mMakeSomething != null) {
- mMakeSomething.join();
+ public synchronized void onMarkerReached(AudioTrack track) {
+ if (mIsTestActive) {
+ int position = mAudioTrack.getPlaybackHeadPosition();
+ mOnMarkerReachedCalled.add(position);
+ mMarkerPosition += mMarkerPeriodInFrames;
+ if (mMarkerPosition <= mFrameCount) {
+ assertEquals(AudioTrack.SUCCESS,
+ mAudioTrack.setNotificationMarkerPosition(mMarkerPosition));
+ }
+ } else {
+ fail("onMarkerReached called when not active");
+ }
}
- if (mAudioTrack != null) {
- mAudioTrack.release();
+
+ public synchronized void onPeriodicNotification(AudioTrack track) {
+ if (mIsTestActive) {
+ mOnPeriodicNotificationCalled.add(mAudioTrack.getPlaybackHeadPosition());
+ } else {
+ fail("onPeriodicNotification called when not active");
+ }
+ }
+
+ public synchronized void stop() {
+ mIsTestActive = false;
+ }
+
+ public Vector<Integer> getMarkerList() {
+ return mOnMarkerReachedCalled;
+ }
+
+ public Vector<Integer> getPeriodicList() {
+ return mOnPeriodicNotificationCalled;
+ }
+
+ public synchronized void release() {
+ mAudioTrack.setPlaybackPositionUpdateListener(null);
mAudioTrack = null;
}
- super.tearDown();
- }
+ private boolean mIsTestActive = true;
+ private AudioTrack mAudioTrack;
+ private Vector<Integer> mOnMarkerReachedCalled = new Vector<Integer>();
+ private Vector<Integer> mOnPeriodicNotificationCalled = new Vector<Integer>();
+ }
}
diff --git a/tests/tests/os/src/android/os/cts/BuildVersionTest.java b/tests/tests/os/src/android/os/cts/BuildVersionTest.java
index 3002ca3..6069ee6 100644
--- a/tests/tests/os/src/android/os/cts/BuildVersionTest.java
+++ b/tests/tests/os/src/android/os/cts/BuildVersionTest.java
@@ -28,8 +28,7 @@
public class BuildVersionTest extends TestCase {
private static final String LOG_TAG = "BuildVersionTest";
- private static final Set<String> EXPECTED_RELEASES =
- new HashSet<String>(Arrays.asList("5.0.1", "5.0.2"));
+ private static final Set<String> EXPECTED_RELEASES = new HashSet<String>(Arrays.asList("5.0"));
private static final int EXPECTED_SDK = 21;
private static final String EXPECTED_BUILD_VARIANT = "user";
private static final String EXPECTED_TAG = "release-keys";
diff --git a/tests/tests/os/src/android/os/cts/StrictModeTest.java b/tests/tests/os/src/android/os/cts/StrictModeTest.java
new file mode 100644
index 0000000..797f91f
--- /dev/null
+++ b/tests/tests/os/src/android/os/cts/StrictModeTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.cts;
+
+import android.os.StrictMode;
+import android.os.SystemClock;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import libcore.io.Streams;
+
+import java.io.ByteArrayOutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * Tests for {@link StrictMode}
+ */
+public class StrictModeTest extends AndroidTestCase {
+ private static final String TAG = "StrictModeTest";
+
+ private StrictMode.VmPolicy mPolicy;
+
+ @Override
+ protected void setUp() {
+ mPolicy = StrictMode.getVmPolicy();
+ }
+
+ @Override
+ protected void tearDown() {
+ StrictMode.setVmPolicy(mPolicy);
+ }
+
+ public void testCleartextNetwork() throws Exception {
+ StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
+ .detectCleartextNetwork()
+ .penaltyLog()
+ .build());
+
+ final long millis = System.currentTimeMillis();
+ final String msg = "Detected cleartext network traffic from UID "
+ + android.os.Process.myUid();
+
+ // Insecure connection should be detected
+ ((HttpURLConnection) new URL("http://android.com/").openConnection()).getResponseCode();
+
+ // Give system enough time to finish logging
+ SystemClock.sleep(5000);
+ assertTrue("Expected cleartext to be caught", readLogSince(millis).contains(msg));
+ }
+
+ public void testEncryptedNetwork() throws Exception {
+ StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
+ .detectCleartextNetwork()
+ .penaltyLog()
+ .build());
+
+ final long millis = System.currentTimeMillis();
+ final String msg = "Detected cleartext network traffic from UID "
+ + android.os.Process.myUid();
+
+ // Secure connection should be ignored
+ ((HttpURLConnection) new URL("https://android.com/").openConnection()).getResponseCode();
+
+ // Give system enough time to finish logging
+ SystemClock.sleep(5000);
+ assertFalse("Expected encrypted to be ignored", readLogSince(millis).contains(msg));
+ }
+
+ private String readLogSince(long millis) throws Exception {
+ final SimpleDateFormat format = new SimpleDateFormat("MM-DD HH:mm:ss.SSS");
+ final Process proc = new ProcessBuilder("logcat", "-t", format.format(new Date(millis)))
+ .redirectErrorStream(true).start();
+
+ final ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ Streams.copy(proc.getInputStream(), buf);
+ final int res = proc.waitFor();
+
+ Log.d(TAG, "Log output was " + buf.size() + " bytes, exit code " + res);
+ return new String(buf.toByteArray());
+ }
+}
diff --git a/tests/tests/print/Android.mk b/tests/tests/print/Android.mk
index 516f6a0..2ece2cf 100644
--- a/tests/tests/print/Android.mk
+++ b/tests/tests/print/Android.mk
@@ -18,15 +18,11 @@
LOCAL_MODULE_TAGS := optional
-LOCAL_SRC_FILES := $(call all-java-files-under, src) \
- src/android/print/cts/IPrivilegedOperations.aidl
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := CtsPrintTestCases
-LOCAL_STATIC_JAVA_LIBRARIES := mockito-target ctstestrunner ub-uiautomator
-
-# This test runner sets up/cleans up the device before/after running the tests.
-LOCAL_CTS_TEST_RUNNER := com.android.cts.tradefed.testtype.PrintTestRunner
+LOCAL_STATIC_JAVA_LIBRARIES := mockito-target ctstestrunner ub-uiautomator ctsdeviceutil
LOCAL_SDK_VERSION := current
diff --git a/tests/tests/print/src/android/print/cts/BasePrintTest.java b/tests/tests/print/src/android/print/cts/BasePrintTest.java
index c73bb64..31dfb9f 100644
--- a/tests/tests/print/src/android/print/cts/BasePrintTest.java
+++ b/tests/tests/print/src/android/print/cts/BasePrintTest.java
@@ -28,6 +28,7 @@
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.cts.util.SystemUtil;
import android.graphics.pdf.PdfDocument;
import android.os.Bundle;
import android.os.CancellationSignal;
@@ -73,12 +74,12 @@
private static final long OPERATION_TIMEOUT = 100000000;
- private static final String ARG_PRIVILEGED_OPS = "ARG_PRIVILEGED_OPS";
-
private static final String PRINT_SPOOLER_PACKAGE_NAME = "com.android.printspooler";
protected static final String PRINT_JOB_NAME = "Test";
+ private static final String PM_CLEAR_SUCCESS_OUTPUT = "Success";
+
private PrintDocumentActivity mActivity;
private Locale mOldLocale;
@@ -94,6 +95,7 @@
public void setUp() throws Exception {
// Make sure we start with a clean slate.
clearPrintSpoolerData();
+ enablePrintServices();
// Workaround for dexmaker bug: https://code.google.com/p/dexmaker/issues/detail?id=2
// Dexmaker is used by mockito.
@@ -139,6 +141,7 @@
resources.updateConfiguration(newConfiguration, displayMetrics);
}
+ disablePrintServices();
// Make sure the spooler is cleaned.
clearPrintSpoolerData();
}
@@ -272,6 +275,19 @@
}
}
+ protected void changeDuplex(String duplex) throws UiObjectNotFoundException {
+ try {
+ UiObject duplexSpinner = new UiObject(new UiSelector().resourceId(
+ "com.android.printspooler:id/duplex_spinner"));
+ duplexSpinner.click();
+ UiObject duplexOption = new UiObject(new UiSelector().text(duplex));
+ duplexOption.click();
+ } catch (UiObjectNotFoundException e) {
+ dumpWindowHierarchy();
+ throw new UiObjectNotFoundException(e);
+ }
+ }
+
protected void clickPrintButton() throws UiObjectNotFoundException {
try {
UiObject printButton = new UiObject(new UiSelector().resourceId(
@@ -306,9 +322,24 @@
}
protected void clearPrintSpoolerData() throws Exception {
- IPrivilegedOperations privilegedOps = IPrivilegedOperations.Stub.asInterface(
- getParams().getBinder(ARG_PRIVILEGED_OPS));
- privilegedOps.clearApplicationUserData(PRINT_SPOOLER_PACKAGE_NAME);
+ assertTrue("failed to clear print spooler data",
+ SystemUtil.runShellCommand(getInstrumentation(),
+ String.format("pm clear %s", PRINT_SPOOLER_PACKAGE_NAME))
+ .contains(PM_CLEAR_SUCCESS_OUTPUT));
+ }
+
+ private void enablePrintServices() throws Exception {
+ String pkgName = getInstrumentation().getContext().getPackageName();
+ String enabledServicesValue = String.format("%s/%s:%s/%s",
+ pkgName, FirstPrintService.class.getCanonicalName(),
+ pkgName, SecondPrintService.class.getCanonicalName());
+ SystemUtil.runShellCommand(getInstrumentation(),
+ "settings put secure enabled_print_services " + enabledServicesValue);
+ }
+
+ private void disablePrintServices() throws Exception {
+ SystemUtil.runShellCommand(getInstrumentation(),
+ "settings put secure enabled_print_services \"\"");
}
protected void verifyLayoutCall(InOrder inOrder, PrintDocumentAdapter mock,
diff --git a/tests/tests/print/src/android/print/cts/IPrivilegedOperations.aidl b/tests/tests/print/src/android/print/cts/IPrivilegedOperations.aidl
deleted file mode 100644
index 93c8c3e..0000000
--- a/tests/tests/print/src/android/print/cts/IPrivilegedOperations.aidl
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.print.cts;
-
-interface IPrivilegedOperations {
- boolean clearApplicationUserData(String packageName);
-}
diff --git a/tests/tests/print/src/android/print/cts/PrintDocumentAdapterContractTest.java b/tests/tests/print/src/android/print/cts/PrintDocumentAdapterContractTest.java
index 538472e..c17583f 100644
--- a/tests/tests/print/src/android/print/cts/PrintDocumentAdapterContractTest.java
+++ b/tests/tests/print/src/android/print/cts/PrintDocumentAdapterContractTest.java
@@ -353,6 +353,12 @@
// Wait for layout.
waitForLayoutAdapterCallbackCount(5);
+ // Change the duplex.
+ changeDuplex("Short edge");
+
+ // Wait for layout.
+ waitForLayoutAdapterCallbackCount(6);
+
// Click the print button.
clickPrintButton();
@@ -394,6 +400,7 @@
.setResolution(new Resolution("300x300", "300x300", 300, 300))
.setMinMargins(Margins.NO_MARGINS)
.setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+ .setDuplexMode(PrintAttributes.DUPLEX_MODE_LONG_EDGE)
.build();
verifyLayoutCall(inOrder, adapter, secondOldAttributes, secondNewAttributes, true);
@@ -406,6 +413,7 @@
.setResolution(new Resolution("300x300", "300x300", 300, 300))
.setMinMargins(Margins.NO_MARGINS)
.setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+ .setDuplexMode(PrintAttributes.DUPLEX_MODE_LONG_EDGE)
.build();
verifyLayoutCall(inOrder, adapter, thirdOldAttributes, thirdNewAttributes, true);
@@ -418,6 +426,7 @@
.setResolution(new Resolution("300x300", "300x300", 300, 300))
.setMinMargins(Margins.NO_MARGINS)
.setColorMode(PrintAttributes.COLOR_MODE_COLOR)
+ .setDuplexMode(PrintAttributes.DUPLEX_MODE_LONG_EDGE)
.build();
verifyLayoutCall(inOrder, adapter, fourthOldAttributes, fourthNewAttributes, true);
@@ -430,11 +439,25 @@
.setResolution(new Resolution("300x300", "300x300", 300, 300))
.setMinMargins(Margins.NO_MARGINS)
.setColorMode(PrintAttributes.COLOR_MODE_MONOCHROME)
+ .setDuplexMode(PrintAttributes.DUPLEX_MODE_LONG_EDGE)
.build();
verifyLayoutCall(inOrder, adapter, fifthOldAttributes, fifthNewAttributes, true);
+ // We changed the duplex which triggers a layout. Since we passed
+ // false to the layout callback meaning that the content didn't change,
+ // there shouldn't be a next call to write.
+ PrintAttributes sixthOldAttributes = fifthNewAttributes;
+ PrintAttributes sixthNewAttributes = new PrintAttributes.Builder()
+ .setMediaSize(MediaSize.ISO_A4.asLandscape())
+ .setResolution(new Resolution("300x300", "300x300", 300, 300))
+ .setMinMargins(Margins.NO_MARGINS)
+ .setColorMode(PrintAttributes.COLOR_MODE_MONOCHROME)
+ .setDuplexMode(PrintAttributes.DUPLEX_MODE_SHORT_EDGE)
+ .build();
+ verifyLayoutCall(inOrder, adapter, sixthOldAttributes, sixthNewAttributes, true);
+
// When print is pressed we ask for a layout which is *not* for preview.
- verifyLayoutCall(inOrder, adapter, fifthNewAttributes, fifthNewAttributes, false);
+ verifyLayoutCall(inOrder, adapter, sixthNewAttributes, sixthNewAttributes, false);
// When print is pressed we ask for all selected pages but we got
// them when asking for the ones for a preview, and the adapter does
@@ -1573,8 +1596,13 @@
.addResolution(new Resolution("200x200", "200x200", 200, 200), true)
.addResolution(new Resolution("300x300", "300x300", 300, 300), false)
.setColorModes(PrintAttributes.COLOR_MODE_COLOR
- | PrintAttributes.COLOR_MODE_MONOCHROME,
- PrintAttributes.COLOR_MODE_MONOCHROME)
+ | PrintAttributes.COLOR_MODE_MONOCHROME,
+ PrintAttributes.COLOR_MODE_MONOCHROME
+ )
+ .setDuplexModes(PrintAttributes.DUPLEX_MODE_LONG_EDGE
+ | PrintAttributes.DUPLEX_MODE_SHORT_EDGE,
+ PrintAttributes.DUPLEX_MODE_LONG_EDGE
+ )
.build();
PrinterInfo secondPrinter = new PrinterInfo.Builder(secondPrinterId,
"Second printer", PrinterInfo.STATUS_IDLE)
diff --git a/tests/tests/security/src/android/security/cts/KernelSettingsTest.java b/tests/tests/security/src/android/security/cts/KernelSettingsTest.java
index f3163be..7edd659 100644
--- a/tests/tests/security/src/android/security/cts/KernelSettingsTest.java
+++ b/tests/tests/security/src/android/security/cts/KernelSettingsTest.java
@@ -115,6 +115,25 @@
private static native boolean supportsXattr();
+ /**
+ * ICMP redirects should be disabled.
+ */
+ public void testNoIcmpRedirects() throws IOException {
+ try {
+ assertEquals("ICMP redirects are enabled for IPv4.",
+ "0", getFile("/proc/sys/net/ipv4/conf/all/accept_redirects"));
+ } catch (FileNotFoundException e) {
+ // Odd. The file doesn't exist... Assume we're ok.
+ }
+
+ try {
+ assertEquals("ICMP redirects are enabled for IPv6.",
+ "0", getFile("/proc/sys/net/ipv6/conf/all/accept_redirects"));
+ } catch (FileNotFoundException e) {
+ // Odd. The file doesn't exist... Assume we're ok.
+ }
+ }
+
private String getFile(String filename) throws IOException {
BufferedReader in = null;
try {
diff --git a/tests/tests/speech/Android.mk b/tests/tests/speech/Android.mk
index 6bec012..3ab78b8 100755
--- a/tests/tests/speech/Android.mk
+++ b/tests/tests/speech/Android.mk
@@ -27,6 +27,7 @@
LOCAL_PACKAGE_NAME := CtsSpeechTestCases
-LOCAL_SDK_VERSION := current
+# Needed for testing M API
+#LOCAL_SDK_VERSION := current
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/speech/src/android/speech/tts/cts/StubTextToSpeechService.java b/tests/tests/speech/src/android/speech/tts/cts/StubTextToSpeechService.java
index 5e6bb41..7b5baca 100644
--- a/tests/tests/speech/src/android/speech/tts/cts/StubTextToSpeechService.java
+++ b/tests/tests/speech/src/android/speech/tts/cts/StubTextToSpeechService.java
@@ -20,12 +20,17 @@
import android.speech.tts.SynthesisRequest;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeechService;
+import android.util.Log;
/**
* Stub implementation of {@link TextToSpeechService}. Used for testing the
* TTS engine API.
*/
public class StubTextToSpeechService extends TextToSpeechService {
+ private static final String LOG_TAG = "StubTextToSpeechService";
+
+ // Object that onSynthesizeText will #wait on, if set to non-null
+ public static volatile Object sSynthesizeTextWait;
@Override
protected String[] onGetLanguage() {
@@ -51,6 +56,18 @@
if (callback.start(16000, AudioFormat.ENCODING_PCM_16BIT, 1) != TextToSpeech.SUCCESS) {
return;
}
+
+ final Object synthesizeTextWait = sSynthesizeTextWait;
+ if (synthesizeTextWait != null) {
+ synchronized (synthesizeTextWait) {
+ try {
+ synthesizeTextWait.wait(10000); // 10s timeout
+ } catch (InterruptedException e) {
+ Log.e(LOG_TAG, "onSynthesizeText wait interrupted", e);
+ }
+ }
+ }
+
byte[] data = { 0x01, 0x2 };
if (callback.audioAvailable(data, 0, data.length) != TextToSpeech.SUCCESS) {
return;
diff --git a/tests/tests/speech/src/android/speech/tts/cts/TextToSpeechServiceTest.java b/tests/tests/speech/src/android/speech/tts/cts/TextToSpeechServiceTest.java
index c19f6c0..7425ecf 100644
--- a/tests/tests/speech/src/android/speech/tts/cts/TextToSpeechServiceTest.java
+++ b/tests/tests/speech/src/android/speech/tts/cts/TextToSpeechServiceTest.java
@@ -37,6 +37,7 @@
@Override
protected void setUp() throws Exception {
super.setUp();
+ StubTextToSpeechService.sSynthesizeTextWait = null;
mTts = TextToSpeechWrapper.createTextToSpeechMockWrapper(getContext());
assertNotNull(mTts);
}
@@ -74,6 +75,31 @@
assertTrue("speak() completion timeout", waitForUtterance());
}
+ public void testSpeakStop() throws Exception {
+ final Object synthesizeTextWait = new Object();
+ StubTextToSpeechService.sSynthesizeTextWait = synthesizeTextWait;
+
+ getTts().stop();
+ final int iterations = 20;
+ for (int i = 0; i < iterations; i++) {
+ int result = getTts().speak(UTTERANCE, TextToSpeech.QUEUE_ADD, null,
+ UTTERANCE_ID + Integer.toString(i));
+ assertEquals("speak() failed", TextToSpeech.SUCCESS, result);
+ }
+ getTts().stop();
+
+ // Wake up the Stubs #onSynthesizeSpeech (one that will be stopped in-progress)
+ synchronized (synthesizeTextWait) {
+ synthesizeTextWait.notify();
+ }
+
+ for (int i = 0; i < iterations; i++) {
+ assertTrue("speak() stop callback timeout", mTts.waitForStop(
+ UTTERANCE_ID + Integer.toString(i)));
+ }
+ }
+
+
public void testMediaPlayerFails() throws Exception {
File sampleFile = new File(Environment.getExternalStorageDirectory(), "notsound.wav");
try {
diff --git a/tests/tests/speech/src/android/speech/tts/cts/TextToSpeechTest.java b/tests/tests/speech/src/android/speech/tts/cts/TextToSpeechTest.java
index 69acdd0..c83304c 100644
--- a/tests/tests/speech/src/android/speech/tts/cts/TextToSpeechTest.java
+++ b/tests/tests/speech/src/android/speech/tts/cts/TextToSpeechTest.java
@@ -124,6 +124,22 @@
assertTrue("speak() completion timeout", waitForUtterance());
}
+
+ public void testSpeakStop() throws Exception {
+ getTts().stop();
+ final int iterations = 20;
+ for (int i = 0; i < iterations; i++) {
+ int result = getTts().speak(SAMPLE_TEXT, TextToSpeech.QUEUE_ADD, null,
+ UTTERANCE_ID + Integer.toString(i));
+ assertEquals("speak() failed", TextToSpeech.SUCCESS, result);
+ }
+ getTts().stop();
+ for (int i = 0; i < iterations; i++) {
+ assertTrue("speak() stop callback timeout", mTts.waitForStop(
+ UTTERANCE_ID + Integer.toString(i)));
+ }
+ }
+
public void testGetEnginesIncludesDefault() throws Exception {
if (mTts == null) {
return;
diff --git a/tests/tests/speech/src/android/speech/tts/cts/TextToSpeechWrapper.java b/tests/tests/speech/src/android/speech/tts/cts/TextToSpeechWrapper.java
index f0d55bf..9d460e2 100644
--- a/tests/tests/speech/src/android/speech/tts/cts/TextToSpeechWrapper.java
+++ b/tests/tests/speech/src/android/speech/tts/cts/TextToSpeechWrapper.java
@@ -19,9 +19,10 @@
import android.media.MediaPlayer;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
-import android.speech.tts.TextToSpeech.OnUtteranceCompletedListener;
+import android.speech.tts.UtteranceProgressListener;
import android.util.Log;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
@@ -65,7 +66,7 @@
if (!mInitListener.waitForInit()) {
return false;
}
- mTts.setOnUtteranceCompletedListener(mUtteranceListener);
+ mTts.setOnUtteranceProgressListener(mUtteranceListener);
return true;
}
@@ -73,6 +74,10 @@
return mUtteranceListener.waitForComplete(utteranceId);
}
+ public boolean waitForStop(String utteranceId) throws InterruptedException {
+ return mUtteranceListener.waitForStop(utteranceId);
+ }
+
public TextToSpeech getTts() {
return mTts;
}
@@ -139,12 +144,16 @@
/**
* Listener for waiting for utterance completion.
*/
- private static class UtteranceWaitListener implements OnUtteranceCompletedListener {
+ private static class UtteranceWaitListener extends UtteranceProgressListener {
private final Lock mLock = new ReentrantLock();
private final Condition mDone = mLock.newCondition();
+ private final HashSet<String> mStartedUtterances = new HashSet<String>();
+ private final HashSet<String> mStoppedUtterances = new HashSet<String>();
+ private final HashMap<String, Integer> mErredUtterances = new HashMap<String, Integer>();
private final HashSet<String> mCompletedUtterances = new HashSet<String>();
- public void onUtteranceCompleted(String utteranceId) {
+ @Override
+ public void onDone(String utteranceId) {
mLock.lock();
try {
mCompletedUtterances.add(utteranceId);
@@ -154,6 +163,49 @@
}
}
+ @Override
+ public void onError(String utteranceId) {
+ mLock.lock();
+ try {
+ mErredUtterances.put(utteranceId, -1);
+ mDone.signal();
+ } finally {
+ mLock.unlock();
+ }
+ }
+
+ @Override
+ public void onError(String utteranceId, int errorCode) {
+ mLock.lock();
+ try {
+ mErredUtterances.put(utteranceId, errorCode);
+ mDone.signal();
+ } finally {
+ mLock.unlock();
+ }
+ }
+
+ @Override
+ public void onStart(String utteranceId) {
+ mLock.lock();
+ try {
+ mStartedUtterances.add(utteranceId);
+ } finally {
+ mLock.unlock();
+ }
+ }
+
+ @Override
+ public void onStop(String utteranceId, boolean isStarted) {
+ mLock.lock();
+ try {
+ mStoppedUtterances.add(utteranceId);
+ mDone.signal();
+ } finally {
+ mLock.unlock();
+ }
+ }
+
public boolean waitForComplete(String utteranceId)
throws InterruptedException {
long timeOutNanos = TimeUnit.MILLISECONDS.toNanos(TTS_INIT_MAX_WAIT_TIME);
@@ -170,6 +222,23 @@
mLock.unlock();
}
}
+
+ public boolean waitForStop(String utteranceId)
+ throws InterruptedException {
+ long timeOutNanos = TimeUnit.MILLISECONDS.toNanos(TTS_INIT_MAX_WAIT_TIME);
+ mLock.lock();
+ try {
+ while (!mStoppedUtterances.remove(utteranceId)) {
+ if (timeOutNanos <= 0) {
+ return false;
+ }
+ timeOutNanos = mDone.awaitNanos(timeOutNanos);
+ }
+ return true;
+ } finally {
+ mLock.unlock();
+ }
+ }
}
/**
diff --git a/tests/tests/telephony/AndroidManifest.xml b/tests/tests/telephony/AndroidManifest.xml
index 31abf12..a87a54b 100644
--- a/tests/tests/telephony/AndroidManifest.xml
+++ b/tests/tests/telephony/AndroidManifest.xml
@@ -31,6 +31,9 @@
<uses-permission android:name="android.permission.BLUETOOTH" />
<application>
+ <provider android:name="android.telephony.cts.MmsPduProvider"
+ android:authorities="telephonyctstest"
+ android:grantUriPermissions="true" />
<uses-library android:name="android.test.runner" />
</application>
diff --git a/tests/tests/telephony/src/android/telephony/cts/CellInfoTest.java b/tests/tests/telephony/src/android/telephony/cts/CellInfoTest.java
new file mode 100644
index 0000000..5b88525
--- /dev/null
+++ b/tests/tests/telephony/src/android/telephony/cts/CellInfoTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.telephony.cts;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.telephony.CellInfo;
+import android.telephony.PhoneStateListener;
+import android.telephony.TelephonyManager;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import java.util.List;
+
+/**
+ * Test TelephonyManager.getAllCellInfo()
+ * <p>
+ * TODO(chesnutt): test onCellInfoChanged() once the implementation
+ * of async callbacks is complete (see http://b/13788638)
+ */
+public class CellInfoTest extends AndroidTestCase{
+ private final Object mLock = new Object();
+ private TelephonyManager mTelephonyManager;
+ private static ConnectivityManager mCm;
+ private static final String TAG = "android.telephony.cts.CellInfoTest";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mTelephonyManager =
+ (TelephonyManager)getContext().getSystemService(Context.TELEPHONY_SERVICE);
+ mCm = (ConnectivityManager)getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
+ }
+
+ public void testCellInfo() throws Throwable {
+ if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
+ Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+ return;
+ }
+
+ // getAllCellInfo should never return null, and there should
+ // be at least one entry.
+ List<CellInfo> allCellInfo = mTelephonyManager.getAllCellInfo();
+ assertNotNull("TelephonyManager.getAllCellInfo() returned NULL!", allCellInfo);
+ assertTrue("TelephonyManager.getAllCellInfo() returned zero-length list!",
+ allCellInfo.size() > 0);
+ }
+}
diff --git a/tests/tests/telephony/src/android/telephony/cts/CellLocationTest.java b/tests/tests/telephony/src/android/telephony/cts/CellLocationTest.java
index c1f5757..9205f0e 100644
--- a/tests/tests/telephony/src/android/telephony/cts/CellLocationTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/CellLocationTest.java
@@ -60,6 +60,14 @@
return;
}
+ // getCellLocation should never return null,
+ // but that is allowed if the cell network type
+ // is LTE (since there is no LteCellLocation class)
+ if (mTelephonyManager.getNetworkType() != TelephonyManager.NETWORK_TYPE_LTE) {
+ assertNotNull("TelephonyManager.getCellLocation() returned null!",
+ mTelephonyManager.getCellLocation());
+ }
+
CellLocation cl = CellLocation.getEmpty();
if (cl instanceof GsmCellLocation) {
GsmCellLocation gcl = (GsmCellLocation) cl;
diff --git a/tests/tests/telephony/src/android/telephony/cts/MmsPduProvider.java b/tests/tests/telephony/src/android/telephony/cts/MmsPduProvider.java
new file mode 100644
index 0000000..08164ee
--- /dev/null
+++ b/tests/tests/telephony/src/android/telephony/cts/MmsPduProvider.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.cts;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+import android.text.TextUtils;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+/**
+ * A simple provider to send MMS PDU to platform MMS service
+ */
+public class MmsPduProvider extends ContentProvider {
+ @Override
+ public boolean onCreate() {
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ // Not supported
+ return null;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ // Not supported
+ return null;
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ // Not supported
+ return null;
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ // Not supported
+ return 0;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ // Not supported
+ return 0;
+ }
+
+ @Override
+ public ParcelFileDescriptor openFile(Uri uri, String fileMode) throws FileNotFoundException {
+ File file = new File(getContext().getCacheDir(), uri.getPath());
+ int mode = (TextUtils.equals(fileMode, "r") ? ParcelFileDescriptor.MODE_READ_ONLY :
+ ParcelFileDescriptor.MODE_WRITE_ONLY
+ |ParcelFileDescriptor.MODE_TRUNCATE
+ |ParcelFileDescriptor.MODE_CREATE);
+ return ParcelFileDescriptor.open(file, mode);
+ }
+}
diff --git a/tests/tests/telephony/src/android/telephony/cts/MmsTest.java b/tests/tests/telephony/src/android/telephony/cts/MmsTest.java
new file mode 100644
index 0000000..4d2e35b
--- /dev/null
+++ b/tests/tests/telephony/src/android/telephony/cts/MmsTest.java
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.cts;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
+import android.os.SystemClock;
+import android.telephony.SmsManager;
+import android.telephony.TelephonyManager;
+import android.test.AndroidTestCase;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.google.android.mms.ContentType;
+import com.google.android.mms.InvalidHeaderValueException;
+import com.google.android.mms.pdu.CharacterSets;
+import com.google.android.mms.pdu.EncodedStringValue;
+import com.google.android.mms.pdu.GenericPdu;
+import com.google.android.mms.pdu.PduBody;
+import com.google.android.mms.pdu.PduComposer;
+import com.google.android.mms.pdu.PduHeaders;
+import com.google.android.mms.pdu.PduParser;
+import com.google.android.mms.pdu.PduPart;
+import com.google.android.mms.pdu.SendConf;
+import com.google.android.mms.pdu.SendReq;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Random;
+
+/**
+ * Test sending MMS using {@link android.telephony.SmsManager}.
+ */
+public class MmsTest extends AndroidTestCase {
+ private static final String TAG = "MmsTest";
+
+ private static final String ACTION_MMS_SENT = "CTS_MMS_SENT_ACTION";
+ private static final long DEFAULT_EXPIRY_TIME = 7 * 24 * 60 * 60;
+ private static final int DEFAULT_PRIORITY = PduHeaders.PRIORITY_NORMAL;
+
+ private static final String SUBJECT = "CTS MMS Test";
+ private static final String MESSAGE_BODY = "CTS MMS test message body";
+ private static final String TEXT_PART_FILENAME = "text_0.txt";
+ private static final String sSmilText =
+ "<smil>" +
+ "<head>" +
+ "<layout>" +
+ "<root-layout/>" +
+ "<region height=\"100%%\" id=\"Text\" left=\"0%%\" top=\"0%%\" width=\"100%%\"/>" +
+ "</layout>" +
+ "</head>" +
+ "<body>" +
+ "<par dur=\"8000ms\">" +
+ "<text src=\"%s\" region=\"Text\"/>" +
+ "</par>" +
+ "</body>" +
+ "</smil>";
+
+ private static final long SENT_TIMEOUT = 1000 * 60 * 5; // 5 minutes
+
+ private static final String PROVIDER_AUTHORITY = "telephonyctstest";
+
+ private Random mRandom;
+ private SentReceiver mSentReceiver;
+
+ private static class SentReceiver extends BroadcastReceiver {
+ private final Object mLock;
+ private boolean mSuccess;
+ private boolean mDone;
+
+ public SentReceiver() {
+ mLock = new Object();
+ mSuccess = false;
+ mDone = false;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.i(TAG, "Action " + intent.getAction());
+ if (!ACTION_MMS_SENT.equals(intent.getAction())) {
+ return;
+ }
+ final int resultCode = getResultCode();
+ if (resultCode == Activity.RESULT_OK) {
+ final byte[] response = intent.getByteArrayExtra(SmsManager.EXTRA_MMS_DATA);
+ if (response != null) {
+ final GenericPdu pdu = new PduParser(
+ response, shouldParseContentDisposition()).parse();
+ if (pdu != null && pdu instanceof SendConf) {
+ final SendConf sendConf = (SendConf) pdu;
+ if (sendConf.getResponseStatus() == PduHeaders.RESPONSE_STATUS_OK) {
+ mSuccess = true;
+ } else {
+ Log.e(TAG, "SendConf response status=" + sendConf.getResponseStatus());
+ }
+ } else {
+ Log.e(TAG, "Not a SendConf: " +
+ (pdu != null ? pdu.getClass().getCanonicalName() : "NULL"));
+ }
+ } else {
+ Log.e(TAG, "Empty response");
+ }
+ } else {
+ Log.e(TAG, "Failure result=" + resultCode);
+ if (resultCode == SmsManager.MMS_ERROR_HTTP_FAILURE) {
+ final int httpError = intent.getIntExtra(SmsManager.EXTRA_MMS_HTTP_STATUS, 0);
+ Log.e(TAG, "HTTP failure=" + httpError);
+ }
+ }
+ synchronized (mLock) {
+ mDone = true;
+ mLock.notify();
+ }
+ }
+
+ public boolean waitForSuccess(long timeout) {
+ synchronized(mLock) {
+ final long startTime = SystemClock.elapsedRealtime();
+ long waitTime = timeout;
+ while (waitTime > 0) {
+ try {
+ mLock.wait(waitTime);
+ } catch (InterruptedException e) {
+ // Ignore
+ }
+ if (mDone) {
+ break;
+ }
+ waitTime = timeout - (SystemClock.elapsedRealtime() - startTime);
+ }
+ Log.i(TAG, "Wait for sent: done=" + mDone + ", success=" + mSuccess);
+ return mDone && mSuccess;
+ }
+
+ }
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mRandom = new Random();
+ }
+
+ public void testSendMmsMessage() {
+ Log.i(TAG, "testSendMmsMessage");
+ final Context context = getContext();
+ // Register sent receiver
+ mSentReceiver = new SentReceiver();
+ context.registerReceiver(mSentReceiver, new IntentFilter(ACTION_MMS_SENT));
+ // Create local provider file for sending PDU
+ final String fileName = "send." + String.valueOf(Math.abs(mRandom.nextLong())) + ".dat";
+ final File sendFile = new File(context.getCacheDir(), fileName);
+ final String selfNumber = getSimNumber(context);
+ assertTrue(!TextUtils.isEmpty(selfNumber));
+ final byte[] pdu = buildPdu(context, selfNumber, SUBJECT, MESSAGE_BODY);
+ assertNotNull(pdu);
+ assertTrue(writePdu(sendFile, pdu));
+ final Uri contentUri = (new Uri.Builder())
+ .authority(PROVIDER_AUTHORITY)
+ .path(fileName)
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .build();
+ // Send
+ final PendingIntent pendingIntent = PendingIntent.getBroadcast(
+ context, 0, new Intent(ACTION_MMS_SENT), 0);
+ SmsManager.getDefault().sendMultimediaMessage(context,
+ contentUri, null/*locationUrl*/, null/*configOverrides*/, pendingIntent);
+ assertTrue(mSentReceiver.waitForSuccess(SENT_TIMEOUT));
+ sendFile.delete();
+ }
+
+ private static boolean writePdu(File file, byte[] pdu) {
+ FileOutputStream writer = null;
+ try {
+ writer = new FileOutputStream(file);
+ writer.write(pdu);
+ return true;
+ } catch (final IOException e) {
+ return false;
+ } finally {
+ if (writer != null) {
+ try {
+ writer.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ }
+
+ private byte[] buildPdu(Context context, String selfNumber, String subject, String text) {
+ final SendReq req = new SendReq();
+ // From, per spec
+ req.setFrom(new EncodedStringValue(selfNumber));
+ // To
+ final String[] recipients = new String[1];
+ recipients[0] = selfNumber;
+ final EncodedStringValue[] encodedNumbers = EncodedStringValue.encodeStrings(recipients);
+ if (encodedNumbers != null) {
+ req.setTo(encodedNumbers);
+ }
+ // Subject
+ if (!TextUtils.isEmpty(subject)) {
+ req.setSubject(new EncodedStringValue(subject));
+ }
+ // Date
+ req.setDate(System.currentTimeMillis() / 1000);
+ // Body
+ final PduBody body = new PduBody();
+ // Add text part. Always add a smil part for compatibility, without it there
+ // may be issues on some carriers/client apps
+ final int size = addTextPart(body, text, true/* add text smil */);
+ req.setBody(body);
+ // Message size
+ req.setMessageSize(size);
+ // Message class
+ req.setMessageClass(PduHeaders.MESSAGE_CLASS_PERSONAL_STR.getBytes());
+ // Expiry
+ req.setExpiry(DEFAULT_EXPIRY_TIME);
+ // The following set methods throw InvalidHeaderValueException
+ try {
+ // Priority
+ req.setPriority(DEFAULT_PRIORITY);
+ // Delivery report
+ req.setDeliveryReport(PduHeaders.VALUE_NO);
+ // Read report
+ req.setReadReport(PduHeaders.VALUE_NO);
+ } catch (InvalidHeaderValueException e) {
+ return null;
+ }
+
+ return new PduComposer(context, req).make();
+ }
+
+ private static int addTextPart(PduBody pb, String message, boolean addTextSmil) {
+ final PduPart part = new PduPart();
+ // Set Charset if it's a text media.
+ part.setCharset(CharacterSets.UTF_8);
+ // Set Content-Type.
+ part.setContentType(ContentType.TEXT_PLAIN.getBytes());
+ // Set Content-Location.
+ part.setContentLocation(TEXT_PART_FILENAME.getBytes());
+ int index = TEXT_PART_FILENAME.lastIndexOf(".");
+ String contentId = (index == -1) ? TEXT_PART_FILENAME
+ : TEXT_PART_FILENAME.substring(0, index);
+ part.setContentId(contentId.getBytes());
+ part.setData(message.getBytes());
+ pb.addPart(part);
+ if (addTextSmil) {
+ final String smil = String.format(sSmilText, TEXT_PART_FILENAME);
+ addSmilPart(pb, smil);
+ }
+ return part.getData().length;
+ }
+
+ private static void addSmilPart(PduBody pb, String smil) {
+ final PduPart smilPart = new PduPart();
+ smilPart.setContentId("smil".getBytes());
+ smilPart.setContentLocation("smil.xml".getBytes());
+ smilPart.setContentType(ContentType.APP_SMIL.getBytes());
+ smilPart.setData(smil.getBytes());
+ pb.addPart(0, smilPart);
+ }
+
+ private static String getSimNumber(Context context) {
+ final TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(
+ Context.TELEPHONY_SERVICE);
+ return telephonyManager.getLine1Number();
+ }
+
+ private static boolean shouldParseContentDisposition() {
+ return SmsManager
+ .getDefault()
+ .getCarrierConfigValues()
+ .getBoolean(SmsManager.MMS_CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION, true);
+ }
+}
diff --git a/tests/tests/uirendering/AndroidManifest.xml b/tests/tests/uirendering/AndroidManifest.xml
index 413dfba..b8d84a6 100644
--- a/tests/tests/uirendering/AndroidManifest.xml
+++ b/tests/tests/uirendering/AndroidManifest.xml
@@ -26,7 +26,7 @@
<uses-library android:name="android.test.runner" />
</application>
- <instrumentation android:name="android.test.InstrumentationTestRunner"
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.cts.uirendering">
</instrumentation>
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java
index e3ad5a6..9aef255 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java
@@ -27,6 +27,8 @@
import android.uirendering.cts.util.BitmapDumper;
import android.util.Log;
+import android.support.test.InstrumentationRegistry;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -77,6 +79,10 @@
*/
@Override
public void setUp() {
+ // As the way to access Instrumentation is changed in the new runner, we need to inject it
+ // manually into ActivityInstrumentationTestCase2. ActivityInstrumentationTestCase2 will
+ // be marked as deprecated and replaced with ActivityTestRule.
+ injectInstrumentation(InstrumentationRegistry.getInstrumentation());
mDifferenceVisualizer = new PassFailVisualizer();
if (USE_RS) {
mRenderScript = RenderScript.create(getActivity().getApplicationContext());
diff --git a/tests/tests/webkit/src/android/webkit/cts/CookieManagerTest.java b/tests/tests/webkit/src/android/webkit/cts/CookieManagerTest.java
index c612886..856b4aa 100644
--- a/tests/tests/webkit/src/android/webkit/cts/CookieManagerTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/CookieManagerTest.java
@@ -319,8 +319,6 @@
assertFalse(anyDeleted.get());
}
- /*
- TODO: uncomment when acceptThirdPartyCookies implementation lands
public void testThirdPartyCookie() throws Throwable {
if (!NullWebViewUtils.isWebViewAvailable()) {
return;
@@ -377,7 +375,6 @@
mOnUiThread.getSettings().setJavaScriptEnabled(false);
}
}
- */
public void testb3167208() throws Exception {
if (!NullWebViewUtils.isWebViewAvailable()) {
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
index 1e22acc..f72a70d 100755
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
@@ -122,6 +122,11 @@
*/
private static final long SCROLL_WAIT_INTERVAL_MS = 200;
+ /**
+ * Epsilon used in page scale value comparisons.
+ */
+ private static final float PAGE_SCALE_EPSILON = 0.0001f;
+
private WebView mWebView;
private CtsTestServer mWebServer;
private WebViewOnUiThread mOnUiThread;
@@ -330,7 +335,7 @@
// that a scale change does *not* happen.
Thread.sleep(500);
currScale = mOnUiThread.getScale();
- assertEquals(currScale, previousScale);
+ assertEquals(currScale, previousScale, PAGE_SCALE_EPSILON);
assertTrue(mOnUiThread.zoomOut());
previousScale = currScale;
@@ -354,7 +359,7 @@
// that a scale change does *not* happen.
Thread.sleep(500);
currScale = mOnUiThread.getScale();
- assertEquals(currScale, previousScale);
+ assertEquals(currScale, previousScale, PAGE_SCALE_EPSILON);
mOnUiThread.zoomBy(1.25f);
previousScale = currScale;
@@ -378,7 +383,7 @@
// that a scale change does *not* happen.
Thread.sleep(500);
currScale = mOnUiThread.getScale();
- assertEquals(currScale, previousScale);
+ assertEquals(currScale, previousScale, PAGE_SCALE_EPSILON);
mOnUiThread.zoomBy(0.8f);
previousScale = currScale;
@@ -402,7 +407,7 @@
// that a scale change does *not* happen.
Thread.sleep(500);
currScale = mOnUiThread.getScale();
- assertEquals(currScale, previousScale);
+ assertEquals(currScale, previousScale, PAGE_SCALE_EPSILON);
}
@UiThreadTest
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java b/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
index 8544a93..2ee649d 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
@@ -31,7 +31,7 @@
@Option(name="cts-install-path", description="the path to the cts installation to use")
private String mCtsRootDirPath = System.getProperty("CTS_ROOT");
- public static final String CTS_BUILD_VERSION = "5.1_r0.5";
+ public static final String CTS_BUILD_VERSION = "5.0_r1.91";
/**
* {@inheritDoc}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/DeqpTestRunner.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/DeqpTestRunner.java
index 8eb1621..6d8d807 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/DeqpTestRunner.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/DeqpTestRunner.java
@@ -22,8 +22,14 @@
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
import java.util.Map;
+import java.util.Set;
/**
* Test runner for dEQP tests
@@ -35,29 +41,35 @@
private static final String DEQP_ONDEVICE_APK = "com.drawelements.deqp.apk";
private static final String DEQP_ONDEVICE_PKG = "com.drawelements.deqp";
private static final String INCOMPLETE_LOG_MESSAGE = "Crash: Incomplete test log";
+ private static final String DEVICE_LOST_MESSAGE = "Crash: Device lost";
+ private static final String SKIPPED_INSTANCE_LOG_MESSAGE = "Configuration skipped";
+ private static final String CASE_LIST_FILE_NAME = "/sdcard/dEQP-TestCaseList.txt";
+ private static final String LOG_FILE_NAME = "/sdcard/TestLog.qpa";
+ public static final String FEATURE_LANDSCAPE = "android.hardware.screen.landscape";
+ public static final String FEATURE_PORTRAIT = "android.hardware.screen.portrait";
- private final int TESTCASE_BATCH_LIMIT = 1000;
-
- private boolean mLogData;
-
- private ITestDevice mDevice;
+ private static final int TESTCASE_BATCH_LIMIT = 1000;
+ private static final BatchRunConfiguration DEFAULT_CONFIG =
+ new BatchRunConfiguration("rgba8888d24s8", "unspecified", "window");
private final String mPackageName;
private final String mName;
- private Collection<TestIdentifier> mTests;
+ private final Collection<TestIdentifier> mRemainingTests;
+ private final Map<TestIdentifier, Set<BatchRunConfiguration>> mTestInstances;
+ private final TestInstanceResultListener mInstanceListerner;
private IAbi mAbi;
private CtsBuildHelper mCtsBuild;
+ private boolean mLogData;
+ private ITestDevice mDevice;
+ private Set<String> mDeviceFeatures;
- private TestIdentifier mCurrentTestId;
- private boolean mGotTestResult;
- private String mCurrentTestLog;
-
- private ITestInvocationListener mListener;
-
- public DeqpTestRunner(String packageName, String name, Collection<TestIdentifier> tests) {
+ public DeqpTestRunner(String packageName, String name, Collection<TestIdentifier> tests,
+ Map<TestIdentifier, List<Map<String,String>>> testInstances) {
mPackageName = packageName;
mName = name;
- mTests = tests;
+ mRemainingTests = new LinkedList<>(tests); // avoid modifying arguments
+ mTestInstances = parseTestInstances(tests, testInstances);
+ mInstanceListerner = new TestInstanceResultListener();
mLogData = false;
}
@@ -95,18 +107,390 @@
}
/**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setDevice(ITestDevice device) {
+ mDevice = device;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ITestDevice getDevice() {
+ return mDevice;
+ }
+
+ private static final class CapabilityQueryFailureException extends Exception {
+ };
+
+ /**
+ * Test configuration of dEPQ test instance execution.
+ * Exposed for unit testing
+ */
+ public static final class BatchRunConfiguration {
+ public static final String ROTATION_UNSPECIFIED = "unspecified";
+ public static final String ROTATION_PORTRAIT = "0";
+ public static final String ROTATION_LANDSCAPE = "90";
+ public static final String ROTATION_REVERSE_PORTRAIT = "180";
+ public static final String ROTATION_REVERSE_LANDSCAPE = "270";
+
+ private final String mGlConfig;
+ private final String mRotation;
+ private final String mSurfaceType;
+
+ public BatchRunConfiguration(String glConfig, String rotation, String surfaceType) {
+ mGlConfig = glConfig;
+ mRotation = rotation;
+ mSurfaceType = surfaceType;
+ }
+
+ /**
+ * Get string that uniquely identifies this config
+ */
+ public String getId() {
+ return String.format("{glformat=%s,rotation=%s,surfacetype=%s}",
+ mGlConfig, mRotation, mSurfaceType);
+ }
+
+ /**
+ * Get the GL config used in this configuration.
+ */
+ public String getGlConfig() {
+ return mGlConfig;
+ }
+
+ /**
+ * Get the screen rotation used in this configuration.
+ */
+ public String getRotation() {
+ return mRotation;
+ }
+
+ /**
+ * Get the surface type used in this configuration.
+ */
+ public String getSurfaceType() {
+ return mSurfaceType;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == null) {
+ return false;
+ } else if (!(other instanceof BatchRunConfiguration)) {
+ return false;
+ } else {
+ return getId().equals(((BatchRunConfiguration)other).getId());
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return getId().hashCode();
+ }
+ }
+
+ /**
+ * dEQP test instance listerer and invocation result forwarded
+ */
+ private class TestInstanceResultListener {
+ private ITestInvocationListener mSink;
+ private BatchRunConfiguration mRunConfig;
+
+ private TestIdentifier mCurrentTestId;
+ private boolean mGotTestResult;
+ private String mCurrentTestLog;
+
+ private class PendingResult
+ {
+ boolean allInstancesPassed;
+ Map<BatchRunConfiguration, String> testLogs;
+ Map<BatchRunConfiguration, String> errorMessages;
+ Set<BatchRunConfiguration> remainingConfigs;
+ };
+ private final Map<TestIdentifier, PendingResult> mPendingResults = new HashMap<>();
+
+ public void setSink(ITestInvocationListener sink) {
+ mSink = sink;
+ }
+
+ public void setCurrentConfig(BatchRunConfiguration runConfig) {
+ mRunConfig = runConfig;
+ }
+
+ /**
+ * Forward result to sink
+ */
+ private void forwardFinalizedPendingResult() {
+ if (mRemainingTests.contains(mCurrentTestId)) {
+ final PendingResult result = mPendingResults.get(mCurrentTestId);
+
+ mRemainingTests.remove(mCurrentTestId);
+ mSink.testStarted(mCurrentTestId);
+
+ // Test Log
+ if (mLogData) {
+ for (Map.Entry<BatchRunConfiguration, String> entry :
+ result.testLogs.entrySet()) {
+ final ByteArrayInputStreamSource source
+ = new ByteArrayInputStreamSource(entry.getValue().getBytes());
+
+ mSink.testLog(mCurrentTestId.getClassName() + "."
+ + mCurrentTestId.getTestName() + "@" + entry.getKey().getId(),
+ LogDataType.XML, source);
+
+ source.cancel();
+ }
+ }
+
+ // Error message
+ if (!result.allInstancesPassed) {
+ final StringBuilder errorLog = new StringBuilder();
+
+ for (Map.Entry<BatchRunConfiguration, String> entry :
+ result.errorMessages.entrySet()) {
+ if (errorLog.length() > 0) {
+ errorLog.append('\n');
+ }
+ errorLog.append(String.format("=== with config %s ===\n",
+ entry.getKey().getId()));
+ errorLog.append(entry.getValue());
+ }
+
+ mSink.testFailed(mCurrentTestId, errorLog.toString());
+ }
+
+ // Clear all that won't be used again. The memory usage of these might
+ // add up to quite large numbers
+ result.testLogs = null;
+ result.errorMessages = null;
+ final Map<String, String> emptyMap = Collections.emptyMap();
+ mSink.testEnded(mCurrentTestId, emptyMap);
+ }
+ }
+
+ /**
+ * Declare existence of a test and instances
+ */
+ public void setTestInstances(TestIdentifier testId, Set<BatchRunConfiguration> configs) {
+ // Test instances cannot change at runtime, ignore if we have already set this
+ if (!mPendingResults.containsKey(testId)) {
+ final PendingResult pendingResult = new PendingResult();
+ pendingResult.allInstancesPassed = true;
+ pendingResult.testLogs = new LinkedHashMap<>();
+ pendingResult.errorMessages = new LinkedHashMap<>();
+ pendingResult.remainingConfigs = new HashSet<>(configs); // avoid mutating argument
+ mPendingResults.put(testId, pendingResult);
+ }
+ }
+
+ /**
+ * Query if test instance has not yet been executed
+ */
+ public boolean isPendingTestInstance(TestIdentifier testId,
+ BatchRunConfiguration config) {
+ final PendingResult result = mPendingResults.get(testId);
+ return result.remainingConfigs.contains(config);
+ }
+
+ /**
+ * Fake execution of an instance with current config
+ */
+ public void skipTest(TestIdentifier testId) {
+ final PendingResult result = mPendingResults.get(testId);
+
+ result.errorMessages.put(mRunConfig, SKIPPED_INSTANCE_LOG_MESSAGE);
+ result.remainingConfigs.remove(mRunConfig);
+
+ if (result.remainingConfigs.isEmpty()) {
+ // fake as if we actually run the test
+ mCurrentTestId = testId;
+ forwardFinalizedPendingResult();
+ mCurrentTestId = null;
+ }
+ }
+
+ /**
+ * Handles beginning of dEQP session.
+ */
+ private void handleBeginSession(Map<String, String> values) {
+ // ignore
+ }
+
+ /**
+ * Handles end of dEQP session.
+ */
+ private void handleEndSession(Map<String, String> values) {
+ // ignore
+ }
+
+ /**
+ * Handles beginning of dEQP testcase.
+ */
+ private void handleBeginTestCase(Map<String, String> values) {
+ mCurrentTestId = pathToIdentifier(values.get("dEQP-BeginTestCase-TestCasePath"));
+ mCurrentTestLog = "";
+ mGotTestResult = false;
+
+ // mark instance as started
+ mPendingResults.get(mCurrentTestId).remainingConfigs.remove(mRunConfig);
+ }
+
+ /**
+ * Handles end of dEQP testcase.
+ */
+ private void handleEndTestCase(Map<String, String> values) {
+ final PendingResult result = mPendingResults.get(mCurrentTestId);
+ if (!mGotTestResult) {
+ result.allInstancesPassed = false;
+ result.errorMessages.put(mRunConfig, INCOMPLETE_LOG_MESSAGE);
+ }
+
+ if (mLogData && mCurrentTestLog != null && mCurrentTestLog.length() > 0) {
+ result.testLogs.put(mRunConfig, mCurrentTestLog);
+ }
+
+ // Pending result finished, report result
+ if (result.remainingConfigs.isEmpty()) {
+ forwardFinalizedPendingResult();
+ }
+ mCurrentTestId = null;
+ }
+
+ /**
+ * Handles dEQP testcase result.
+ */
+ private void handleTestCaseResult(Map<String, String> values) {
+ String code = values.get("dEQP-TestCaseResult-Code");
+ String details = values.get("dEQP-TestCaseResult-Details");
+
+ if (code.compareTo("Pass") == 0) {
+ mGotTestResult = true;
+ } else if (code.compareTo("NotSupported") == 0) {
+ mGotTestResult = true;
+ } else if (code.compareTo("QualityWarning") == 0) {
+ mGotTestResult = true;
+ } else if (code.compareTo("CompatibilityWarning") == 0) {
+ mGotTestResult = true;
+ } else if (code.compareTo("Fail") == 0 || code.compareTo("ResourceError") == 0
+ || code.compareTo("InternalError") == 0 || code.compareTo("Crash") == 0
+ || code.compareTo("Timeout") == 0) {
+ mPendingResults.get(mCurrentTestId).allInstancesPassed = false;
+ mPendingResults.get(mCurrentTestId)
+ .errorMessages.put(mRunConfig, code + ": " + details);
+ mGotTestResult = true;
+ } else {
+ String codeError = "Unknown result code: " + code;
+ mPendingResults.get(mCurrentTestId).allInstancesPassed = false;
+ mPendingResults.get(mCurrentTestId)
+ .errorMessages.put(mRunConfig, codeError + ": " + details);
+ mGotTestResult = true;
+ }
+ }
+
+ /**
+ * Handles terminated dEQP testcase.
+ */
+ private void handleTestCaseTerminate(Map<String, String> values) {
+ final PendingResult result = mPendingResults.get(mCurrentTestId);
+
+ String reason = values.get("dEQP-TerminateTestCase-Reason");
+ mPendingResults.get(mCurrentTestId).allInstancesPassed = false;
+ mPendingResults.get(mCurrentTestId)
+ .errorMessages.put(mRunConfig, "Terminated: " + reason);
+
+ // Pending result finished, report result
+ if (result.remainingConfigs.isEmpty()) {
+ forwardFinalizedPendingResult();
+ }
+
+ mCurrentTestId = null;
+ mGotTestResult = true;
+ }
+
+ /**
+ * Handles dEQP testlog data.
+ */
+ private void handleTestLogData(Map<String, String> values) {
+ mCurrentTestLog = mCurrentTestLog + values.get("dEQP-TestLogData-Log");
+ }
+
+ /**
+ * Handles new instrumentation status message.
+ */
+ public void handleStatus(Map<String, String> values) {
+ String eventType = values.get("dEQP-EventType");
+
+ if (eventType == null) {
+ return;
+ }
+
+ if (eventType.compareTo("BeginSession") == 0) {
+ handleBeginSession(values);
+ } else if (eventType.compareTo("EndSession") == 0) {
+ handleEndSession(values);
+ } else if (eventType.compareTo("BeginTestCase") == 0) {
+ handleBeginTestCase(values);
+ } else if (eventType.compareTo("EndTestCase") == 0) {
+ handleEndTestCase(values);
+ } else if (eventType.compareTo("TestCaseResult") == 0) {
+ handleTestCaseResult(values);
+ } else if (eventType.compareTo("TerminateTestCase") == 0) {
+ handleTestCaseTerminate(values);
+ } else if (eventType.compareTo("TestLogData") == 0) {
+ handleTestLogData(values);
+ }
+ }
+
+ /**
+ * Signal listener that batch ended to flush incomplete results.
+ */
+ public void endBatch() {
+ // end open test if when stream ends
+ if (mCurrentTestId != null) {
+ final Map<String, String> emptyMap = Collections.emptyMap();
+ handleEndTestCase(emptyMap);
+ }
+ }
+
+ /**
+ * Signal listener that device just died.
+ */
+ public void onDeviceLost() {
+ if (mCurrentTestId != null) {
+ final PendingResult result = mPendingResults.get(mCurrentTestId);
+
+ // kill current test
+ result.allInstancesPassed = false;
+ result.errorMessages.put(mRunConfig, DEVICE_LOST_MESSAGE);
+
+ if (mLogData && mCurrentTestLog != null && mCurrentTestLog.length() > 0) {
+ result.testLogs.put(mRunConfig, mCurrentTestLog);
+ }
+
+ // finish all pending instances
+ result.remainingConfigs.clear();
+ forwardFinalizedPendingResult();
+ mCurrentTestId = null;
+ }
+ }
+ }
+
+ /**
* dEQP instrumentation parser
*/
- class InstrumentationParser extends MultiLineReceiver {
- private DeqpTestRunner mDeqpTests;
+ private static class InstrumentationParser extends MultiLineReceiver {
+ private TestInstanceResultListener mListener;
private Map<String, String> mValues;
private String mCurrentName;
private String mCurrentValue;
- public InstrumentationParser(DeqpTestRunner tests) {
- mDeqpTests = tests;
+ public InstrumentationParser(TestInstanceResultListener listener) {
+ mListener = listener;
}
/**
@@ -125,7 +509,7 @@
mCurrentValue = null;
}
- mDeqpTests.handleStatus(mValues);
+ mListener.handleStatus(mValues);
mValues = null;
} else if (line.startsWith("INSTRUMENTATION_STATUS: dEQP-")) {
if (mCurrentName != null) {
@@ -161,7 +545,7 @@
}
if (mValues != null) {
- mDeqpTests.handleStatus(mValues);
+ mListener.handleStatus(mValues);
mValues = null;
}
}
@@ -176,9 +560,112 @@
}
/**
+ * dEQP platfom query instrumentation parser
+ */
+ private static class PlatformQueryInstrumentationParser extends MultiLineReceiver {
+ private Map<String,String> mResultMap = new LinkedHashMap<>();
+ private int mResultCode;
+ private boolean mGotExitValue = false;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void processNewLines(String[] lines) {
+ for (String line : lines) {
+ if (line.startsWith("INSTRUMENTATION_RESULT: ")) {
+ final String parts[] = line.substring(24).split("=",2);
+ if (parts.length == 2) {
+ mResultMap.put(parts[0], parts[1]);
+ } else {
+ CLog.w("Instrumentation status format unexpected");
+ }
+ } else if (line.startsWith("INSTRUMENTATION_CODE: ")) {
+ try {
+ mResultCode = Integer.parseInt(line.substring(22));
+ mGotExitValue = true;
+ } catch (NumberFormatException ex) {
+ CLog.w("Instrumentation code format unexpected");
+ }
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isCancelled() {
+ return false;
+ }
+
+ public boolean wasSuccessful() {
+ return mGotExitValue;
+ }
+
+ public int getResultCode() {
+ return mResultCode;
+ }
+
+ public Map<String,String> getResultMap() {
+ return mResultMap;
+ }
+ }
+
+ /**
+ * Parse map of instance arguments to map of BatchRunConfigurations
+ */
+ private static Map<TestIdentifier, Set<BatchRunConfiguration>> parseTestInstances(
+ Collection<TestIdentifier> tests,
+ Map<TestIdentifier, List<Map<String,String>>> testInstances) {
+ final Map<TestIdentifier, Set<BatchRunConfiguration>> instances = new HashMap<>();
+ for (final TestIdentifier test : tests) {
+ final Set<BatchRunConfiguration> testInstanceSet = new LinkedHashSet<>();
+ if (testInstances.get(test).isEmpty()) {
+ // no instances defined, use default
+ testInstanceSet.add(DEFAULT_CONFIG);
+ } else {
+ for (Map<String, String> instanceArgs : testInstances.get(test)) {
+ testInstanceSet.add(parseRunConfig(instanceArgs));
+ }
+ }
+ instances.put(test, testInstanceSet);
+ }
+ return instances;
+ }
+
+ private static BatchRunConfiguration parseRunConfig(Map<String,String> instanceArguments) {
+ final String glConfig;
+ final String rotation;
+ final String surfaceType;
+
+ if (instanceArguments.containsKey("glconfig")) {
+ glConfig = instanceArguments.get("glconfig");
+ } else {
+ glConfig = DEFAULT_CONFIG.getGlConfig();
+ }
+ if (instanceArguments.containsKey("rotation")) {
+ rotation = instanceArguments.get("rotation");
+ } else {
+ rotation = DEFAULT_CONFIG.getRotation();
+ }
+ if (instanceArguments.containsKey("surfaceType")) {
+ surfaceType = instanceArguments.get("surfaceType");
+ } else {
+ surfaceType = DEFAULT_CONFIG.getSurfaceType();
+ }
+
+ return new BatchRunConfiguration(glConfig, rotation, surfaceType);
+ }
+
+ private Set<BatchRunConfiguration> getTestRunConfigs (TestIdentifier testId) {
+ return mTestInstances.get(testId);
+ }
+
+ /**
* Converts dEQP testcase path to TestIdentifier.
*/
- private TestIdentifier pathToIdentifier(String testPath) {
+ private static TestIdentifier pathToIdentifier(String testPath) {
String[] components = testPath.split("\\.");
String name = components[components.length - 1];
String className = null;
@@ -194,150 +681,14 @@
return new TestIdentifier(className, name);
}
- /**
- * Handles beginning of dEQP session.
- */
- private void handleBeginSession(Map<String, String> values) {
- String id = AbiUtils.createId(mAbi.getName(), mPackageName);
- mListener.testRunStarted(id, mTests.size());
- }
-
- /**
- * Handles end of dEQP session.
- */
- private void handleEndSession(Map<String, String> values) {
- Map <String, String> emptyMap = Collections.emptyMap();
- mListener.testRunEnded(0, emptyMap);
- }
-
- /**
- * Handles beginning of dEQP testcase.
- */
- private void handleBeginTestCase(Map<String, String> values) {
- mCurrentTestId = pathToIdentifier(values.get("dEQP-BeginTestCase-TestCasePath"));
- mCurrentTestLog = "";
- mGotTestResult = false;
-
- mListener.testStarted(mCurrentTestId);
- mTests.remove(mCurrentTestId);
- }
-
- /**
- * Handles end of dEQP testcase.
- */
- private void handleEndTestCase(Map<String, String> values) {
- Map <String, String> emptyMap = Collections.emptyMap();
-
- if (!mGotTestResult) {
- mListener.testFailed(mCurrentTestId,
- INCOMPLETE_LOG_MESSAGE);
- }
-
- if (mLogData && mCurrentTestLog != null && mCurrentTestLog.length() > 0) {
- ByteArrayInputStreamSource source
- = new ByteArrayInputStreamSource(mCurrentTestLog.getBytes());
-
- mListener.testLog(mCurrentTestId.getClassName() + "."
- + mCurrentTestId.getTestName(), LogDataType.XML, source);
-
- source.cancel();
- }
-
- mListener.testEnded(mCurrentTestId, emptyMap);
- mCurrentTestId = null;
- }
-
- /**
- * Handles dEQP testcase result.
- */
- private void handleTestCaseResult(Map<String, String> values) {
- String code = values.get("dEQP-TestCaseResult-Code");
- String details = values.get("dEQP-TestCaseResult-Details");
-
- if (code.compareTo("Pass") == 0) {
- mGotTestResult = true;
- } else if (code.compareTo("NotSupported") == 0) {
- mGotTestResult = true;
- } else if (code.compareTo("QualityWarning") == 0) {
- mGotTestResult = true;
- } else if (code.compareTo("CompatibilityWarning") == 0) {
- mGotTestResult = true;
- } else if (code.compareTo("Fail") == 0 || code.compareTo("ResourceError") == 0
- || code.compareTo("InternalError") == 0 || code.compareTo("Crash") == 0
- || code.compareTo("Timeout") == 0) {
- mListener.testFailed(mCurrentTestId,
- code + ": " + details);
- mGotTestResult = true;
- } else {
- mListener.testFailed(mCurrentTestId,
- "Unknown result code: " + code + ": " + details);
- mGotTestResult = true;
- }
- }
-
- /**
- * Handles terminated dEQP testcase.
- */
- private void handleTestCaseTerminate(Map<String, String> values) {
- Map <String, String> emptyMap = Collections.emptyMap();
-
- String reason = values.get("dEQP-TerminateTestCase-Reason");
- mListener.testFailed(mCurrentTestId,
- "Terminated: " + reason);
- mListener.testEnded(mCurrentTestId, emptyMap);
-
- if (mLogData && mCurrentTestLog != null && mCurrentTestLog.length() > 0) {
- ByteArrayInputStreamSource source
- = new ByteArrayInputStreamSource(mCurrentTestLog.getBytes());
-
- mListener.testLog(mCurrentTestId.getClassName() + "."
- + mCurrentTestId.getTestName(), LogDataType.XML, source);
-
- source.cancel();
- }
-
- mCurrentTestId = null;
- mGotTestResult = true;
- }
-
- /**
- * Handles dEQP testlog data.
- */
- private void handleTestLogData(Map<String, String> values) {
- mCurrentTestLog = mCurrentTestLog + values.get("dEQP-TestLogData-Log");
- }
-
- /**
- * Handles new instrumentation status message.
- */
- public void handleStatus(Map<String, String> values) {
- String eventType = values.get("dEQP-EventType");
-
- if (eventType == null) {
- return;
- }
-
- if (eventType.compareTo("BeginSession") == 0) {
- handleBeginSession(values);
- } else if (eventType.compareTo("EndSession") == 0) {
- handleEndSession(values);
- } else if (eventType.compareTo("BeginTestCase") == 0) {
- handleBeginTestCase(values);
- } else if (eventType.compareTo("EndTestCase") == 0) {
- handleEndTestCase(values);
- } else if (eventType.compareTo("TestCaseResult") == 0) {
- handleTestCaseResult(values);
- } else if (eventType.compareTo("TerminateTestCase") == 0) {
- handleTestCaseTerminate(values);
- } else if (eventType.compareTo("TestLogData") == 0) {
- handleTestLogData(values);
- }
+ private String getId() {
+ return AbiUtils.createId(mAbi.getName(), mPackageName);
}
/**
* Generates tescase trie from dEQP testcase paths. Used to define which testcases to execute.
*/
- private String generateTestCaseTrieFromPaths(Collection<String> tests) {
+ private static String generateTestCaseTrieFromPaths(Collection<String> tests) {
String result = "{";
boolean first = true;
@@ -390,15 +741,11 @@
/**
* Generates testcase trie from TestIdentifiers.
*/
- private String generateTestCaseTrie(Collection<TestIdentifier> tests) {
+ private static String generateTestCaseTrie(Collection<TestIdentifier> tests) {
ArrayList<String> testPaths = new ArrayList<String>();
for (TestIdentifier test : tests) {
testPaths.add(test.getClassName() + "." + test.getTestName());
-
- // Limit number of testcases for each run
- if (testPaths.size() > TESTCASE_BATCH_LIMIT)
- break;
}
return generateTestCaseTrieFromPaths(testPaths);
@@ -407,34 +754,178 @@
/**
* Executes tests on the device.
*/
- private void executeTests(ITestInvocationListener listener) throws DeviceNotAvailableException {
- InstrumentationParser parser = new InstrumentationParser(this);
- String caseListFileName = "/sdcard/dEQP-TestCaseList.txt";
- String logFileName = "/sdcard/TestLog.qpa";
- String testCases = generateTestCaseTrie(mTests);
+ private void runTests() throws DeviceNotAvailableException, CapabilityQueryFailureException {
+ while (!mRemainingTests.isEmpty()) {
+ // select tests for the batch
+ final ArrayList<TestIdentifier> batchTests = new ArrayList<>(TESTCASE_BATCH_LIMIT);
+ for (TestIdentifier test : mRemainingTests) {
+ batchTests.add(test);
+ if (batchTests.size() >= TESTCASE_BATCH_LIMIT) {
+ break;
+ }
+ }
- mDevice.executeShellCommand("rm " + caseListFileName);
- mDevice.executeShellCommand("rm " + logFileName);
- mDevice.pushString(testCases + "\n", caseListFileName);
+ // find union of all run configurations
+ final Set<BatchRunConfiguration> allConfigs = new LinkedHashSet<>();
+ for (TestIdentifier test : batchTests) {
+ allConfigs.addAll(getTestRunConfigs(test));
+ }
- String instrumentationName =
+ // prepare instance listener
+ for (TestIdentifier test : batchTests) {
+ mInstanceListerner.setTestInstances(test, getTestRunConfigs(test));
+ }
+
+ // run batch for all configurations
+ for (BatchRunConfiguration runConfig : allConfigs) {
+ final ArrayList<TestIdentifier> relevantTests =
+ new ArrayList<>(TESTCASE_BATCH_LIMIT);
+
+ // run only for declared run configs and only if test has not already
+ // been attempted to run
+ for (TestIdentifier test : batchTests) {
+ if (mInstanceListerner.isPendingTestInstance(test, runConfig)) {
+ relevantTests.add(test);
+ }
+ }
+
+ if (!relevantTests.isEmpty()) {
+ runTestRunBatch(relevantTests, runConfig);
+ }
+ }
+ }
+ }
+
+ private void runTestRunBatch(Collection<TestIdentifier> tests, BatchRunConfiguration runConfig)
+ throws DeviceNotAvailableException, CapabilityQueryFailureException {
+ boolean isSupportedConfig = true;
+
+ // orientation support
+ if (!BatchRunConfiguration.ROTATION_UNSPECIFIED.equals(runConfig.getRotation())) {
+ final Set<String> features = getDeviceFeatures(mDevice);
+
+ if (isPortraitClassRotation(runConfig.getRotation()) &&
+ !features.contains(FEATURE_PORTRAIT)) {
+ isSupportedConfig = false;
+ }
+ if (isLandscapeClassRotation(runConfig.getRotation()) &&
+ !features.contains(FEATURE_LANDSCAPE)) {
+ isSupportedConfig = false;
+ }
+ }
+
+ // renderability support for OpenGL ES tests
+ if (isSupportedConfig && isOpenGlEsPackage()) {
+ isSupportedConfig = isSupportedGlesRenderConfig(runConfig);
+ }
+
+ mInstanceListerner.setCurrentConfig(runConfig);
+
+ // execute only if config is executable, else fake results
+ if (isSupportedConfig) {
+ executeTestRunBatch(tests, runConfig);
+ } else {
+ fakePassTestRunBatch(tests, runConfig);
+ }
+ }
+
+ private void executeTestRunBatch(Collection<TestIdentifier> tests,
+ BatchRunConfiguration runConfig) throws DeviceNotAvailableException {
+ final String testCases = generateTestCaseTrie(tests);
+
+ mDevice.executeShellCommand("rm " + CASE_LIST_FILE_NAME);
+ mDevice.executeShellCommand("rm " + LOG_FILE_NAME);
+ mDevice.pushString(testCases + "\n", CASE_LIST_FILE_NAME);
+
+ final String instrumentationName =
"com.drawelements.deqp/com.drawelements.deqp.testercore.DeqpInstrumentation";
- String command = String.format(
- "am instrument %s -w -e deqpLogFileName \"%s\" -e deqpCmdLine \""
- + "--deqp-caselist-file=%s --deqp-gl-config-name=rgba8888d24s8\""
- + " -e deqpLogData \"%s\" %s",
- AbiUtils.createAbiFlag(mAbi.getName()), logFileName, caseListFileName, mLogData,
- instrumentationName);
+ final StringBuilder deqpCmdLine = new StringBuilder();
+ deqpCmdLine.append("--deqp-caselist-file=");
+ deqpCmdLine.append(CASE_LIST_FILE_NAME);
+ deqpCmdLine.append(" ");
+ deqpCmdLine.append(getRunConfigDisplayCmdLine(runConfig));
- mDevice.executeShellCommand(command, parser);
- parser.flush();
+ final String command = String.format(
+ "am instrument %s -w -e deqpLogFileName \"%s\" -e deqpCmdLine \"%s\""
+ + " -e deqpLogData \"%s\" %s",
+ AbiUtils.createAbiFlag(mAbi.getName()), LOG_FILE_NAME, deqpCmdLine.toString(),
+ mLogData, instrumentationName);
+
+ try {
+ final InstrumentationParser parser = new InstrumentationParser(mInstanceListerner);
+ mDevice.executeShellCommand(command, parser);
+ parser.flush();
+ } catch (DeviceNotAvailableException ex) {
+ // Device lost. We must signal the tradedef by rethrowing this execption. However,
+ // there is a possiblity that the device loss was caused by the currently run test
+ // instance. Since CtsTest is unaware of tests with only some instances executed,
+ // continuing the session after device has recovered will create a new DeqpTestRunner
+ // with current test in its run queue and this will cause the re-execution of this same
+ // instance. If the instance reliably can kill the device, the CTS cannot recover.
+ //
+ // Prevent this by terminating ALL instances of a tests if any of them causes a device
+ // loss.
+ mInstanceListerner.onDeviceLost();
+ throw ex;
+ } finally {
+ mInstanceListerner.endBatch();
+ }
+ }
+
+ private static String getRunConfigDisplayCmdLine(BatchRunConfiguration runConfig) {
+ final StringBuilder deqpCmdLine = new StringBuilder();
+ if (!runConfig.getGlConfig().isEmpty()) {
+ deqpCmdLine.append("--deqp-gl-config-name=");
+ deqpCmdLine.append(runConfig.getGlConfig());
+ }
+ if (!runConfig.getRotation().isEmpty()) {
+ if (deqpCmdLine.length() != 0) {
+ deqpCmdLine.append(" ");
+ }
+ deqpCmdLine.append("--deqp-screen-rotation=");
+ deqpCmdLine.append(runConfig.getRotation());
+ }
+ if (!runConfig.getSurfaceType().isEmpty()) {
+ if (deqpCmdLine.length() != 0) {
+ deqpCmdLine.append(" ");
+ }
+ deqpCmdLine.append("--deqp-surface-type=");
+ deqpCmdLine.append(runConfig.getSurfaceType());
+ }
+ return deqpCmdLine.toString();
+ }
+
+ /**
+ * Pass given batch tests without running it
+ */
+ private void fakePassTestRunBatch(Collection<TestIdentifier> tests,
+ BatchRunConfiguration runConfig) {
+ for (TestIdentifier test : tests) {
+ CLog.d("Skipping test '%s' invocation in config '%s'", test.toString(),
+ runConfig.getId());
+ mInstanceListerner.skipTest(test);
+ }
+ }
+
+ /**
+ * Pass all remaining tests without running them
+ */
+ private void fakePassTests(ITestInvocationListener listener) {
+ Map <String, String> emptyMap = Collections.emptyMap();
+ for (TestIdentifier test : mRemainingTests) {
+ CLog.d("Skipping test '%s', Opengl ES version not supported", test.toString());
+ listener.testStarted(test);
+ listener.testEnded(test, emptyMap);
+ }
+ mRemainingTests.clear();
}
/**
* Check if device supports OpenGL ES version.
*/
- static boolean isSupportedGles(ITestDevice device, int requiredMajorVersion, int requiredMinorVersion) throws DeviceNotAvailableException {
+ private static boolean isSupportedGles(ITestDevice device, int requiredMajorVersion,
+ int requiredMinorVersion) throws DeviceNotAvailableException {
String roOpenglesVersion = device.getProperty("ro.opengles.version");
if (roOpenglesVersion == null)
@@ -450,6 +941,99 @@
}
/**
+ * Query if rendertarget is supported
+ */
+ private boolean isSupportedGlesRenderConfig(BatchRunConfiguration runConfig)
+ throws DeviceNotAvailableException, CapabilityQueryFailureException {
+ // query if configuration is supported
+ final StringBuilder configCommandLine =
+ new StringBuilder(getRunConfigDisplayCmdLine(runConfig));
+ if (configCommandLine.length() != 0) {
+ configCommandLine.append(" ");
+ }
+ configCommandLine.append("--deqp-gl-major-version=");
+ configCommandLine.append(getGlesMajorVersion());
+ configCommandLine.append(" --deqp-gl-minor-version=");
+ configCommandLine.append(getGlesMinorVersion());
+
+ final String instrumentationName =
+ "com.drawelements.deqp/com.drawelements.deqp.platformutil.DeqpPlatformCapabilityQueryInstrumentation";
+ final String command = String.format(
+ "am instrument %s -w -e deqpQueryType renderConfigSupported -e deqpCmdLine \"%s\""
+ + " %s",
+ AbiUtils.createAbiFlag(mAbi.getName()), configCommandLine.toString(),
+ instrumentationName);
+
+ final PlatformQueryInstrumentationParser parser = new PlatformQueryInstrumentationParser();
+ mDevice.executeShellCommand(command, parser);
+ parser.flush();
+
+ if (parser.wasSuccessful() && parser.getResultCode() == 0 &&
+ parser.getResultMap().containsKey("Supported")) {
+ if ("Yes".equals(parser.getResultMap().get("Supported"))) {
+ return true;
+ } else if ("No".equals(parser.getResultMap().get("Supported"))) {
+ return false;
+ } else {
+ CLog.e("Capability query did not return a result");
+ throw new CapabilityQueryFailureException();
+ }
+ } else if (parser.wasSuccessful()) {
+ CLog.e("Failed to run capability query. Code: %d, Result: %s",
+ parser.getResultCode(), parser.getResultMap().toString());
+ throw new CapabilityQueryFailureException();
+ } else {
+ CLog.e("Failed to run capability query");
+ throw new CapabilityQueryFailureException();
+ }
+ }
+
+ /**
+ * Return feature set supported by the device
+ */
+ private Set<String> getDeviceFeatures(ITestDevice device)
+ throws DeviceNotAvailableException, CapabilityQueryFailureException {
+ if (mDeviceFeatures == null) {
+ mDeviceFeatures = queryDeviceFeatures(device);
+ }
+ return mDeviceFeatures;
+ }
+
+ /**
+ * Query feature set supported by the device
+ */
+ private static Set<String> queryDeviceFeatures(ITestDevice device)
+ throws DeviceNotAvailableException, CapabilityQueryFailureException {
+ // NOTE: Almost identical code in BaseDevicePolicyTest#hasDeviceFeatures
+ // TODO: Move this logic to ITestDevice.
+ String command = "pm list features";
+ String commandOutput = device.executeShellCommand(command);
+
+ // Extract the id of the new user.
+ HashSet<String> availableFeatures = new HashSet<>();
+ for (String feature: commandOutput.split("\\s+")) {
+ // Each line in the output of the command has the format "feature:{FEATURE_VALUE}".
+ String[] tokens = feature.split(":");
+ if (tokens.length < 2 || !"feature".equals(tokens[0])) {
+ CLog.e("Failed parse features. Unexpect format on line \"%s\"", tokens[0]);
+ throw new CapabilityQueryFailureException();
+ }
+ availableFeatures.add(tokens[1]);
+ }
+ return availableFeatures;
+ }
+
+ private boolean isPortraitClassRotation(String rotation) {
+ return BatchRunConfiguration.ROTATION_PORTRAIT.equals(rotation) ||
+ BatchRunConfiguration.ROTATION_REVERSE_PORTRAIT.equals(rotation);
+ }
+
+ private boolean isLandscapeClassRotation(String rotation) {
+ return BatchRunConfiguration.ROTATION_LANDSCAPE.equals(rotation) ||
+ BatchRunConfiguration.ROTATION_REVERSE_LANDSCAPE.equals(rotation);
+ }
+
+ /**
* Install dEQP OnDevice Package
*/
private void installTestApk() throws DeviceNotAvailableException {
@@ -473,60 +1057,53 @@
}
/**
- * {@inheritDoc}
+ * Parse gl nature from package name
*/
- @Override
- public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
- mListener = listener;
-
- if ((mName.equals( "dEQP-GLES3") && isSupportedGles(mDevice, 3, 0))
- || (mName.equals("dEQP-GLES31") && isSupportedGles(mDevice, 3, 1))) {
-
- // Make sure there is no pre-existing package form earlier interrupted test run.
- uninstallTestApk();
- installTestApk();
-
- while (!mTests.isEmpty()) {
- executeTests(listener);
-
- // Set test to failed if it didn't receive test result
- if (mCurrentTestId != null) {
- Map <String, String> emptyMap = Collections.emptyMap();
-
- if (mLogData && mCurrentTestLog != null && mCurrentTestLog.length() > 0) {
- ByteArrayInputStreamSource source
- = new ByteArrayInputStreamSource(mCurrentTestLog.getBytes());
-
- mListener.testLog(mCurrentTestId.getClassName() + "."
- + mCurrentTestId.getTestName(), LogDataType.XML, source);
-
- source.cancel();
- }
- if (!mGotTestResult) {
- mListener.testFailed(mCurrentTestId,
- INCOMPLETE_LOG_MESSAGE);
- }
-
- mListener.testEnded(mCurrentTestId, emptyMap);
- mCurrentTestId = null;
- mListener.testRunEnded(0, emptyMap);
- }
- }
-
- uninstallTestApk();
+ private boolean isOpenGlEsPackage() {
+ if ("dEQP-GLES2".equals(mName) || "dEQP-GLES3".equals(mName) ||
+ "dEQP-GLES31".equals(mName)) {
+ return true;
+ } else if ("dEQP-EGL".equals(mName)) {
+ return false;
} else {
- /* Pass all tests if OpenGL ES version is not supported */
- Map <String, String> emptyMap = Collections.emptyMap();
- String id = AbiUtils.createId(mAbi.getName(), mPackageName);
- mListener.testRunStarted(id, mTests.size());
+ throw new IllegalStateException("dEQP runner was created with illegal name");
+ }
+ }
- for (TestIdentifier test : mTests) {
- CLog.d("Skipping test '%s', Opengl ES version not supported", test.toString());
- mListener.testStarted(test);
- mListener.testEnded(test, emptyMap);
- }
+ /**
+ * Check GL support (based on package name)
+ */
+ private boolean isSupportedGles() throws DeviceNotAvailableException {
+ return isSupportedGles(mDevice, getGlesMajorVersion(), getGlesMinorVersion());
+ }
- mListener.testRunEnded(0, emptyMap);
+ /**
+ * Get GL major version (based on package name)
+ */
+ private int getGlesMajorVersion() throws DeviceNotAvailableException {
+ if ("dEQP-GLES2".equals(mName)) {
+ return 2;
+ } else if ("dEQP-GLES3".equals(mName)) {
+ return 3;
+ } else if ("dEQP-GLES31".equals(mName)) {
+ return 3;
+ } else {
+ throw new IllegalStateException("getGlesMajorVersion called for non gles pkg");
+ }
+ }
+
+ /**
+ * Get GL minor version (based on package name)
+ */
+ private int getGlesMinorVersion() throws DeviceNotAvailableException {
+ if ("dEQP-GLES2".equals(mName)) {
+ return 0;
+ } else if ("dEQP-GLES3".equals(mName)) {
+ return 0;
+ } else if ("dEQP-GLES31".equals(mName)) {
+ return 1;
+ } else {
+ throw new IllegalStateException("getGlesMinorVersion called for non gles pkg");
}
}
@@ -534,15 +1111,33 @@
* {@inheritDoc}
*/
@Override
- public void setDevice(ITestDevice device) {
- mDevice = device;
- }
+ public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
+ final Map<String, String> emptyMap = Collections.emptyMap();
+ final boolean isSupportedApi = !isOpenGlEsPackage() || isSupportedGles();
- /**
- * {@inheritDoc}
- */
- @Override
- public ITestDevice getDevice() {
- return mDevice;
+ listener.testRunStarted(getId(), mRemainingTests.size());
+
+ try {
+ if (isSupportedApi) {
+ // Make sure there is no pre-existing package form earlier interrupted test run.
+ uninstallTestApk();
+ installTestApk();
+
+ mInstanceListerner.setSink(listener);
+ runTests();
+
+ uninstallTestApk();
+ } else {
+ // Pass all tests if OpenGL ES version is not supported
+ fakePassTests(listener);
+ }
+ } catch (CapabilityQueryFailureException ex) {
+ // Platform is not behaving correctly, for example crashing when trying to create
+ // a window. Instead of silenty failing, signal failure by leaving the rest of the
+ // test cases in "NotExecuted" state
+ uninstallTestApk();
+ }
+
+ listener.testRunEnded(0, emptyMap);
}
}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/PrintTestRemoteTestRunner.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/PrintTestRemoteTestRunner.java
deleted file mode 100644
index 72dccd4..0000000
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/PrintTestRemoteTestRunner.java
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.tradefed.testtype;
-
-import com.android.ddmlib.AdbCommandRejectedException;
-import com.android.ddmlib.IShellEnabledDevice;
-import com.android.ddmlib.Log;
-import com.android.ddmlib.ShellCommandUnresponsiveException;
-import com.android.ddmlib.TimeoutException;
-import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.ITestRunListener;
-import com.android.ddmlib.testrunner.InstrumentationResultParser;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Hashtable;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.concurrent.TimeUnit;
-
-public class PrintTestRemoteTestRunner implements IRemoteAndroidTestRunner {
-
- private final String mPackageName;
- private final String mRunnerName;
- private IShellEnabledDevice mRemoteDevice;
- // default to no timeout
- private long mMaxTimeToOutputResponse = 0;
- private TimeUnit mMaxTimeUnits = TimeUnit.MILLISECONDS;
- private String mRunName = null;
-
- /** map of name-value instrumentation argument pairs */
- private Map<String, String> mArgMap;
- private InstrumentationResultParser mParser;
-
- private static final String LOG_TAG = "RemoteAndroidTest";
- private static final String DEFAULT_RUNNER_NAME = "android.test.InstrumentationTestRunner";
-
- private static final char CLASS_SEPARATOR = ',';
- private static final char METHOD_SEPARATOR = '#';
- private static final char RUNNER_SEPARATOR = '/';
-
- // defined instrumentation argument names
- private static final String CLASS_ARG_NAME = "class";
- private static final String LOG_ARG_NAME = "log";
- private static final String DEBUG_ARG_NAME = "debug";
- private static final String COVERAGE_ARG_NAME = "coverage";
- private static final String PACKAGE_ARG_NAME = "package";
- private static final String SIZE_ARG_NAME = "size";
-
- // This command starts a shell Java program (installed by this class)
- // in the folder owned by the shell user. This app creates a proxy
- // which does privileged operations such as wiping a package's user
- // data and then starts the tests passing the proxy. This enables
- // the tests to clear the print spooler data.
- private static final String INSTRUMENTATION_COMMAND =
- "chmod 755 /data/local/tmp/print-instrument && "
- + "/data/local/tmp/print-instrument instrument -w -r %1$s %2$s";
-
- /**
- * Creates a remote Android test runner.
- *
- * @param packageName the Android application package that contains the
- * tests to run
- * @param runnerName the instrumentation test runner to execute. If null,
- * will use default runner
- * @param remoteDevice the Android device to execute tests on
- */
- public PrintTestRemoteTestRunner(String packageName, String runnerName,
- IShellEnabledDevice remoteDevice) {
-
- mPackageName = packageName;
- mRunnerName = runnerName;
- mRemoteDevice = remoteDevice;
- mArgMap = new Hashtable<String, String>();
- }
-
- /**
- * Alternate constructor. Uses default instrumentation runner.
- *
- * @param packageName the Android application package that contains the
- * tests to run
- * @param remoteDevice the Android device to execute tests on
- */
- public PrintTestRemoteTestRunner(String packageName, IShellEnabledDevice remoteDevice) {
- this(packageName, null, remoteDevice);
- }
-
- @Override
- public String getPackageName() {
- return mPackageName;
- }
-
- @Override
- public String getRunnerName() {
- if (mRunnerName == null) {
- return DEFAULT_RUNNER_NAME;
- }
- return mRunnerName;
- }
-
- /**
- * Returns the complete instrumentation component path.
- */
- private String getRunnerPath() {
- return getPackageName() + RUNNER_SEPARATOR + getRunnerName();
- }
-
- @Override
- public void setClassName(String className) {
- addInstrumentationArg(CLASS_ARG_NAME, className);
- }
-
- @Override
- public void setClassNames(String[] classNames) {
- StringBuilder classArgBuilder = new StringBuilder();
-
- for (int i = 0; i < classNames.length; i++) {
- if (i != 0) {
- classArgBuilder.append(CLASS_SEPARATOR);
- }
- classArgBuilder.append(classNames[i]);
- }
- setClassName(classArgBuilder.toString());
- }
-
- @Override
- public void setMethodName(String className, String testName) {
- setClassName(className + METHOD_SEPARATOR + testName);
- }
-
- @Override
- public void setTestPackageName(String packageName) {
- addInstrumentationArg(PACKAGE_ARG_NAME, packageName);
- }
-
- @Override
- public void addInstrumentationArg(String name, String value) {
- if (name == null || value == null) {
- throw new IllegalArgumentException("name or value arguments cannot be null");
- }
- mArgMap.put(name, value);
- }
-
- @Override
- public void removeInstrumentationArg(String name) {
- if (name == null) {
- throw new IllegalArgumentException("name argument cannot be null");
- }
- mArgMap.remove(name);
- }
-
- @Override
- public void addBooleanArg(String name, boolean value) {
- addInstrumentationArg(name, Boolean.toString(value));
- }
-
- @Override
- public void setLogOnly(boolean logOnly) {
- addBooleanArg(LOG_ARG_NAME, logOnly);
- }
-
- @Override
- public void setDebug(boolean debug) {
- addBooleanArg(DEBUG_ARG_NAME, debug);
- }
-
- @Override
- public void setCoverage(boolean coverage) {
- addBooleanArg(COVERAGE_ARG_NAME, coverage);
- }
-
- @Override
- public void setTestCollection(boolean b) {
- throw new UnsupportedOperationException("Test Collection mode is not supported");
- }
-
- @Override
- public void setTestSize(TestSize size) {
- addInstrumentationArg(SIZE_ARG_NAME, ""/*size.getRunnerValue()*/);
- }
-
- @Override
- public void setMaxtimeToOutputResponse(int maxTimeToOutputResponse) {
- setMaxTimeToOutputResponse(maxTimeToOutputResponse, TimeUnit.MILLISECONDS);
- }
-
- @Override
- public void setMaxTimeToOutputResponse(long maxTimeToOutputResponse, TimeUnit maxTimeUnits) {
- mMaxTimeToOutputResponse = maxTimeToOutputResponse;
- mMaxTimeUnits = maxTimeUnits;
- }
-
- @Override
- public void setRunName(String runName) {
- mRunName = runName;
- }
-
- @Override
- public void run(ITestRunListener... listeners) throws TimeoutException,
- AdbCommandRejectedException, ShellCommandUnresponsiveException, IOException {
- run(Arrays.asList(listeners));
- }
-
- @Override
- public void run(Collection<ITestRunListener> listeners) throws TimeoutException,
- AdbCommandRejectedException, ShellCommandUnresponsiveException, IOException {
- final String runCaseCommandStr = String.format(INSTRUMENTATION_COMMAND,
- getArgsCommand(), getRunnerPath());
- Log.i(LOG_TAG,
- String.format("Running %1$s on %2$s", runCaseCommandStr, mRemoteDevice.getName()));
- String runName = mRunName == null ? mPackageName : mRunName;
- mParser = new InstrumentationResultParser(runName, listeners);
-
- try {
- mRemoteDevice.executeShellCommand(runCaseCommandStr, mParser, mMaxTimeToOutputResponse,
- mMaxTimeUnits);
- } catch (IOException e) {
- Log.w(LOG_TAG, String.format("IOException %1$s when running tests %2$s on %3$s",
- e.toString(), getPackageName(), mRemoteDevice.getName()));
- // rely on parser to communicate results to listeners
- mParser.handleTestRunFailed(e.toString());
- throw e;
- } catch (ShellCommandUnresponsiveException e) {
- Log.w(LOG_TAG, String.format(
- "ShellCommandUnresponsiveException %1$s when running tests %2$s on %3$s",
- e.toString(), getPackageName(), mRemoteDevice.getName()));
- mParser.handleTestRunFailed(String
- .format("Failed to receive adb shell test output within %1$d ms. "
- + "Test may have timed out, or adb connection to device became"
- + "unresponsive", mMaxTimeToOutputResponse));
- throw e;
- } catch (TimeoutException e) {
- Log.w(LOG_TAG, String.format("TimeoutException when running tests %1$s on %2$s",
- getPackageName(), mRemoteDevice.getName()));
- mParser.handleTestRunFailed(e.toString());
- throw e;
- } catch (AdbCommandRejectedException e) {
- Log.w(LOG_TAG, String.format(
- "AdbCommandRejectedException %1$s when running tests %2$s on %3$s",
- e.toString(), getPackageName(), mRemoteDevice.getName()));
- mParser.handleTestRunFailed(e.toString());
- throw e;
- }
- }
-
- @Override
- public void cancel() {
- if (mParser != null) {
- mParser.cancel();
- }
- }
-
- /**
- * Returns the full instrumentation command line syntax for the provided
- * instrumentation arguments. Returns an empty string if no arguments were
- * specified.
- */
- private String getArgsCommand() {
- StringBuilder commandBuilder = new StringBuilder();
- for (Entry<String, String> argPair : mArgMap.entrySet()) {
- final String argCmd = String.format(" -e %1$s %2$s", argPair.getKey(),
- argPair.getValue());
- commandBuilder.append(argCmd);
- }
- return commandBuilder.toString();
- }
-}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/PrintTestRunner.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/PrintTestRunner.java
deleted file mode 100644
index 44d2d3a..0000000
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/PrintTestRunner.java
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.cts.tradefed.testtype;
-
-import com.android.cts.tradefed.build.CtsBuildHelper;
-import com.android.cts.tradefed.targetprep.SettingsToggler;
-import com.android.cts.util.AbiUtils;
-import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner.TestSize;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.result.ITestInvocationListener;
-import com.android.tradefed.testtype.IAbi;
-import com.android.tradefed.testtype.IBuildReceiver;
-import com.android.tradefed.testtype.IDeviceTest;
-import com.android.tradefed.testtype.IRemoteTest;
-import com.android.tradefed.util.StringEscapeUtils;
-
-import java.io.FileNotFoundException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Running the print tests requires modification of secure settings. Secure
- * settings cannot be changed from device CTS tests since system signature
- * permission is required. Such settings can be modified by the shell user,
- * so a host side test driver is used for enabling these services, running
- * the tests, and disabling the services.
- */
-public class PrintTestRunner implements IBuildReceiver, IRemoteTest, IDeviceTest {
-
- private static final String PRINT_TEST_AND_SERVICES_APP_NAME =
- "CtsPrintTestCases.apk";
-
- private static final String PRINT_TESTS_PACKAGE_NAME =
- "com.android.cts.print";
-
- private static final String FIRST_PRINT_SERVICE_NAME =
- "android.print.cts.services.FirstPrintService";
-
- private static final String SECOND_PRINT_SERVICE_NAME =
- "android.print.cts.services.SecondPrintService";
-
- private static final String SHELL_USER_FOLDER = "data/local/tmp";
-
- private static final String PRINT_INSTRUMENT_JAR = "CtsPrintInstrument.jar";
-
- private static final String PRINT_INSTRUMENT_SCRIPT = "print-instrument";
-
- private ITestDevice mDevice;
-
- private CtsBuildHelper mCtsBuild;
-
- private IAbi mAbi;
- private String mPackageName;
- private String mRunnerName = "android.test.InstrumentationTestRunner";
- private String mTestClassName;
- private String mTestMethodName;
- private String mTestPackageName;
- private int mTestTimeout = 10 * 60 * 1000; // 10 minutes
- private String mTestSize;
- private String mRunName = null;
- private Map<String, String> mInstrArgMap = new HashMap<String, String>();
-
- /**
- * @param abi The ABI to run the test on
- */
- public void setAbi(IAbi abi) {
- mAbi = abi;
- }
-
- @Override
- public void setBuild(IBuildInfo buildInfo) {
- mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
- }
-
- @Override
- public void setDevice(ITestDevice device) {
- mDevice = device;
- }
-
- @Override
- public ITestDevice getDevice() {
- return mDevice;
- }
-
- public void setPackageName(String packageName) {
- mPackageName = packageName;
- }
-
- public void setRunnerName(String runnerName) {
- mRunnerName = runnerName;
- }
-
- public void setClassName(String testClassName) {
- mTestClassName = testClassName;
- }
-
- public void setMethodName(String testMethodName) {
- mTestMethodName = StringEscapeUtils.escapeShell(testMethodName);
- }
-
- public void setTestPackageName(String testPackageName) {
- mTestPackageName = testPackageName;
- }
-
- public void setTestSize(String size) {
- mTestSize = size;
- }
-
- public void setRunName(String runName) {
- mRunName = runName;
- }
-
- @Override
- public void run(final ITestInvocationListener listener) throws DeviceNotAvailableException {
- installShellProgramAndScriptFiles();
- installTestsAndServicesApk();
- enablePrintServices();
- doRunTests(listener);
- disablePrintServices();
- uninstallTestsAndServicesApk();
- uninstallShellProgramAndScriptFiles();
- }
-
- private void doRunTests(ITestInvocationListener listener)
- throws DeviceNotAvailableException {
- if (mPackageName == null) {
- throw new IllegalArgumentException("package name has not been set");
- }
- if (mDevice == null) {
- throw new IllegalArgumentException("Device has not been set");
- }
-
- IRemoteAndroidTestRunner runner = new PrintTestRemoteTestRunner(mPackageName,
- mRunnerName, mDevice.getIDevice());
-
- if (mTestClassName != null) {
- if (mTestMethodName != null) {
- runner.setMethodName(mTestClassName, mTestMethodName);
- } else {
- runner.setClassName(mTestClassName);
- }
- } else if (mTestPackageName != null) {
- runner.setTestPackageName(mTestPackageName);
- }
- if (mTestSize != null) {
- runner.setTestSize(TestSize.getTestSize(mTestSize));
- }
- runner.setMaxTimeToOutputResponse(mTestTimeout, TimeUnit.MILLISECONDS);
- if (mRunName != null) {
- runner.setRunName(mRunName);
- }
- for (Map.Entry<String, String> argEntry : mInstrArgMap.entrySet()) {
- runner.addInstrumentationArg(argEntry.getKey(), argEntry.getValue());
- }
-
- mDevice.runInstrumentationTests(runner, listener);
- }
-
- private void installShellProgramAndScriptFiles() throws DeviceNotAvailableException {
- installFile(PRINT_INSTRUMENT_JAR);
- installFile(PRINT_INSTRUMENT_SCRIPT);
- }
-
- private void installFile(String fileName) throws DeviceNotAvailableException {
- try {
- final boolean success = getDevice().pushFile(mCtsBuild.getTestApp(
- fileName), SHELL_USER_FOLDER + "/" + fileName);
- if (!success) {
- throw new IllegalArgumentException("Failed to install "
- + fileName + " on " + getDevice().getSerialNumber());
- }
- } catch (FileNotFoundException fnfe) {
- throw new IllegalArgumentException("Cannot find file: " + fileName);
- }
- }
-
- private void uninstallShellProgramAndScriptFiles() throws DeviceNotAvailableException {
- getDevice().executeShellCommand("rm " + SHELL_USER_FOLDER + "/"
- + PRINT_INSTRUMENT_JAR);
- getDevice().executeShellCommand("rm " + SHELL_USER_FOLDER + "/"
- + PRINT_INSTRUMENT_SCRIPT);
- }
-
- private void installTestsAndServicesApk() throws DeviceNotAvailableException {
- try {
- String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
- String installCode = getDevice().installPackage(mCtsBuild.getTestApp(
- PRINT_TEST_AND_SERVICES_APP_NAME), true, options);
- if (installCode != null) {
- throw new IllegalArgumentException("Failed to install "
- + PRINT_TEST_AND_SERVICES_APP_NAME + " on " + getDevice().getSerialNumber()
- + ". Reason: " + installCode);
- }
- } catch (FileNotFoundException fnfe) {
- throw new IllegalArgumentException("Cannot find file: "
- + PRINT_TEST_AND_SERVICES_APP_NAME);
- }
- }
-
- private void uninstallTestsAndServicesApk() throws DeviceNotAvailableException {
- getDevice().uninstallPackage(PRINT_TESTS_PACKAGE_NAME);
- }
-
- private void enablePrintServices() throws DeviceNotAvailableException {
- String enabledServicesValue = PRINT_TESTS_PACKAGE_NAME + "/" + FIRST_PRINT_SERVICE_NAME
- + ":" + PRINT_TESTS_PACKAGE_NAME + "/" + SECOND_PRINT_SERVICE_NAME;
- SettingsToggler.setSecureString(getDevice(), "enabled_print_services",
- enabledServicesValue);
- }
-
- private void disablePrintServices() throws DeviceNotAvailableException {
- SettingsToggler.setSecureString(getDevice(), "enabled_print_services", "");
- }
-}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java
index 9ef6257..59dee04 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java
@@ -35,7 +35,11 @@
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Collection;
+import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
/**
* Container for CTS test info.
@@ -53,8 +57,6 @@
"com.android.cts.tradefed.testtype.AccessibilityTestRunner";
public static final String ACCESSIBILITY_SERVICE_TEST =
"com.android.cts.tradefed.testtype.AccessibilityServiceTestRunner";
- public static final String PRINT_TEST =
- "com.android.cts.tradefed.testtype.PrintTestRunner";
public static final String DISPLAY_TEST =
"com.android.cts.tradefed.testtype.DisplayTestRunner";
public static final String UIAUTOMATOR_TEST = "uiAutomator";
@@ -76,6 +78,9 @@
private Collection<TestIdentifier> mTests = new LinkedHashSet<TestIdentifier>();
// also maintain an index of known test classes
private Collection<String> mTestClasses = new LinkedHashSet<String>();
+ // store instance arguments in order too for consistency
+ private Map<TestIdentifier, List<Map<String, String>>> mTestInstanceArguments =
+ new LinkedHashMap<>();
// dynamic options, not parsed from package xml
private String mClassName;
@@ -240,7 +245,8 @@
mDigest = generateDigest(testCaseDir, mJarPath);
return vmHostTest;
} else if (DEQP_TEST.equals(mTestType)) {
- DeqpTestRunner deqpTest = new DeqpTestRunner(mAppPackageName, mName, mTests);
+ DeqpTestRunner deqpTest =
+ new DeqpTestRunner(mAppPackageName, mName, mTests, mTestInstanceArguments);
deqpTest.setAbi(mAbi);
return deqpTest;
} else if (NATIVE_TEST.equals(mTestType)) {
@@ -255,9 +261,6 @@
} else if (ACCESSIBILITY_TEST.equals(mTestType)) {
AccessibilityTestRunner test = new AccessibilityTestRunner();
return setInstrumentationTest(test, testCaseDir);
- } else if (PRINT_TEST.equals(mTestType)) {
- PrintTestRunner test = new PrintTestRunner();
- return setPrintTest(test, testCaseDir);
} else if (ACCESSIBILITY_SERVICE_TEST.equals(mTestType)) {
@SuppressWarnings("deprecation")
AccessibilityServiceTestRunner test = new AccessibilityServiceTestRunner();
@@ -291,19 +294,6 @@
}
}
- private PrintTestRunner setPrintTest(PrintTestRunner printTest,
- File testCaseDir) {
- printTest.setRunName(mAppPackageName);
- printTest.setPackageName(mAppNameSpace);
- printTest.setRunnerName(mRunner);
- printTest.setTestPackageName(mTestPackageName);
- printTest.setClassName(mClassName);
- printTest.setMethodName(mMethodName);
- printTest.setAbi(mAbi);
- mDigest = generateDigest(testCaseDir, String.format("%s.apk", mName));
- return printTest;
- }
-
/**
* Populates given {@link CtsInstrumentationApkTest} with data from the package xml.
*
@@ -379,6 +369,7 @@
void addTest(TestIdentifier testDef, int timeout) {
mTests.add(testDef);
mTestClasses.add(testDef.getClassName());
+ mTestInstanceArguments.put(testDef, new LinkedList<Map<String, String>>());
// 0 means no timeout, so keep 0 if already is.
if ((timeout > mTimeoutInMins) && (mTimeoutInMins != 0)) {
mTimeoutInMins = timeout;
@@ -386,6 +377,16 @@
}
/**
+ * Add a test instance to an existing {@link TestIdentifier}.
+ */
+ void addTestInstance(TestIdentifier testDef, Map<String, String> instanceArguments) {
+ if (!mTestInstanceArguments.containsKey(testDef)) {
+ throw new IllegalStateException("test id does not name an existing test");
+ }
+ mTestInstanceArguments.get(testDef).add(instanceArguments);
+ }
+
+ /**
* {@inheritDoc}
*/
@Override
@@ -394,6 +395,15 @@
}
/**
+ * Get the instance argument map for tests.
+ * <p/>
+ * Exposed for unit testing.
+ */
+ public Map<TestIdentifier, List<Map<String, String>>> getTestInstanceArguments() {
+ return mTestInstanceArguments;
+ }
+
+ /**
* {@inheritDoc}
*/
@Override
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageXmlParser.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageXmlParser.java
index baceb8b..649dd9e 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageXmlParser.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageXmlParser.java
@@ -59,6 +59,7 @@
* <TestSuite ...>
* <TestCase>
* <Test>
+ * <TestInstance> (optional)
*/
private class TestPackageHandler extends DefaultHandler {
@@ -66,9 +67,11 @@
private static final String TEST_SUITE_TAG = "TestSuite";
private static final String TEST_CASE_TAG = "TestCase";
private static final String TEST_TAG = "Test";
+ private static final String TEST_INSTANCE_TAG = "TestInstance";
// holds current class name segments
private Stack<String> mClassNameStack = new Stack<String>();
+ private TestIdentifier mTestId;
@Override
public void startElement(String uri, String localName, String name, Attributes attributes) {
@@ -139,6 +142,7 @@
classNameBuilder.append(".");
}
}
+ mTestId = new TestIdentifier(classNameBuilder.toString(), methodName);
int timeout = -1;
String timeoutStr = attributes.getValue("timeout");
if (timeoutStr != null) {
@@ -158,14 +162,24 @@
}
}
for (String abi : abis) {
- TestIdentifier testId = new TestIdentifier(
- classNameBuilder.toString(), methodName);
- mPackageDefs.get(abi).addTest(testId, timeout);
+ mPackageDefs.get(abi).addTest(mTestId, timeout);
}
}
}
+ } else if (TEST_INSTANCE_TAG.equals(localName)) {
+ if (mTestId != null) {
+ final Map<String, String> instanceArguments = genAttributeMap(attributes);
+ for (TestPackageDef packageDef : mPackageDefs.values()) {
+ if (packageDef.getTests().contains(mTestId)) {
+ packageDef.addTestInstance(mTestId, instanceArguments);
+ }
+ }
+ } else {
+ Log.e(LOG_TAG, String.format(
+ "Invalid XML: encountered a '%s' tag not enclosed within a '%s' tag",
+ TEST_INSTANCE_TAG, TEST_TAG));
+ }
}
-
}
private String getTestType(Attributes attributes) {
@@ -182,6 +196,8 @@
public void endElement (String uri, String localName, String qName) {
if (TEST_SUITE_TAG.equals(localName) || TEST_CASE_TAG.equals(localName)) {
mClassNameStack.pop();
+ } else if (TEST_TAG.equals(localName)) {
+ mTestId = null;
}
}
@@ -192,6 +208,19 @@
return stringValue != null &&
Boolean.parseBoolean(stringValue);
}
+
+ private Map<String, String> genAttributeMap(Attributes attributes) {
+ final Map<String, String> attribMap = new HashMap<String, String>();
+ for (int i = 0; i < attributes.getLength(); ++i) {
+ final String localName = attributes.getLocalName(i);
+ final String namespace = attributes.getURI(i);
+ final String fullyQualifiedName =
+ (namespace.isEmpty()) ? (localName) : (namespace + ":" + localName);
+
+ attribMap.put(fullyQualifiedName, attributes.getValue(i));
+ }
+ return attribMap;
+ }
}
@Override
diff --git a/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/DeqpTestRunnerTest.java b/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/DeqpTestRunnerTest.java
index c41793f..2721ec6 100644
--- a/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/DeqpTestRunnerTest.java
+++ b/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/DeqpTestRunnerTest.java
@@ -21,6 +21,7 @@
import com.android.ddmlib.IShellOutputReceiver;
import com.android.ddmlib.testrunner.ITestRunListener;
import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.testtype.IAbi;
@@ -32,7 +33,10 @@
import java.io.File;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
import java.util.Map;
/**
@@ -45,8 +49,23 @@
private static final String LOG_FILE_NAME = "/sdcard/TestLog.qpa";
private static final String INSTRUMENTATION_NAME =
"com.drawelements.deqp/com.drawelements.deqp.testercore.DeqpInstrumentation";
+ private static final String QUERY_INSTRUMENTATION_NAME =
+ "com.drawelements.deqp/com.drawelements.deqp.platformutil.DeqpPlatformCapabilityQueryInstrumentation";
private static final String DEQP_ONDEVICE_APK = "com.drawelements.deqp.apk";
private static final String DEQP_ONDEVICE_PKG = "com.drawelements.deqp";
+ private static final String ONLY_LANDSCAPE_FEATURES =
+ "feature:"+DeqpTestRunner.FEATURE_LANDSCAPE;
+ private static final String ALL_FEATURES =
+ ONLY_LANDSCAPE_FEATURES + "\nfeature:"+DeqpTestRunner.FEATURE_PORTRAIT;
+ private static List<Map<String,String>> DEFAULT_INSTANCE_ARGS;
+
+ static {
+ DEFAULT_INSTANCE_ARGS = new ArrayList<>(1);
+ DEFAULT_INSTANCE_ARGS.add(new HashMap<String,String>());
+ DEFAULT_INSTANCE_ARGS.iterator().next().put("glconfig", "rgba8888d24s8");
+ DEFAULT_INSTANCE_ARGS.iterator().next().put("rotation", "unspecified");
+ DEFAULT_INSTANCE_ARGS.iterator().next().put("surfacetype", "window");
+ }
/**
* {@inheritDoc}
@@ -106,13 +125,15 @@
ITestInvocationListener mockListener
= EasyMock.createStrictMock(ITestInvocationListener.class);
Collection<TestIdentifier> tests = new ArrayList<TestIdentifier>();
-
tests.add(testId);
+ Map<TestIdentifier, List<Map<String, String>>> instance = new HashMap<>();
+ instance.put(testId, DEFAULT_INSTANCE_ARGS);
+
DeqpTestRunner deqpTest = new DeqpTestRunner(NAME,
"dEQP-GLES" + Integer.toString(requiredMajorVersion)
+ (requiredMinorVersion > 0 ? Integer.toString(requiredMinorVersion) : ""),
- tests);
+ tests, instance);
deqpTest.setAbi(UnitTests.ABI);
int version = (majorVersion << 16) | minorVersion;
@@ -129,6 +150,8 @@
EasyMock.eq(AbiUtils.createAbiFlag(UnitTests.ABI.getName()))))
.andReturn(null).once();
+ expectRenderConfigQuery(mockDevice, requiredMajorVersion, requiredMinorVersion);
+
EasyMock.expect(mockDevice.executeShellCommand(
EasyMock.eq("rm " + CASE_LIST_FILE_NAME))).andReturn("").once();
@@ -140,7 +163,9 @@
String command = String.format(
"am instrument %s -w -e deqpLogFileName \"%s\" -e deqpCmdLine \""
- + "--deqp-caselist-file=%s --deqp-gl-config-name=rgba8888d24s8\" "
+ + "--deqp-caselist-file=%s --deqp-gl-config-name=rgba8888d24s8 "
+ + "--deqp-screen-rotation=unspecified "
+ + "--deqp-surface-type=window\" "
+ "-e deqpLogData \"%s\" %s",
AbiUtils.createAbiFlag(UnitTests.ABI.getName()), LOG_FILE_NAME,
CASE_LIST_FILE_NAME, false, INSTRUMENTATION_NAME);
@@ -188,6 +213,46 @@
EasyMock.verify(mockDevice);
}
+ private void expectRenderConfigQuery(ITestDevice mockDevice, int majorVersion, int minorVersion)
+ throws Exception {
+ expectRenderConfigQuery(mockDevice, String.format("--deqp-gl-config-name=rgba8888d24s8 "
+ + "--deqp-screen-rotation=unspecified "
+ + "--deqp-surface-type=window "
+ + "--deqp-gl-major-version=%d "
+ + "--deqp-gl-minor-version=%d", majorVersion, minorVersion));
+ }
+
+ private void expectRenderConfigQuery(ITestDevice mockDevice, String commandLine)
+ throws Exception {
+ expectRenderConfigQueryAndReturn(mockDevice, commandLine, "Yes");
+ }
+
+ private void expectRenderConfigQueryAndReturn(ITestDevice mockDevice, String commandLine,
+ String output) throws Exception {
+ final String queryOutput = "INSTRUMENTATION_RESULT: Supported=" + output + "\r\n"
+ + "INSTRUMENTATION_CODE: 0\r\n";
+ final String command = String.format(
+ "am instrument %s -w -e deqpQueryType renderConfigSupported -e deqpCmdLine "
+ + "\"%s\" %s",
+ AbiUtils.createAbiFlag(UnitTests.ABI.getName()), commandLine, QUERY_INSTRUMENTATION_NAME);
+
+ mockDevice.executeShellCommand(EasyMock.eq(command),
+ EasyMock.<IShellOutputReceiver>notNull());
+
+ EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
+ @Override
+ public Object answer() {
+ IShellOutputReceiver receiver
+ = (IShellOutputReceiver)EasyMock.getCurrentArguments()[1];
+
+ receiver.addOutput(queryOutput.getBytes(), 0, queryOutput.length());
+ receiver.flush();
+
+ return null;
+ }
+ });
+ }
+
/**
* Test that result code produces correctly pass or fail.
*/
@@ -228,10 +293,12 @@
ITestInvocationListener mockListener
= EasyMock.createStrictMock(ITestInvocationListener.class);
Collection<TestIdentifier> tests = new ArrayList<TestIdentifier>();
-
tests.add(testId);
- DeqpTestRunner deqpTest = new DeqpTestRunner(NAME, NAME, tests);
+ Map<TestIdentifier, List<Map<String, String>>> instance = new HashMap<>();
+ instance.put(testId, DEFAULT_INSTANCE_ARGS);
+
+ DeqpTestRunner deqpTest = new DeqpTestRunner(NAME, NAME, tests, instance);
deqpTest.setAbi(UnitTests.ABI);
int version = 3 << 16;
@@ -245,6 +312,8 @@
EasyMock.eq(true), EasyMock.eq(AbiUtils.createAbiFlag(UnitTests.ABI.getName()))))
.andReturn(null).once();
+ expectRenderConfigQuery(mockDevice, 3, 0);
+
EasyMock.expect(mockDevice.executeShellCommand(EasyMock.eq("rm " + CASE_LIST_FILE_NAME)))
.andReturn("").once();
@@ -256,7 +325,9 @@
String command = String.format(
"am instrument %s -w -e deqpLogFileName \"%s\" -e deqpCmdLine \""
- + "--deqp-caselist-file=%s --deqp-gl-config-name=rgba8888d24s8\" "
+ + "--deqp-caselist-file=%s --deqp-gl-config-name=rgba8888d24s8 "
+ + "--deqp-screen-rotation=unspecified "
+ + "--deqp-surface-type=window\" "
+ "-e deqpLogData \"%s\" %s",
AbiUtils.createAbiFlag(UnitTests.ABI.getName()), LOG_FILE_NAME,
CASE_LIST_FILE_NAME, false, INSTRUMENTATION_NAME);
@@ -285,7 +356,8 @@
if (!pass) {
mockListener.testFailed(testId,
- resultCode + ": Detail" + resultCode);
+ "=== with config {glformat=rgba8888d24s8,rotation=unspecified,surfacetype=window} ===\n"
+ + resultCode + ": Detail" + resultCode);
EasyMock.expectLastCall().once();
}
@@ -412,12 +484,14 @@
ITestInvocationListener mockListener
= EasyMock.createStrictMock(ITestInvocationListener.class);
Collection<TestIdentifier> tests = new ArrayList<TestIdentifier>();
+ Map<TestIdentifier, List<Map<String, String>>> instances = new HashMap<>();
for (TestIdentifier id : testIds) {
tests.add(id);
+ instances.put(id, DEFAULT_INSTANCE_ARGS);
}
- DeqpTestRunner deqpTest = new DeqpTestRunner(NAME, NAME, tests);
+ DeqpTestRunner deqpTest = new DeqpTestRunner(NAME, NAME, tests, instances);
deqpTest.setAbi(UnitTests.ABI);
int version = 3 << 16;
@@ -430,6 +504,8 @@
EasyMock.eq(true), EasyMock.eq(AbiUtils.createAbiFlag(UnitTests.ABI.getName()))))
.andReturn(null).once();
+ expectRenderConfigQuery(mockDevice, 3, 0);
+
EasyMock.expect(mockDevice.executeShellCommand(EasyMock.eq("rm " + CASE_LIST_FILE_NAME)))
.andReturn("").once();
@@ -441,7 +517,9 @@
String command = String.format(
"am instrument %s -w -e deqpLogFileName \"%s\" -e deqpCmdLine \""
- + "--deqp-caselist-file=%s --deqp-gl-config-name=rgba8888d24s8\" "
+ + "--deqp-caselist-file=%s --deqp-gl-config-name=rgba8888d24s8 "
+ + "--deqp-screen-rotation=unspecified "
+ + "--deqp-surface-type=window\" "
+ "-e deqpLogData \"%s\" %s",
AbiUtils.createAbiFlag(UnitTests.ABI.getName()), LOG_FILE_NAME,
CASE_LIST_FILE_NAME, false, INSTRUMENTATION_NAME);
@@ -493,6 +571,269 @@
}
/**
+ * Test that test are left unexecuted if pm list query fails
+ */
+ public void testRun_queryPmListFailure()
+ throws Exception {
+ final TestIdentifier testId = new TestIdentifier("dEQP-GLES3.orientation", "test");
+
+ ITestDevice mockDevice = EasyMock.createMock(ITestDevice.class);
+ ITestInvocationListener mockListener
+ = EasyMock.createStrictMock(ITestInvocationListener.class);
+ Collection<TestIdentifier> tests = new ArrayList<TestIdentifier>();
+ tests.add(testId);
+
+ Map<TestIdentifier, List<Map<String, String>>> instance = new HashMap<>();
+ instance.put(testId, new ArrayList<Map<String,String>>(1));
+ instance.get(testId).add(new HashMap<String,String>());
+ instance.get(testId).iterator().next().put("glconfig", "rgba8888d24s8");
+ instance.get(testId).iterator().next().put("rotation", "90");
+ instance.get(testId).iterator().next().put("surfacetype", "window");
+
+ DeqpTestRunner deqpTest = new DeqpTestRunner(NAME, NAME, tests, instance);
+ deqpTest.setAbi(UnitTests.ABI);
+ deqpTest.setDevice(mockDevice);
+ deqpTest.setBuildHelper(new StubCtsBuildHelper());
+
+ int version = 3 << 16;
+ EasyMock.expect(mockDevice.getProperty("ro.opengles.version"))
+ .andReturn(Integer.toString(version)).atLeastOnce();
+
+ EasyMock.expect(mockDevice.executeShellCommand("pm list features"))
+ .andReturn("not a valid format");
+
+ EasyMock.expect(mockDevice.uninstallPackage(EasyMock.eq(DEQP_ONDEVICE_PKG))).
+ andReturn("").once();
+
+ EasyMock.expect(mockDevice.installPackage(EasyMock.<File>anyObject(),
+ EasyMock.eq(true),
+ EasyMock.eq(AbiUtils.createAbiFlag(UnitTests.ABI.getName())))).andReturn(null)
+ .once();
+
+ EasyMock.expect(mockDevice.uninstallPackage(EasyMock.eq(DEQP_ONDEVICE_PKG)))
+ .andReturn("").once();
+
+ mockListener.testRunStarted(ID, 1);
+ EasyMock.expectLastCall().once();
+
+ mockListener.testRunEnded(EasyMock.anyLong(), EasyMock.<Map<String, String>>notNull());
+ EasyMock.expectLastCall().once();
+
+ EasyMock.replay(mockDevice);
+ EasyMock.replay(mockListener);
+ deqpTest.run(mockListener);
+ EasyMock.verify(mockListener);
+ EasyMock.verify(mockDevice);
+ }
+
+ /**
+ * Test that test are left unexecuted if renderablity query fails
+ */
+ public void testRun_queryRenderabilityFailure()
+ throws Exception {
+ final TestIdentifier testId = new TestIdentifier("dEQP-GLES3.orientation", "test");
+
+ ITestDevice mockDevice = EasyMock.createMock(ITestDevice.class);
+ ITestInvocationListener mockListener
+ = EasyMock.createStrictMock(ITestInvocationListener.class);
+ Collection<TestIdentifier> tests = new ArrayList<TestIdentifier>();
+ tests.add(testId);
+
+ Map<TestIdentifier, List<Map<String, String>>> instance = new HashMap<>();
+ instance.put(testId, new ArrayList<Map<String,String>>(1));
+ instance.get(testId).add(new HashMap<String,String>());
+ instance.get(testId).iterator().next().put("glconfig", "rgba8888d24s8");
+ instance.get(testId).iterator().next().put("rotation", "unspecified");
+ instance.get(testId).iterator().next().put("surfacetype", "window");
+
+ DeqpTestRunner deqpTest = new DeqpTestRunner(NAME, NAME, tests, instance);
+ deqpTest.setAbi(UnitTests.ABI);
+ deqpTest.setDevice(mockDevice);
+ deqpTest.setBuildHelper(new StubCtsBuildHelper());
+
+ int version = 3 << 16;
+ EasyMock.expect(mockDevice.getProperty("ro.opengles.version"))
+ .andReturn(Integer.toString(version)).atLeastOnce();
+
+ EasyMock.expect(mockDevice.uninstallPackage(EasyMock.eq(DEQP_ONDEVICE_PKG))).
+ andReturn("").once();
+
+ EasyMock.expect(mockDevice.installPackage(EasyMock.<File>anyObject(),
+ EasyMock.eq(true),
+ EasyMock.eq(AbiUtils.createAbiFlag(UnitTests.ABI.getName())))).andReturn(null)
+ .once();
+
+ expectRenderConfigQueryAndReturn(mockDevice,
+ "--deqp-gl-config-name=rgba8888d24s8 "
+ + "--deqp-screen-rotation=unspecified "
+ + "--deqp-surface-type=window "
+ + "--deqp-gl-major-version=3 "
+ + "--deqp-gl-minor-version=0", "Maybe?");
+
+ EasyMock.expect(mockDevice.uninstallPackage(EasyMock.eq(DEQP_ONDEVICE_PKG)))
+ .andReturn("").once();
+
+ mockListener.testRunStarted(ID, 1);
+ EasyMock.expectLastCall().once();
+
+ mockListener.testRunEnded(EasyMock.anyLong(), EasyMock.<Map<String, String>>notNull());
+ EasyMock.expectLastCall().once();
+
+ EasyMock.replay(mockDevice);
+ EasyMock.replay(mockListener);
+ deqpTest.run(mockListener);
+ EasyMock.verify(mockListener);
+ EasyMock.verify(mockDevice);
+ }
+
+ /**
+ * Test that orientation is supplied to runner correctly
+ */
+ private void testOrientation(final String rotation, final String featureString)
+ throws Exception {
+ final TestIdentifier testId = new TestIdentifier("dEQP-GLES3.orientation", "test");
+ final String testPath = "dEQP-GLES3.orientation.test";
+ final String testTrie = "{dEQP-GLES3{orientation{test}}}";
+ final String output = "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=releaseName\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=2014.x\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=releaseId\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=0xcafebabe\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=targetName\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=android\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginSession\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginTestCase\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-BeginTestCase-TestCasePath=" + testPath + "\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Code=Pass\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Details=Pass\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=TestCaseResult\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=EndTestCase\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=EndSession\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_CODE: 0\r\n";
+
+ ITestDevice mockDevice = EasyMock.createMock(ITestDevice.class);
+ ITestInvocationListener mockListener
+ = EasyMock.createStrictMock(ITestInvocationListener.class);
+ Collection<TestIdentifier> tests = new ArrayList<TestIdentifier>();
+ tests.add(testId);
+
+ Map<TestIdentifier, List<Map<String, String>>> instance = new HashMap<>();
+ instance.put(testId, new ArrayList<Map<String,String>>(1));
+ instance.get(testId).add(new HashMap<String,String>());
+ instance.get(testId).iterator().next().put("glconfig", "rgba8888d24s8");
+ instance.get(testId).iterator().next().put("rotation", rotation);
+ instance.get(testId).iterator().next().put("surfacetype", "window");
+
+ DeqpTestRunner deqpTest = new DeqpTestRunner(NAME, NAME, tests, instance);
+ deqpTest.setAbi(UnitTests.ABI);
+ deqpTest.setDevice(mockDevice);
+ deqpTest.setBuildHelper(new StubCtsBuildHelper());
+
+ int version = 3 << 16;
+ EasyMock.expect(mockDevice.getProperty("ro.opengles.version"))
+ .andReturn(Integer.toString(version)).atLeastOnce();
+
+ if (!rotation.equals(DeqpTestRunner.BatchRunConfiguration.ROTATION_UNSPECIFIED)) {
+ EasyMock.expect(mockDevice.executeShellCommand("pm list features"))
+ .andReturn(featureString);
+ }
+
+ final boolean isPortraitOrientation =
+ rotation.equals(DeqpTestRunner.BatchRunConfiguration.ROTATION_PORTRAIT) ||
+ rotation.equals(DeqpTestRunner.BatchRunConfiguration.ROTATION_REVERSE_PORTRAIT);
+ final boolean isLandscapeOrientation =
+ rotation.equals(DeqpTestRunner.BatchRunConfiguration.ROTATION_LANDSCAPE) ||
+ rotation.equals(DeqpTestRunner.BatchRunConfiguration.ROTATION_REVERSE_LANDSCAPE);
+ final boolean executable =
+ rotation.equals(DeqpTestRunner.BatchRunConfiguration.ROTATION_UNSPECIFIED) ||
+ (isPortraitOrientation &&
+ featureString.contains(DeqpTestRunner.FEATURE_PORTRAIT)) ||
+ (isLandscapeOrientation &&
+ featureString.contains(DeqpTestRunner.FEATURE_LANDSCAPE));
+
+ EasyMock.expect(mockDevice.uninstallPackage(EasyMock.eq(DEQP_ONDEVICE_PKG))).
+ andReturn("").once();
+
+ EasyMock.expect(mockDevice.installPackage(EasyMock.<File>anyObject(),
+ EasyMock.eq(true),
+ EasyMock.eq(AbiUtils.createAbiFlag(UnitTests.ABI.getName())))).andReturn(null)
+ .once();
+
+ if (executable) {
+ expectRenderConfigQuery(mockDevice, String.format(
+ "--deqp-gl-config-name=rgba8888d24s8 --deqp-screen-rotation=%s "
+ + "--deqp-surface-type=window --deqp-gl-major-version=3 "
+ + "--deqp-gl-minor-version=0", rotation));
+
+ EasyMock.expect(
+ mockDevice.executeShellCommand(EasyMock.eq("rm " + CASE_LIST_FILE_NAME)))
+ .andReturn("").once();
+
+ EasyMock.expect(mockDevice.executeShellCommand(EasyMock.eq("rm " + LOG_FILE_NAME)))
+ .andReturn("").once();
+
+ EasyMock.expect(mockDevice.pushString(testTrie + "\n", CASE_LIST_FILE_NAME))
+ .andReturn(true).once();
+
+ String command = String.format(
+ "am instrument %s -w -e deqpLogFileName \"%s\" -e deqpCmdLine \""
+ + "--deqp-caselist-file=%s --deqp-gl-config-name=rgba8888d24s8 "
+ + "--deqp-screen-rotation=%s "
+ + "--deqp-surface-type=window\" "
+ + "-e deqpLogData \"%s\" %s",
+ AbiUtils.createAbiFlag(UnitTests.ABI.getName()), LOG_FILE_NAME,
+ CASE_LIST_FILE_NAME, rotation, false, INSTRUMENTATION_NAME);
+
+ mockDevice.executeShellCommand(EasyMock.eq(command),
+ EasyMock.<IShellOutputReceiver>notNull());
+
+ EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
+ @Override
+ public Object answer() {
+ IShellOutputReceiver receiver
+ = (IShellOutputReceiver)EasyMock.getCurrentArguments()[1];
+
+ receiver.addOutput(output.getBytes(), 0, output.length());
+ receiver.flush();
+
+ return null;
+ }
+ });
+ }
+
+ EasyMock.expect(mockDevice.uninstallPackage(EasyMock.eq(DEQP_ONDEVICE_PKG)))
+ .andReturn("").once();
+
+ mockListener.testRunStarted(ID, 1);
+ EasyMock.expectLastCall().once();
+
+ mockListener.testStarted(EasyMock.eq(testId));
+ EasyMock.expectLastCall().once();
+
+ mockListener.testEnded(EasyMock.eq(testId), EasyMock.<Map<String, String>>notNull());
+ EasyMock.expectLastCall().once();
+
+ mockListener.testRunEnded(EasyMock.anyLong(), EasyMock.<Map<String, String>>notNull());
+ EasyMock.expectLastCall().once();
+
+ EasyMock.replay(mockDevice);
+ EasyMock.replay(mockListener);
+ deqpTest.run(mockListener);
+ EasyMock.verify(mockListener);
+ EasyMock.verify(mockDevice);
+ }
+
+ /**
* Test OpeGL ES3 tests on device with OpenGL ES2.
*/
public void testRun_require30DeviceVersion20() throws Exception {
@@ -596,4 +937,681 @@
public void testRun_resultTimeout() throws Exception {
testResultCode("Timeout", false);
}
+ /**
+ * Test dEQP Orientation
+ */
+ public void testRun_orientationLandscape() throws Exception {
+ testOrientation("90", ALL_FEATURES);
+ }
+
+ /**
+ * Test dEQP Orientation
+ */
+ public void testRun_orientationPortrait() throws Exception {
+ testOrientation("0", ALL_FEATURES);
+ }
+
+ /**
+ * Test dEQP Orientation
+ */
+ public void testRun_orientationReverseLandscape() throws Exception {
+ testOrientation("270", ALL_FEATURES);
+ }
+
+ /**
+ * Test dEQP Orientation
+ */
+ public void testRun_orientationReversePortrait() throws Exception {
+ testOrientation("180", ALL_FEATURES);
+ }
+
+ /**
+ * Test dEQP Orientation
+ */
+ public void testRun_orientationUnspecified() throws Exception {
+ testOrientation("unspecified", ALL_FEATURES);
+ }
+
+ /**
+ * Test dEQP Orientation with limited features
+ */
+ public void testRun_orientationUnspecifiedLimitedFeatures() throws Exception {
+ testOrientation("unspecified", ONLY_LANDSCAPE_FEATURES);
+ }
+
+ /**
+ * Test dEQP Orientation with limited features
+ */
+ public void testRun_orientationLandscapeLimitedFeatures() throws Exception {
+ testOrientation("90", ONLY_LANDSCAPE_FEATURES);
+ }
+
+ /**
+ * Test dEQP Orientation with limited features
+ */
+ public void testRun_orientationPortraitLimitedFeatures() throws Exception {
+ testOrientation("0", ONLY_LANDSCAPE_FEATURES);
+ }
+
+ /**
+ * Test dEQP unsupported pixel format
+ */
+ public void testRun_unsupportedPixelFormat() throws Exception {
+ final String pixelFormat = "rgba5658d16m4";
+ final TestIdentifier testId = new TestIdentifier("dEQP-GLES3.pixelformat", "test");
+ final String testPath = "dEQP-GLES3.pixelformat.test";
+ final String testTrie = "{dEQP-GLES3{pixelformat{test}}}";
+ final String output = "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=releaseName\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=2014.x\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=releaseId\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=0xcafebabe\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=targetName\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=android\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginSession\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginTestCase\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-BeginTestCase-TestCasePath=" + testPath + "\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Code=Pass\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Details=Pass\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=TestCaseResult\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=EndTestCase\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=EndSession\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_CODE: 0\r\n";
+
+ ITestDevice mockDevice = EasyMock.createMock(ITestDevice.class);
+ ITestInvocationListener mockListener
+ = EasyMock.createStrictMock(ITestInvocationListener.class);
+ Collection<TestIdentifier> tests = new ArrayList<TestIdentifier>();
+ tests.add(testId);
+
+ Map<TestIdentifier, List<Map<String, String>>> instance = new HashMap<>();
+ instance.put(testId, new ArrayList<Map<String,String>>(1));
+ instance.get(testId).add(new HashMap<String,String>());
+ instance.get(testId).iterator().next().put("glconfig", pixelFormat);
+ instance.get(testId).iterator().next().put("rotation", "unspecified");
+ instance.get(testId).iterator().next().put("surfacetype", "window");
+
+ DeqpTestRunner deqpTest = new DeqpTestRunner(NAME, NAME, tests, instance);
+ deqpTest.setAbi(UnitTests.ABI);
+ deqpTest.setDevice(mockDevice);
+ deqpTest.setBuildHelper(new StubCtsBuildHelper());
+
+ int version = 3 << 16;
+ EasyMock.expect(mockDevice.getProperty("ro.opengles.version"))
+ .andReturn(Integer.toString(version)).atLeastOnce();
+
+ EasyMock.expect(mockDevice.uninstallPackage(EasyMock.eq(DEQP_ONDEVICE_PKG))).
+ andReturn("").once();
+
+ EasyMock.expect(mockDevice.installPackage(EasyMock.<File>anyObject(),
+ EasyMock.eq(true),
+ EasyMock.eq(AbiUtils.createAbiFlag(UnitTests.ABI.getName())))).andReturn(null)
+ .once();
+
+ expectRenderConfigQueryAndReturn(mockDevice, String.format(
+ "--deqp-gl-config-name=%s --deqp-screen-rotation=unspecified "
+ + "--deqp-surface-type=window "
+ + "--deqp-gl-major-version=3 "
+ + "--deqp-gl-minor-version=0", pixelFormat), "No");
+
+ EasyMock.expect(mockDevice.uninstallPackage(EasyMock.eq(DEQP_ONDEVICE_PKG)))
+ .andReturn("").once();
+
+ mockListener.testRunStarted(ID, 1);
+ EasyMock.expectLastCall().once();
+
+ mockListener.testStarted(EasyMock.eq(testId));
+ EasyMock.expectLastCall().once();
+
+ mockListener.testEnded(EasyMock.eq(testId), EasyMock.<Map<String, String>>notNull());
+ EasyMock.expectLastCall().once();
+
+ mockListener.testRunEnded(EasyMock.anyLong(), EasyMock.<Map<String, String>>notNull());
+ EasyMock.expectLastCall().once();
+
+ EasyMock.replay(mockDevice);
+ EasyMock.replay(mockListener);
+ deqpTest.run(mockListener);
+ EasyMock.verify(mockListener);
+ EasyMock.verify(mockDevice);
+ }
+
+ /**
+ * Test dEQP with multiple instances
+ */
+ public void testRun_multipleInstances() throws Exception {
+ final String instrumentationAnswerConfigA =
+ "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=releaseName\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=2014.x\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=releaseId\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=0xcafebabe\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=targetName\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=android\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginSession\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginTestCase\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-BeginTestCase-TestCasePath=dEQP-GLES3.instances.passall\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Code=Pass\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Details=Pass\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=TestCaseResult\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=EndTestCase\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginTestCase\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-BeginTestCase-TestCasePath=dEQP-GLES3.instances.failone\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Code=Pass\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Details=Pass\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=TestCaseResult\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginTestCase\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-BeginTestCase-TestCasePath=dEQP-GLES3.instances.crashtwo\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"; // early eof
+ final String instrumentationAnswerConfigB =
+ "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=releaseName\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=2014.x\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=releaseId\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=0xcafebabe\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=targetName\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=android\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginSession\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginTestCase\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-BeginTestCase-TestCasePath=dEQP-GLES3.instances.passall\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Code=Pass\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Details=Pass\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=TestCaseResult\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=EndTestCase\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginTestCase\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-BeginTestCase-TestCasePath=dEQP-GLES3.instances.crashtwo\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-TerminateTestCase-Reason=Magic\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=TerminateTestCase\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginTestCase\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-BeginTestCase-TestCasePath=dEQP-GLES3.instances.skipone\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Code=Pass\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Details=Pass\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=TestCaseResult\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=EndTestCase\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=EndSession\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_CODE: 0\r\n";
+ final String instrumentationAnswerConfigC =
+ "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=releaseName\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=2014.x\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=releaseId\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=0xcafebabe\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=targetName\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=android\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginSession\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginTestCase\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-BeginTestCase-TestCasePath=dEQP-GLES3.instances.failone\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Code=Fail\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Details=Fail\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=TestCaseResult\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=EndTestCase\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginTestCase\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-BeginTestCase-TestCasePath=dEQP-GLES3.instances.crashtwo\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Code=Pass\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Details=Pass\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=TestCaseResult\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=EndTestCase\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=EndSession\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_CODE: 0\r\n";
+
+ final TestIdentifier[] testIds = {
+ new TestIdentifier("dEQP-GLES3.instances", "passall"),
+ new TestIdentifier("dEQP-GLES3.instances", "failone"),
+ new TestIdentifier("dEQP-GLES3.instances", "crashtwo"),
+ new TestIdentifier("dEQP-GLES3.instances", "skipone"),
+ };
+
+ final String[] testPaths = {
+ "dEQP-GLES3.instances.passall",
+ "dEQP-GLES3.instances.failone",
+ "dEQP-GLES3.instances.crashtwo",
+ "dEQP-GLES3.instances.skipone",
+ };
+
+ Map<String,String> supportedConfigA = new HashMap<>();
+ supportedConfigA.put("glconfig", "rgba8888d24s8");
+ supportedConfigA.put("rotation", "unspecified");
+ supportedConfigA.put("surfacetype", "window");
+
+ Map<String,String> supportedConfigB = new HashMap<>();
+ supportedConfigB.put("glconfig", "rgba8888d24s8");
+ supportedConfigB.put("rotation", "90");
+ supportedConfigB.put("surfacetype", "window");
+
+ Map<String,String> supportedConfigC = new HashMap<>();
+ supportedConfigC.put("glconfig", "rgba8888d24s8");
+ supportedConfigC.put("rotation", "180");
+ supportedConfigC.put("surfacetype", "window");
+
+ Map<String,String> unsupportedConfig = new HashMap<>();
+ unsupportedConfig.put("glconfig", "rgb565d16s0");
+ unsupportedConfig.put("rotation", "unspecified");
+ unsupportedConfig.put("surfacetype", "window");
+
+ Map<TestIdentifier, List<Map<String, String>>> instances = new HashMap<>();
+
+ // pass all
+ instances.put(testIds[0], new ArrayList<Map<String,String>>());
+ instances.get(testIds[0]).add(supportedConfigA);
+ instances.get(testIds[0]).add(supportedConfigB);
+
+ // fail one
+ instances.put(testIds[1], new ArrayList<Map<String,String>>());
+ instances.get(testIds[1]).add(supportedConfigA);
+ instances.get(testIds[1]).add(supportedConfigC);
+
+ // crash two
+ instances.put(testIds[2], new ArrayList<Map<String,String>>());
+ instances.get(testIds[2]).add(supportedConfigA);
+ instances.get(testIds[2]).add(supportedConfigC);
+ instances.get(testIds[2]).add(supportedConfigB);
+
+ // skip one
+ instances.put(testIds[3], new ArrayList<Map<String,String>>());
+ instances.get(testIds[3]).add(supportedConfigB);
+ instances.get(testIds[3]).add(unsupportedConfig);
+
+ Collection<TestIdentifier> tests = new ArrayList<TestIdentifier>();
+ for (TestIdentifier id : testIds) {
+ tests.add(id);
+ }
+
+ ITestDevice mockDevice = EasyMock.createMock(ITestDevice.class);
+ ITestInvocationListener mockListener
+ = EasyMock.createStrictMock(ITestInvocationListener.class);
+
+ DeqpTestRunner deqpTest = new DeqpTestRunner(NAME, NAME, tests, instances);
+ deqpTest.setAbi(UnitTests.ABI);
+ deqpTest.setDevice(mockDevice);
+ deqpTest.setBuildHelper(new StubCtsBuildHelper());
+
+ int version = 3 << 16;
+ EasyMock.expect(mockDevice.getProperty("ro.opengles.version"))
+ .andReturn(Integer.toString(version)).atLeastOnce();
+ EasyMock.expect(mockDevice.executeShellCommand("pm list features")).andReturn(ALL_FEATURES)
+ .anyTimes();
+
+ EasyMock.expect(mockDevice.uninstallPackage(EasyMock.eq(DEQP_ONDEVICE_PKG))).
+ andReturn("").once();
+
+ EasyMock.expect(mockDevice.installPackage(EasyMock.<File>anyObject(),
+ EasyMock.eq(true),
+ EasyMock.eq(AbiUtils.createAbiFlag(UnitTests.ABI.getName())))).andReturn(null)
+ .once();
+
+ // query config A
+ expectRenderConfigQueryAndReturn(mockDevice, "--deqp-gl-config-name=rgba8888d24s8 "
+ + "--deqp-screen-rotation=unspecified "
+ + "--deqp-surface-type=window "
+ + "--deqp-gl-major-version=3 "
+ + "--deqp-gl-minor-version=0", "Yes");
+
+ // run config A
+ runInstrumentationLineAndAnswer(mockDevice,
+ "{dEQP-GLES3{instances{passall,failone,crashtwo}}}",
+ "--deqp-caselist-file=" + CASE_LIST_FILE_NAME
+ + " --deqp-gl-config-name=rgba8888d24s8 "
+ + "--deqp-screen-rotation=unspecified "
+ + "--deqp-surface-type=window", instrumentationAnswerConfigA);
+
+ // query for config B
+ expectRenderConfigQueryAndReturn(mockDevice, "--deqp-gl-config-name=rgba8888d24s8 "
+ + "--deqp-screen-rotation=90 "
+ + "--deqp-surface-type=window "
+ + "--deqp-gl-major-version=3 "
+ + "--deqp-gl-minor-version=0", "Yes");
+
+ // run for config B
+ runInstrumentationLineAndAnswer(mockDevice,
+ "{dEQP-GLES3{instances{passall,crashtwo,skipone}}}",
+ "--deqp-caselist-file=" + CASE_LIST_FILE_NAME
+ + " --deqp-gl-config-name=rgba8888d24s8 "
+ + "--deqp-screen-rotation=90 "
+ + "--deqp-surface-type=window", instrumentationAnswerConfigB);
+
+ // query for config C
+ expectRenderConfigQueryAndReturn(mockDevice, "--deqp-gl-config-name=rgba8888d24s8 "
+ + "--deqp-screen-rotation=180 "
+ + "--deqp-surface-type=window "
+ + "--deqp-gl-major-version=3 "
+ + "--deqp-gl-minor-version=0", "Yes");
+
+ // run for config C
+ runInstrumentationLineAndAnswer(mockDevice,
+ "{dEQP-GLES3{instances{failone,crashtwo}}}",
+ "--deqp-caselist-file=" + CASE_LIST_FILE_NAME
+ + " --deqp-gl-config-name=rgba8888d24s8 "
+ + "--deqp-screen-rotation=180 "
+ + "--deqp-surface-type=window", instrumentationAnswerConfigC);
+
+ // query for unsupported config
+ expectRenderConfigQueryAndReturn(mockDevice, "--deqp-gl-config-name=rgb565d16s0 "
+ + "--deqp-screen-rotation=unspecified "
+ + "--deqp-surface-type=window "
+ + "--deqp-gl-major-version=3 "
+ + "--deqp-gl-minor-version=0", "No");
+
+ EasyMock.expect(mockDevice.uninstallPackage(EasyMock.eq(DEQP_ONDEVICE_PKG)))
+ .andReturn("").once();
+
+ mockListener.testRunStarted(ID, 4);
+ EasyMock.expectLastCall().once();
+
+ // pass all
+ mockListener.testStarted(EasyMock.eq(testIds[0]));
+ EasyMock.expectLastCall().once();
+
+ mockListener.testEnded(EasyMock.eq(testIds[0]), EasyMock.<Map<String, String>>notNull());
+ EasyMock.expectLastCall().once();
+
+ // fail one
+ mockListener.testStarted(EasyMock.eq(testIds[1]));
+ EasyMock.expectLastCall().once();
+
+ mockListener.testFailed(testIds[1],
+ "=== with config {glformat=rgba8888d24s8,rotation=180,surfacetype=window} ===\n"
+ + "Fail: Fail");
+ EasyMock.expectLastCall().once();
+
+ mockListener.testEnded(EasyMock.eq(testIds[1]), EasyMock.<Map<String, String>>notNull());
+ EasyMock.expectLastCall().once();
+
+ // crash two
+ mockListener.testStarted(EasyMock.eq(testIds[2]));
+ EasyMock.expectLastCall().once();
+
+ mockListener.testFailed(testIds[2],
+ "=== with config {glformat=rgba8888d24s8,rotation=unspecified,surfacetype=window} ===\n"
+ + "Crash: Incomplete test log\n"
+ + "=== with config {glformat=rgba8888d24s8,rotation=90,surfacetype=window} ===\n"
+ + "Terminated: Magic");
+ EasyMock.expectLastCall().once();
+
+ mockListener.testEnded(EasyMock.eq(testIds[2]), EasyMock.<Map<String, String>>notNull());
+ EasyMock.expectLastCall().once();
+
+ // skip one
+ mockListener.testStarted(EasyMock.eq(testIds[3]));
+ EasyMock.expectLastCall().once();
+
+ mockListener.testEnded(EasyMock.eq(testIds[3]), EasyMock.<Map<String, String>>notNull());
+ EasyMock.expectLastCall().once();
+
+ mockListener.testRunEnded(EasyMock.anyLong(), EasyMock.<Map<String, String>>notNull());
+ EasyMock.expectLastCall().once();
+
+ EasyMock.replay(mockDevice);
+ EasyMock.replay(mockListener);
+ deqpTest.run(mockListener);
+ EasyMock.verify(mockListener);
+ EasyMock.verify(mockDevice);
+ }
+
+ /**
+ * Test dEQP with runner if device is lost during one of multiple instances.
+ */
+ public void testRun_multipleInstancesLossOfDeviceMidInstance() throws Exception {
+ final String instrumentationAnswerFine =
+ "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=releaseName\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=2014.x\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=releaseId\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=0xcafebabe\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=targetName\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=android\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginSession\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginTestCase\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-BeginTestCase-TestCasePath=dEQP-GLES3.loss.instance\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Code=Pass\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-TestCaseResult-Details=Pass\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=TestCaseResult\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=EndTestCase\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=EndSession\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_CODE: 0\r\n";
+ final String instrumentationAnswerCrash =
+ "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=releaseName\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=2014.x\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=releaseId\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=0xcafebabe\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Name=targetName\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=SessionInfo\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-SessionInfo-Value=android\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginSession\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-EventType=BeginTestCase\r\n"
+ + "INSTRUMENTATION_STATUS: dEQP-BeginTestCase-TestCasePath=dEQP-GLES3.loss.instance\r\n"
+ + "INSTRUMENTATION_STATUS_CODE: 0\r\n"; // early <EOF>
+
+ final TestIdentifier testId = new TestIdentifier("dEQP-GLES3.loss", "instance");
+ final String testPath = "dEQP-GLES3.loss.instance";
+
+ Map<String,String> supportedConfigA = new HashMap<>();
+ supportedConfigA.put("glconfig", "rgba8888d24s8");
+ supportedConfigA.put("rotation", "unspecified");
+ supportedConfigA.put("surfacetype", "window");
+
+ Map<String,String> supportedConfigB = new HashMap<>();
+ supportedConfigB.put("glconfig", "rgba8888d24s8");
+ supportedConfigB.put("rotation", "90");
+ supportedConfigB.put("surfacetype", "window");
+
+ Map<String,String> supportedConfigC = new HashMap<>();
+ supportedConfigC.put("glconfig", "rgba8888d24s8");
+ supportedConfigC.put("rotation", "180");
+ supportedConfigC.put("surfacetype", "window");
+
+ Collection<TestIdentifier> tests = new ArrayList<TestIdentifier>();
+ tests.add(testId);
+
+ Map<TestIdentifier, List<Map<String, String>>> instance = new HashMap<>();
+ instance.put(testId, new ArrayList<Map<String,String>>());
+ instance.get(testId).add(supportedConfigA);
+ instance.get(testId).add(supportedConfigB);
+ instance.get(testId).add(supportedConfigC);
+
+ ITestDevice mockDevice = EasyMock.createMock(ITestDevice.class);
+ ITestInvocationListener mockListener
+ = EasyMock.createStrictMock(ITestInvocationListener.class);
+
+ DeqpTestRunner deqpTest = new DeqpTestRunner(NAME, NAME, tests, instance);
+ deqpTest.setAbi(UnitTests.ABI);
+ deqpTest.setDevice(mockDevice);
+ deqpTest.setBuildHelper(new StubCtsBuildHelper());
+
+ int version = 3 << 16;
+ EasyMock.expect(mockDevice.getProperty("ro.opengles.version"))
+ .andReturn(Integer.toString(version)).atLeastOnce();
+ EasyMock.expect(mockDevice.executeShellCommand("pm list features")).andReturn(ALL_FEATURES)
+ .anyTimes();
+
+ EasyMock.expect(mockDevice.uninstallPackage(EasyMock.eq(DEQP_ONDEVICE_PKG))).
+ andReturn("").once();
+
+ EasyMock.expect(mockDevice.installPackage(EasyMock.<File>anyObject(),
+ EasyMock.eq(true),
+ EasyMock.eq(AbiUtils.createAbiFlag(UnitTests.ABI.getName())))).andReturn(null)
+ .once();
+
+ // query config A
+ expectRenderConfigQueryAndReturn(mockDevice, "--deqp-gl-config-name=rgba8888d24s8 "
+ + "--deqp-screen-rotation=unspecified "
+ + "--deqp-surface-type=window "
+ + "--deqp-gl-major-version=3 "
+ + "--deqp-gl-minor-version=0", "Yes");
+
+ // run config A
+ runInstrumentationLineAndAnswer(mockDevice,
+ "{dEQP-GLES3{loss{instance}}}",
+ "--deqp-caselist-file=" + CASE_LIST_FILE_NAME
+ + " --deqp-gl-config-name=rgba8888d24s8 "
+ + "--deqp-screen-rotation=unspecified "
+ + "--deqp-surface-type=window", instrumentationAnswerFine);
+
+ // query config B
+ expectRenderConfigQueryAndReturn(mockDevice, "--deqp-gl-config-name=rgba8888d24s8 "
+ + "--deqp-screen-rotation=90 "
+ + "--deqp-surface-type=window "
+ + "--deqp-gl-major-version=3 "
+ + "--deqp-gl-minor-version=0", "Yes");
+
+ // run config B
+ EasyMock.expect(mockDevice.executeShellCommand(EasyMock.eq("rm " + CASE_LIST_FILE_NAME)))
+ .andReturn("").once();
+
+ EasyMock.expect(mockDevice.executeShellCommand(EasyMock.eq("rm " + LOG_FILE_NAME)))
+ .andReturn("").once();
+
+ EasyMock.expect(mockDevice.pushString("{dEQP-GLES3{loss{instance}}}\n", CASE_LIST_FILE_NAME))
+ .andReturn(true).once();
+
+ String command = String.format(
+ "am instrument %s -w -e deqpLogFileName \"%s\" -e deqpCmdLine \""
+ + "--deqp-caselist-file=%s"
+ + " --deqp-gl-config-name=rgba8888d24s8 "
+ + "--deqp-screen-rotation=90 "
+ + "--deqp-surface-type=window\" "
+ + "-e deqpLogData \"%s\" %s",
+ AbiUtils.createAbiFlag(UnitTests.ABI.getName()), LOG_FILE_NAME,
+ CASE_LIST_FILE_NAME, false, INSTRUMENTATION_NAME);
+
+ mockDevice.executeShellCommand(EasyMock.eq(command),
+ EasyMock.<IShellOutputReceiver>notNull());
+
+ EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
+ @Override
+ public Object answer() throws DeviceNotAvailableException {
+ IShellOutputReceiver receiver
+ = (IShellOutputReceiver)EasyMock.getCurrentArguments()[1];
+
+ receiver.addOutput(instrumentationAnswerCrash.getBytes(), 0,
+ instrumentationAnswerCrash.length());
+ throw new DeviceNotAvailableException();
+ }
+ });
+
+ mockListener.testRunStarted(ID, 1);
+ EasyMock.expectLastCall().once();
+
+ mockListener.testStarted(EasyMock.eq(testId));
+ EasyMock.expectLastCall().once();
+
+ mockListener.testFailed(testId,
+ "=== with config {glformat=rgba8888d24s8,rotation=90,surfacetype=window} ===\n"
+ + "Crash: Device lost");
+ EasyMock.expectLastCall().once();
+
+ mockListener.testEnded(EasyMock.eq(testId), EasyMock.<Map<String, String>>notNull());
+ EasyMock.expectLastCall().once();
+
+ EasyMock.replay(mockDevice);
+ EasyMock.replay(mockListener);
+
+ try {
+ deqpTest.run(mockListener);
+ fail("did not get DeviceNotAvailableException");
+ } catch (DeviceNotAvailableException ex) {
+ // expected
+ }
+
+ EasyMock.verify(mockListener);
+ EasyMock.verify(mockDevice);
+ }
+
+ private void runInstrumentationLineAndAnswer(ITestDevice mockDevice, final String testTrie,
+ final String cmd, final String output) throws Exception {
+ EasyMock.expect(mockDevice.executeShellCommand(EasyMock.eq("rm " + CASE_LIST_FILE_NAME)))
+ .andReturn("").once();
+
+ EasyMock.expect(mockDevice.executeShellCommand(EasyMock.eq("rm " + LOG_FILE_NAME)))
+ .andReturn("").once();
+
+ EasyMock.expect(mockDevice.pushString(testTrie + "\n", CASE_LIST_FILE_NAME))
+ .andReturn(true).once();
+
+ String command = String.format(
+ "am instrument %s -w -e deqpLogFileName \"%s\" -e deqpCmdLine \"%s\" "
+ + "-e deqpLogData \"%s\" %s",
+ AbiUtils.createAbiFlag(UnitTests.ABI.getName()), LOG_FILE_NAME,
+ cmd, false, INSTRUMENTATION_NAME);
+
+ mockDevice.executeShellCommand(EasyMock.eq(command),
+ EasyMock.<IShellOutputReceiver>notNull());
+
+ EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
+ @Override
+ public Object answer() {
+ IShellOutputReceiver receiver
+ = (IShellOutputReceiver)EasyMock.getCurrentArguments()[1];
+
+ receiver.addOutput(output.getBytes(), 0, output.length());
+ receiver.flush();
+
+ return null;
+ }
+ });
+ }
}
diff --git a/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/TestPackageXmlParserTest.java b/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/TestPackageXmlParserTest.java
index 6d87a61..bd48c51 100644
--- a/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/TestPackageXmlParserTest.java
+++ b/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/TestPackageXmlParserTest.java
@@ -25,6 +25,8 @@
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
/**
* Unit tests for {@link TestPackageXmlParser}.
@@ -65,6 +67,29 @@
private static final String NO_TEST_DATA = "<invalid />";
+ private static final String INSTANCED_TEST_DATA =
+ "<TestPackage>\n" +
+ " <TestSuite name=\"com\" >\n" +
+ " <TestSuite name=\"example\" >\n" +
+ " <TestCase name=\"ExampleTest\" >\n" +
+ " <Test name=\"testMultiInstanced\" >\n" +
+ " <TestInstance foo=\"bar\" />\n" +
+ " <TestInstance foo=\"baz\" foo2=\"baz2\"/>\n" +
+ " </Test>\n" +
+ " <Test name=\"testSingleInstanced\" >\n" +
+ " <TestInstance foo=\"bar\" />\n" +
+ " </Test>\n" +
+ " <Test name=\"testEmptyInstances\" >\n" +
+ " <TestInstance />\n" +
+ " <TestInstance />\n" +
+ " </Test>\n" +
+ " <Test name=\"testNotInstanced\" >\n" +
+ " </Test>\n" +
+ " </TestCase>\n" +
+ " </TestSuite>\n" +
+ " </TestSuite>\n" +
+ "</TestPackage>";
+
/**
* Test parsing test case xml containing an instrumentation test definition.
*/
@@ -162,6 +187,90 @@
assertTrue(parser.getTestPackageDefs().isEmpty());
}
+ /**
+ * Test parsing a test case xml with multiple test instances
+ */
+ public void testParse_instancedMultiple() throws ParseException {
+ TestPackageXmlParser parser = new TestPackageXmlParser(true);
+ parser.parse(getStringAsStream(INSTANCED_TEST_DATA));
+ for (TestPackageDef def : parser.getTestPackageDefs()) {
+ final TestIdentifier testId =
+ new TestIdentifier("com.example.ExampleTest", "testMultiInstanced");
+ final List<Map<String, String>> targetInstances =
+ def.getTestInstanceArguments().get(testId);
+ assertNotNull(targetInstances);
+ assertEquals(2, targetInstances.size());
+
+ final Iterator<Map<String, String>> iterator = targetInstances.iterator();
+ final Map<String, String> firstInstance = iterator.next();
+ final Map<String, String> secondInstance = iterator.next();
+
+ assertEquals("bar", firstInstance.get("foo"));
+ assertEquals("baz", secondInstance.get("foo"));
+ assertEquals("baz2", secondInstance.get("foo2"));
+ }
+ }
+
+ /**
+ * Test parsing a test case xml with single test instance
+ */
+ public void testParse_instancedSingle() throws ParseException {
+ TestPackageXmlParser parser = new TestPackageXmlParser(true);
+ parser.parse(getStringAsStream(INSTANCED_TEST_DATA));
+ for (TestPackageDef def : parser.getTestPackageDefs()) {
+ final TestIdentifier testId =
+ new TestIdentifier("com.example.ExampleTest", "testSingleInstanced");
+ final List<Map<String, String>> targetInstances =
+ def.getTestInstanceArguments().get(testId);
+ assertNotNull(targetInstances);
+ assertEquals(1, targetInstances.size());
+
+ final Iterator<Map<String, String>> iterator = targetInstances.iterator();
+ final Map<String, String> firstInstance = iterator.next();
+
+ assertEquals("bar", firstInstance.get("foo"));
+ }
+ }
+
+ /**
+ * Test parsing a test case xml with multiple test instances with no data
+ */
+ public void testParse_instancedEmptys() throws ParseException {
+ TestPackageXmlParser parser = new TestPackageXmlParser(true);
+ parser.parse(getStringAsStream(INSTANCED_TEST_DATA));
+ for (TestPackageDef def : parser.getTestPackageDefs()) {
+ final TestIdentifier testId =
+ new TestIdentifier("com.example.ExampleTest", "testEmptyInstances");
+ final List<Map<String, String>> targetInstances =
+ def.getTestInstanceArguments().get(testId);
+ assertNotNull(targetInstances);
+ assertEquals(2, targetInstances.size());
+
+ final Iterator<Map<String, String>> iterator = targetInstances.iterator();
+ final Map<String, String> firstInstance = iterator.next();
+ final Map<String, String> secondInstance = iterator.next();
+
+ assertTrue(firstInstance.isEmpty());
+ assertTrue(secondInstance.isEmpty());
+ }
+ }
+
+ /**
+ * Test parsing a test case xml with no test instances
+ */
+ public void testParse_instancedNoInstances() throws ParseException {
+ TestPackageXmlParser parser = new TestPackageXmlParser(true);
+ parser.parse(getStringAsStream(INSTANCED_TEST_DATA));
+ for (TestPackageDef def : parser.getTestPackageDefs()) {
+ final TestIdentifier testId =
+ new TestIdentifier("com.example.ExampleTest", "testNotInstanced");
+ final List<Map<String, String>> targetInstances =
+ def.getTestInstanceArguments().get(testId);
+ assertNotNull(targetInstances);
+ assertTrue(targetInstances.isEmpty());
+ }
+ }
+
private InputStream getStringAsStream(String input) {
return new ByteArrayInputStream(input.getBytes());
}
diff --git a/tools/vm-tests-tf/Android.mk b/tools/vm-tests-tf/Android.mk
index 88f2a53..f2a8914 100644
--- a/tools/vm-tests-tf/Android.mk
+++ b/tools/vm-tests-tf/Android.mk
@@ -14,6 +14,28 @@
LOCAL_PATH := $(call my-dir)
+# test dex library
+# ============================================================
+include $(CLEAR_VARS)
+
+# custom variables used to generate test description. do not touch!
+LOCAL_SRC_FILES := $(call all-java-files-under, src/dot)
+
+LOCAL_MODULE := cts-tf-dalvik-lib
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+LOCAL_MODULE_TAGS := optional
+LOCAL_JAVA_LIBRARIES := junit-targetdex
+
+include $(BUILD_JAVA_LIBRARY)
+
+cts-tf-dalvik-lib.jack := $(full_classes_jack)
+
+private_jill_jarjar_asm := $(addprefix $(HOST_OUT_JAVA_LIBRARIES)/,jill-jarjar-asm.jar)
+$(private_jill_jarjar_asm) : PRIVATE_JARJAR_RULES := $(LOCAL_PATH)/jill-jarjar-rules.txt
+$(private_jill_jarjar_asm) : $(addprefix $(HOST_OUT_JAVA_LIBRARIES)/,jill.jar) | $(JARJAR)
+ @echo JarJar: $@
+ $(hide) java -jar $(JARJAR) process $(PRIVATE_JARJAR_RULES) $< $@
+
# buildutil java library
# ============================================================
include $(CLEAR_VARS)
@@ -29,16 +51,31 @@
LOCAL_MODULE_TAGS := optional
LOCAL_JAVA_LIBRARIES := dx dasm cfassembler junit
-LOCAL_CLASSPATH := $(HOST_JDK_TOOLS_JAR)
+LOCAL_JAVA_LIBRARIES += jack
+
+LOCAL_CLASSPATH := $(HOST_JDK_TOOLS_JAR) $(private_jill_jarjar_asm)
include $(BUILD_HOST_JAVA_LIBRARY)
# Buid android.core.vm-tests-tf.jar
# ============================================================
#
+include $(CLEAR_VARS)
+
+LOCAL_JACK_ENABLED := $(strip $(LOCAL_JACK_ENABLED))
intermediates := $(call intermediates-dir-for,JAVA_LIBRARIES,vm-tests-tf,HOST)
vmteststf_jar := $(intermediates)/android.core.vm-tests-tf.jar
vmteststf_dep_jars := $(addprefix $(HOST_OUT_JAVA_LIBRARIES)/, cts-tf-dalvik-buildutil.jar dasm.jar dx.jar cfassembler.jar junit.jar)
+vmteststf_dep_jars += $(addprefix $(HOST_OUT_JAVA_LIBRARIES)/, jack.jar)
+vmteststf_dep_jars += $(private_jill_jarjar_asm)
+
+$(vmteststf_jar): PRIVATE_JACK_VM_ARGS := $(LOCAL_JACK_VM_ARGS)
+$(vmteststf_jar): PRIVATE_JACK_EXTRA_ARGS := $(LOCAL_JACK_EXTRA_ARGS)
+
+ifdef LOCAL_JACK_ENABLED
+ vmteststf_dep_jars += $(cts-tf-dalvik-lib.jack)
+endif
+
$(vmteststf_jar): PRIVATE_SRC_FOLDER := $(LOCAL_PATH)/src
$(vmteststf_jar): PRIVATE_LIB_FOLDER := $(LOCAL_PATH)/lib
$(vmteststf_jar): PRIVATE_INTERMEDIATES_CLASSES := $(call intermediates-dir-for,JAVA_LIBRARIES,cts-tf-dalvik-buildutil,HOST)/classes
@@ -47,7 +84,8 @@
$(vmteststf_jar): PRIVATE_INTERMEDIATES_MAIN_FILES := $(intermediates)/main_files
$(vmteststf_jar): PRIVATE_INTERMEDIATES_HOSTJUNIT_FILES := $(intermediates)/hostjunit_files
$(vmteststf_jar): PRIVATE_CLASS_PATH := $(subst $(space),:,$(vmteststf_dep_jars)):$(HOST_JDK_TOOLS_JAR)
-$(vmteststf_jar) : $(vmteststf_dep_jars) $(HOST_OUT_JAVA_LIBRARIES)/tradefed-prebuilt.jar
+ifndef LOCAL_JACK_ENABLED
+$(vmteststf_jar) : $(vmteststf_dep_jars) $(JACK_JAR) $(JILL_JAR) $(HOST_OUT_JAVA_LIBRARIES)/tradefed-prebuilt.jar
$(hide) rm -rf $(dir $@) && mkdir -p $(dir $@)
$(hide) mkdir -p $(PRIVATE_INTERMEDIATES_HOSTJUNIT_FILES)/dot/junit $(dir $(PRIVATE_INTERMEDIATES_DEXCORE_JAR))
# generated and compile the host side junit tests
@@ -62,6 +100,26 @@
$(if $(NO_OPTIMIZE_DX), --no-optimize) $(PRIVATE_INTERMEDIATES_DEXCORE_JAR).jar && rm -f $(PRIVATE_INTERMEDIATES_DEXCORE_JAR).jar
$(hide) cd $(PRIVATE_INTERMEDIATES_HOSTJUNIT_FILES)/classes && zip -q -r ../../android.core.vm-tests-tf.jar .
$(hide) cd $(dir $@) && zip -q -r android.core.vm-tests-tf.jar tests
+else # LOCAL_JACK_ENABLED
+$(vmteststf_jar) : $(vmteststf_dep_jars) $(JACK_JAR) $(JILL_JAR) out/target/common/obj/JAVA_LIBRARIES/core-libart_intermediates/classes.jack $(HOST_OUT_JAVA_LIBRARIES)/tradefed-prebuilt.jar $(LOCAL_PATH)/lib/junit.jar
+ $(hide) rm -rf $(dir $@) && mkdir -p $(dir $@)
+ $(hide) mkdir -p $(PRIVATE_INTERMEDIATES_HOSTJUNIT_FILES)/dot/junit $(dir $(PRIVATE_INTERMEDIATES_DEXCORE_JAR))
+ # generated and compile the host side junit tests
+ @echo "Write generated Main_*.java files to $(PRIVATE_INTERMEDIATES_MAIN_FILES)"
+ $(hide) java -cp $(PRIVATE_CLASS_PATH) util.build.JackBuildDalvikSuite $(PRIVATE_SRC_FOLDER) $(PRIVATE_INTERMEDIATES) \
+ out/target/common/obj/JAVA_LIBRARIES/core-libart_intermediates/classes.jack:$(cts-tf-dalvik-lib.jack):$(HOST_OUT_JAVA_LIBRARIES)/tradefed-prebuilt.jar:$(LOCAL_PATH)/lib/junit.jar \
+ $(PRIVATE_INTERMEDIATES_MAIN_FILES) $(PRIVATE_INTERMEDIATES_CLASSES) $(PRIVATE_INTERMEDIATES_HOSTJUNIT_FILES) $$RUN_VM_TESTS_RTO
+ @echo "Generate $(PRIVATE_INTERMEDIATES_DEXCORE_JAR)"
+ $(hide) jar -cf $(PRIVATE_INTERMEDIATES_DEXCORE_JAR)-class.jar \
+ $(addprefix -C $(PRIVATE_INTERMEDIATES_CLASSES) , dot/junit/DxUtil.class dot/junit/DxAbstractMain.class)
+ $(hide) $(JILL) --output $(PRIVATE_INTERMEDIATES_DEXCORE_JAR).jack $(PRIVATE_INTERMEDIATES_DEXCORE_JAR)-class.jar
+ $(hide) mkdir -p $(PRIVATE_INTERMEDIATES_DEXCORE_JAR).tmp
+ $(hide) $(call call-jack,$(PRIVATE_JACK_VM_ARGS),$(PRIVATE_JACK_EXTRA_ARGS)) --output-dex $(PRIVATE_INTERMEDIATES_DEXCORE_JAR).tmp \
+ $(if $(NO_OPTIMIZE_DX), -D jack.dex.optimize "false") --import $(PRIVATE_INTERMEDIATES_DEXCORE_JAR).jack && rm -f $(PRIVATE_INTERMEDIATES_DEXCORE_JAR).jack
+ $(hide) cd $(PRIVATE_INTERMEDIATES_DEXCORE_JAR).tmp && zip -q -r $(abspath $(PRIVATE_INTERMEDIATES_DEXCORE_JAR)) .
+ $(hide) cd $(PRIVATE_INTERMEDIATES_HOSTJUNIT_FILES)/classes && zip -q -r ../../android.core.vm-tests-tf.jar .
+ $(hide) cd $(dir $@) && zip -q -r android.core.vm-tests-tf.jar tests
+endif # LOCAL_JACK_ENABLED
# Clean up temp vars
intermediates :=
diff --git a/tools/vm-tests-tf/jill-jarjar-rules.txt b/tools/vm-tests-tf/jill-jarjar-rules.txt
new file mode 100644
index 0000000..ee6f403
--- /dev/null
+++ b/tools/vm-tests-tf/jill-jarjar-rules.txt
@@ -0,0 +1 @@
+rule org.objectweb.** com.android.jill.@0
\ No newline at end of file
diff --git a/tools/vm-tests-tf/src/util/build/BuildDalvikSuite.java b/tools/vm-tests-tf/src/util/build/BuildDalvikSuite.java
index c772c33..4ce8c38 100644
--- a/tools/vm-tests-tf/src/util/build/BuildDalvikSuite.java
+++ b/tools/vm-tests-tf/src/util/build/BuildDalvikSuite.java
@@ -78,6 +78,7 @@
private int testClassCnt = 0;
private int testMethodsCnt = 0;
+ private boolean useJack;
/*
* using a linked hashmap to keep the insertion order for iterators.
@@ -101,39 +102,47 @@
*/
public static void main(String[] args) throws IOException {
- if (args.length > 5) {
- JAVASRC_FOLDER = args[0];
- OUTPUT_FOLDER = args[1];
- CLASS_PATH = args[2];
- MAIN_SRC_OUTPUT_FOLDER = args[3];
- CLASSES_OUTPUT_FOLDER = MAIN_SRC_OUTPUT_FOLDER + "/classes";
-
- COMPILED_CLASSES_FOLDER = args[4];
-
- HOSTJUNIT_SRC_OUTPUT_FOLDER = args[5];
- HOSTJUNIT_CLASSES_OUTPUT_FOLDER = HOSTJUNIT_SRC_OUTPUT_FOLDER + "/classes";
-
- if (args.length > 6) {
- // optional: restrict to e.g. "opcodes.add_double"
- restrictTo = args[6];
- System.out.println("restricting build to: " + restrictTo);
- }
-
- } else {
- System.out.println("usage: java-src-folder output-folder classpath " +
- "generated-main-files compiled_output generated-main-files " +
- "[restrict-to-opcode]");
- System.exit(-1);
- }
+ parseArgs(args);
long start = System.currentTimeMillis();
- BuildDalvikSuite cat = new BuildDalvikSuite();
+ BuildDalvikSuite cat = new BuildDalvikSuite(false);
cat.compose();
long end = System.currentTimeMillis();
System.out.println("elapsed seconds: " + (end - start) / 1000);
}
+ public static void parseArgs(String[] args) {
+ if (args.length > 5) {
+ JAVASRC_FOLDER = args[0];
+ OUTPUT_FOLDER = args[1];
+ CLASS_PATH = args[2];
+ MAIN_SRC_OUTPUT_FOLDER = args[3];
+ CLASSES_OUTPUT_FOLDER = MAIN_SRC_OUTPUT_FOLDER + "/classes";
+
+ COMPILED_CLASSES_FOLDER = args[4];
+
+ HOSTJUNIT_SRC_OUTPUT_FOLDER = args[5];
+ HOSTJUNIT_CLASSES_OUTPUT_FOLDER = HOSTJUNIT_SRC_OUTPUT_FOLDER + "/classes";
+
+ if (args.length > 6) {
+ // optional: restrict to e.g. "opcodes.add_double"
+ restrictTo = args[6];
+ System.out.println("restricting build to: " + restrictTo);
+ }
+
+ } else {
+ System.out.println("usage: java-src-folder output-folder classpath " +
+ "generated-main-files compiled_output generated-main-files " +
+ "[restrict-to-opcode]");
+ System.exit(-1);
+ }
+ }
+
+ public BuildDalvikSuite(boolean useJack) {
+ this.useJack = useJack;
+ }
+
public void compose() throws IOException {
System.out.println("Collecting all junit tests...");
new TestRunner() {
@@ -182,19 +191,21 @@
li.add(method);
}
private String curJunitFileName = null;
+ private String curJunitName = null;
private String curJunitFileData = "";
- private JavacBuildStep javacHostJunitBuildStep;
+ private SourceBuildStep hostJunitBuildStep;
private void flushHostJunitFile() {
if (curJunitFileName != null) {
File toWrite = new File(curJunitFileName);
String absPath = toWrite.getAbsolutePath();
// add to java source files for later compilation
- javacHostJunitBuildStep.addSourceFile(absPath);
+ hostJunitBuildStep.addSourceFile(absPath);
// write file
curJunitFileData += "\n}\n";
writeToFileMkdir(toWrite, curJunitFileData);
+
curJunitFileName = null;
curJunitFileData = "";
}
@@ -267,11 +278,11 @@
String datafileContent = "";
Set<BuildStep> targets = new TreeSet<BuildStep>();
- javacHostJunitBuildStep = new JavacBuildStep(HOSTJUNIT_CLASSES_OUTPUT_FOLDER, CLASS_PATH);
+ SourceBuildStep srcBuildStep;
+ hostJunitBuildStep = new JavacBuildStep(
+ HOSTJUNIT_CLASSES_OUTPUT_FOLDER, CLASS_PATH);
-
- JavacBuildStep javacBuildStep = new JavacBuildStep(
- CLASSES_OUTPUT_FOLDER, CLASS_PATH);
+ srcBuildStep = new JavacBuildStep(CLASSES_OUTPUT_FOLDER, CLASS_PATH);
for (Entry<String, List<String>> entry : map.entrySet()) {
@@ -334,19 +345,25 @@
" public static void main(String[] args) throws Exception {" +
methodContent + "\n}\n";
- String fileName = getFileName(pName, method, ".java");
File sourceFile = getFileFromPackage(pName, method);
- File classFile = new File(CLASSES_OUTPUT_FOLDER + "/" +
- getFileName(pName, method, ".class"));
- // if (sourceFile.lastModified() > classFile.lastModified()) {
writeToFile(sourceFile, content);
- javacBuildStep.addSourceFile(sourceFile.getAbsolutePath());
+ if (useJack) {
+ File jackFile = new File(CLASSES_OUTPUT_FOLDER + "/" +
+ getFileName(pName, method, ".jack"));
+ JackBuildStep step = new JackBuildStep(jackFile.getAbsolutePath(), CLASS_PATH);
+ step.addSourceFile(sourceFile.getAbsolutePath());
+ if (!step.build()) {
+ System.out.println("main src dalvik-cts-buildutil build step failed");
+ System.exit(1);
+ }
+ } else {
+ srcBuildStep.addSourceFile(sourceFile.getAbsolutePath());
+ }
BuildStep dexBuildStep = generateDexBuildStep(
- CLASSES_OUTPUT_FOLDER, getFileName(pName, method, ""));
+ CLASSES_OUTPUT_FOLDER, getFileName(pName, method, ""), null);
targets.add(dexBuildStep);
- // }
// prepare the entry in the data file for the bash script.
@@ -442,22 +459,23 @@
scriptDataDir.mkdirs();
writeToFile(new File(scriptDataDir, "scriptdata"), datafileContent);
- if (!javacHostJunitBuildStep.build()) {
+ if (!hostJunitBuildStep.build()) {
System.out.println("main javac cts-host-hostjunit-classes build step failed");
System.exit(1);
}
- if (javacBuildStep.build()) {
- for (BuildStep buildStep : targets) {
- if (!buildStep.build()) {
- System.out.println("building failed. buildStep: " +
- buildStep.getClass().getName() + ", " + buildStep);
- System.exit(1);
- }
+ if (!useJack) {
+ if (!srcBuildStep.build()) {
+ System.out.println("main src dalvik-cts-buildutil build step failed");
+ System.exit(1);
}
- } else {
- System.out.println("main javac dalvik-cts-buildutil build step failed");
- System.exit(1);
+ }
+ for (BuildStep buildStep : targets) {
+ if (!buildStep.build()) {
+ System.out.println("building failed. buildStep: " +
+ buildStep.getClass().getName() + ", " + buildStep);
+ System.exit(1);
+ }
}
}
@@ -514,19 +532,37 @@
return;
}
- if (new File(sourceFolder, fileName + ".java").exists()) {
-
+ File srcFile = new File(sourceFolder, fileName + ".java");
+ if (srcFile.exists()) {
+ JackBuildStep jackBuildStep = null;
+ if (useJack) {
+ jackBuildStep = new JackBuildStep(
+ COMPILED_CLASSES_FOLDER + File.separator + fileName + ".jack",
+ CLASS_PATH);
+ jackBuildStep.addSourceFile(srcFile.getAbsolutePath());
+ }
BuildStep dexBuildStep = generateDexBuildStep(
- COMPILED_CLASSES_FOLDER, fileName);
+ COMPILED_CLASSES_FOLDER, fileName, jackBuildStep);
targets.add(dexBuildStep);
return;
}
try {
if (Class.forName(dependentTestClassName) != null) {
+ JillBuildStep jillBuildStep = null;
+ if (useJack) {
+ BuildStep.BuildFile classFile = new BuildStep.BuildFile(
+ COMPILED_CLASSES_FOLDER, fileName + ".class");
+ BuildStep.BuildFile jackFile = new BuildStep.BuildFile(
+ COMPILED_CLASSES_FOLDER,
+ fileName + ".jack");
+
+ jillBuildStep = new JillBuildStep(classFile,
+ jackFile);
+ }
BuildStep dexBuildStep = generateDexBuildStep(
- COMPILED_CLASSES_FOLDER, fileName);
+ COMPILED_CLASSES_FOLDER, fileName, jillBuildStep);
targets.add(dexBuildStep);
return;
}
@@ -539,24 +575,50 @@
}
private BuildStep generateDexBuildStep(String classFileFolder,
- String classFileName) {
- BuildStep.BuildFile classFile = new BuildStep.BuildFile(
- classFileFolder, classFileName + ".class");
+ String classFileName, BuildStep dependency) {
+ if (!useJack) {
+ BuildStep.BuildFile classFile = new BuildStep.BuildFile(
+ classFileFolder, classFileName + ".class");
- BuildStep.BuildFile tmpJarFile = new BuildStep.BuildFile(OUTPUT_FOLDER,
- classFileName + "_tmp.jar");
+ BuildStep.BuildFile tmpJarFile = new BuildStep.BuildFile(
+ OUTPUT_FOLDER,
+ classFileName + "_tmp.jar");
- JarBuildStep jarBuildStep = new JarBuildStep(classFile, classFileName +
- ".class", tmpJarFile, false);
+ JarBuildStep jarBuildStep = new JarBuildStep(classFile,
+ classFileName + ".class", tmpJarFile, false);
- BuildStep.BuildFile outputFile = new BuildStep.BuildFile(OUTPUT_FOLDER,
- classFileName + ".jar");
+ if (dependency != null) {
+ jarBuildStep.addChild(dependency);
+ }
- DexBuildStep dexBuildStep = new DexBuildStep(tmpJarFile, outputFile,
- true);
+ BuildStep.BuildFile outputFile = new BuildStep.BuildFile(
+ OUTPUT_FOLDER,
+ classFileName + ".jar");
- dexBuildStep.addChild(jarBuildStep);
- return dexBuildStep;
+ DxBuildStep dexBuildStep = new DxBuildStep(tmpJarFile,
+ outputFile,
+ true);
+
+ dexBuildStep.addChild(jarBuildStep);
+ return dexBuildStep;
+ } else {
+ BuildStep.BuildFile jackFile = new BuildStep.BuildFile(
+ classFileFolder, classFileName + ".jack");
+
+ BuildStep.BuildFile outputFile = new BuildStep.BuildFile(
+ OUTPUT_FOLDER,
+ classFileName + ".jar");
+
+ JackDexBuildStep dexBuildStep = new JackDexBuildStep(jackFile,
+ outputFile,
+ true);
+
+ if (dependency != null) {
+ dexBuildStep.addChild(dependency);
+ }
+ return dexBuildStep;
+
+ }
}
@@ -747,7 +809,7 @@
private void writeToFile(File file, String content) {
try {
- if (file.length() == content.length()) {
+ if (file.exists() && file.length() == content.length()) {
FileReader reader = new FileReader(file);
char[] charContents = new char[(int) file.length()];
reader.read(charContents);
diff --git a/tools/vm-tests-tf/src/util/build/DexBuildStep.java b/tools/vm-tests-tf/src/util/build/DxBuildStep.java
similarity index 93%
rename from tools/vm-tests-tf/src/util/build/DexBuildStep.java
rename to tools/vm-tests-tf/src/util/build/DxBuildStep.java
index 6aba51c..6e347b2 100644
--- a/tools/vm-tests-tf/src/util/build/DexBuildStep.java
+++ b/tools/vm-tests-tf/src/util/build/DxBuildStep.java
@@ -19,11 +19,11 @@
import com.android.dx.command.dexer.Main;
import java.io.IOException;
-public class DexBuildStep extends BuildStep {
+public class DxBuildStep extends BuildStep {
private final boolean deleteInputFileAfterBuild;
- DexBuildStep(BuildFile inputFile, BuildFile outputFile,
+ DxBuildStep(BuildFile inputFile, BuildFile outputFile,
boolean deleteInputFileAfterBuild) {
super(inputFile, outputFile);
this.deleteInputFileAfterBuild = deleteInputFileAfterBuild;
@@ -71,7 +71,7 @@
@Override
public boolean equals(Object obj) {
if (super.equals(obj)) {
- DexBuildStep other = (DexBuildStep) obj;
+ DxBuildStep other = (DxBuildStep) obj;
return inputFile.equals(other.inputFile)
&& outputFile.equals(other.outputFile);
diff --git a/tools/vm-tests-tf/src/util/build/JackBuildDalvikSuite.java b/tools/vm-tests-tf/src/util/build/JackBuildDalvikSuite.java
new file mode 100644
index 0000000..a508e5b
--- /dev/null
+++ b/tools/vm-tests-tf/src/util/build/JackBuildDalvikSuite.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package util.build;
+
+import java.io.IOException;
+
+public class JackBuildDalvikSuite {
+
+ public static void main(String[] args) throws IOException {
+
+ BuildDalvikSuite.parseArgs(args);
+
+ long start = System.currentTimeMillis();
+ BuildDalvikSuite cat = new BuildDalvikSuite(true);
+ cat.compose();
+ long end = System.currentTimeMillis();
+
+ System.out.println("elapsed seconds: " + (end - start) / 1000);
+ }
+}
diff --git a/tools/vm-tests-tf/src/util/build/JackBuildStep.java b/tools/vm-tests-tf/src/util/build/JackBuildStep.java
new file mode 100644
index 0000000..9e93475
--- /dev/null
+++ b/tools/vm-tests-tf/src/util/build/JackBuildStep.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package util.build;
+
+import com.android.jack.Jack;
+import com.android.jack.Main;
+import com.android.jack.Options;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class JackBuildStep extends SourceBuildStep {
+
+ private final String destPath;
+ private final String classPath;
+ private final Set<String> sourceFiles = new HashSet<String>();
+
+ public JackBuildStep(String destPath, String classPath) {
+ this.destPath = destPath;
+ this.classPath = classPath;
+ }
+
+ @Override
+ public void addSourceFile(String sourceFile) {
+ sourceFiles.add(sourceFile);
+ }
+
+ @Override
+ boolean build() {
+ if (super.build()) {
+ if (sourceFiles.isEmpty()) {
+ return true;
+ }
+
+ File outDir = new File(destPath).getParentFile();
+ if (!outDir.exists() && !outDir.mkdirs()) {
+ System.err.println("failed to create output dir: "
+ + outDir.getAbsolutePath());
+ return false;
+ }
+ List<String> commandLine = new ArrayList(4 + sourceFiles.size());
+ commandLine.add("--classpath");
+ commandLine.add(classPath);
+ commandLine.add("--output-jack");
+ commandLine.add(destPath);
+ commandLine.addAll(sourceFiles);
+
+ try {
+ Options options = Main.parseCommandLine(commandLine);
+ Jack.run(options);
+ } catch (Throwable ex) {
+ ex.printStackTrace();
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (super.equals(obj)) {
+ JackBuildStep other = (JackBuildStep) obj;
+ return destPath.equals(other.destPath) && classPath.equals(other.classPath)
+ && sourceFiles.equals(other.sourceFiles);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return destPath.hashCode() ^ classPath.hashCode() ^ sourceFiles.hashCode();
+ }
+}
diff --git a/tools/vm-tests-tf/src/util/build/JackDexBuildStep.java b/tools/vm-tests-tf/src/util/build/JackDexBuildStep.java
new file mode 100644
index 0000000..8d9771c
--- /dev/null
+++ b/tools/vm-tests-tf/src/util/build/JackDexBuildStep.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2008 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 util.build;
+
+import com.android.jack.Jack;
+import com.android.jack.Main;
+import com.android.jack.Options;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+public class JackDexBuildStep extends BuildStep {
+
+ private final boolean deleteInputFileAfterBuild;
+
+ JackDexBuildStep(BuildFile inputFile, BuildFile outputFile,
+ boolean deleteInputFileAfterBuild) {
+ super(inputFile, outputFile);
+ this.deleteInputFileAfterBuild = deleteInputFileAfterBuild;
+ }
+
+ @Override
+ boolean build() {
+
+ if (super.build()) {
+ String outputFilePath = outputFile.fileName.getAbsolutePath();
+ if (outputFilePath.endsWith(".dex")) {
+ throw new AssertionError(
+ "DexBuildStep does not support dex output outside of an archive");
+ }
+
+ File outDir = outputFile.fileName.getParentFile();
+ if (!outDir.exists() && !outDir.mkdirs()) {
+ System.err.println("failed to create output dir: "
+ + outDir.getAbsolutePath());
+ return false;
+ }
+
+ List<String> commandLine = new ArrayList<String>(4);
+ commandLine.add("--output-dex-zip");
+ commandLine.add(outputFilePath);
+ commandLine.add("--import");
+ commandLine.add(inputFile.fileName.getAbsolutePath());
+
+ try {
+ Options options = Main.parseCommandLine(commandLine);
+ Jack.run(options);
+ if (deleteInputFileAfterBuild) {
+ inputFile.fileName.delete();
+ }
+ return true;
+ } catch (Throwable ex) {
+ System.err.println("exception while dexing "
+ + inputFile.fileName.getAbsolutePath() + " to "
+ + outputFile.fileName.getAbsolutePath());
+ ex.printStackTrace();
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return inputFile.hashCode() ^ outputFile.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (super.equals(obj)) {
+ JackDexBuildStep other = (JackDexBuildStep) obj;
+
+ return inputFile.equals(other.inputFile)
+ && outputFile.equals(other.outputFile);
+ }
+ return false;
+ }
+
+
+}
diff --git a/tools/vm-tests-tf/src/util/build/JavacBuildStep.java b/tools/vm-tests-tf/src/util/build/JavacBuildStep.java
index 7d7033f..d08a2c6 100644
--- a/tools/vm-tests-tf/src/util/build/JavacBuildStep.java
+++ b/tools/vm-tests-tf/src/util/build/JavacBuildStep.java
@@ -23,7 +23,7 @@
import java.util.HashSet;
import java.util.Set;
-public class JavacBuildStep extends BuildStep {
+public class JavacBuildStep extends SourceBuildStep {
private final String destPath;
private final String classPath;
@@ -32,12 +32,13 @@
this.destPath = destPath;
this.classPath = classPath;
}
-
+
+ @Override
public void addSourceFile(String sourceFile)
{
sourceFiles.add(sourceFile);
}
-
+
@Override
boolean build() {
if (super.build())
@@ -46,7 +47,7 @@
{
return true;
}
-
+
File destFile = new File(destPath);
if (!destFile.exists() && !destFile.mkdirs())
{
@@ -59,13 +60,12 @@
commandLine[1] = classPath;
commandLine[2] = "-d";
commandLine[3] = destPath;
-
+
String[] files = new String[sourceFiles.size()];
sourceFiles.toArray(files);
-
+
System.arraycopy(files, 0, commandLine, args, files.length);
-
-
+
return Main.compile(commandLine, new PrintWriter(System.err)) == 0;
}
return false;
@@ -73,17 +73,16 @@
@Override
public boolean equals(Object obj) {
- // TODO Auto-generated method stub
if (super.equals(obj))
{
JavacBuildStep other = (JavacBuildStep) obj;
- return destPath.equals(other.destPath)
+ return destPath.equals(other.destPath)
&& classPath.equals(other.classPath)
&& sourceFiles.equals(other.sourceFiles);
}
return false;
}
-
+
@Override
public int hashCode() {
return destPath.hashCode() ^ classPath.hashCode() ^ sourceFiles.hashCode();
diff --git a/tools/vm-tests-tf/src/util/build/JillBuildStep.java b/tools/vm-tests-tf/src/util/build/JillBuildStep.java
new file mode 100644
index 0000000..aff3bb0
--- /dev/null
+++ b/tools/vm-tests-tf/src/util/build/JillBuildStep.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package util.build;
+
+import com.android.jill.Main;
+import com.android.jill.Options;
+
+import java.io.File;
+
+public class JillBuildStep extends BuildStep {
+
+ JillBuildStep(BuildFile inputFile, BuildFile outputFile) {
+ super(inputFile, outputFile);
+ }
+
+ @Override
+ boolean build() {
+ if (super.build()) {
+
+ File outDir = outputFile.fileName.getParentFile();
+ if (!outDir.exists() && !outDir.mkdirs()) {
+ System.err.println("failed to create output dir: "
+ + outDir.getAbsolutePath());
+ return false;
+ }
+
+ int args = 3;
+ String[] commandLine = new String[args];
+ commandLine[0] = "--output";
+ commandLine[1] = outputFile.fileName.getAbsolutePath();
+ commandLine[2] = inputFile.fileName.getAbsolutePath();
+
+ try {
+ Options options = Main.getOptions(commandLine);
+ Main.run(options);
+ } catch (Throwable ex) {
+ ex.printStackTrace();
+ return false;
+ }
+
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (super.equals(obj)) {
+ JillBuildStep other = (JillBuildStep) obj;
+
+ return inputFile.equals(other.inputFile) && outputFile.equals(other.outputFile);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return inputFile.hashCode() ^ outputFile.hashCode();
+ }
+}
diff --git a/tests/print/src/android/print/cts/IPrivilegedOperations.aidl b/tools/vm-tests-tf/src/util/build/SourceBuildStep.java
similarity index 74%
rename from tests/print/src/android/print/cts/IPrivilegedOperations.aidl
rename to tools/vm-tests-tf/src/util/build/SourceBuildStep.java
index 93c8c3e..4a68a05 100644
--- a/tests/print/src/android/print/cts/IPrivilegedOperations.aidl
+++ b/tools/vm-tests-tf/src/util/build/SourceBuildStep.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,8 +14,10 @@
* limitations under the License.
*/
-package android.print.cts;
+package util.build;
-interface IPrivilegedOperations {
- boolean clearApplicationUserData(String packageName);
+public abstract class SourceBuildStep extends BuildStep {
+
+ public abstract void addSourceFile(String sourceFile);
+
}