diff options
18 files changed, 827 insertions, 293 deletions
diff --git a/audio/core/all-versions/default/Android.bp b/audio/core/all-versions/default/Android.bp index 8fb7111fbf..6a0d0a08cd 100644 --- a/audio/core/all-versions/default/Android.bp +++ b/audio/core/all-versions/default/Android.bp @@ -48,6 +48,8 @@ cc_defaults { "libhidlbase", "liblog", "libmedia_helper", + "libmediautils_vendor", + "libmemunreachable", "libutils", "android.hardware.audio.common-util", ], diff --git a/audio/core/all-versions/default/Device.cpp b/audio/core/all-versions/default/Device.cpp index 130dfba95b..c33e6f30fa 100644 --- a/audio/core/all-versions/default/Device.cpp +++ b/audio/core/all-versions/default/Device.cpp @@ -30,6 +30,8 @@ #include <algorithm> #include <android/log.h> +#include <mediautils/MemoryLeakTrackUtil.h> +#include <memunreachable/memunreachable.h> #include <HidlUtils.h> @@ -456,9 +458,32 @@ Return<void> Device::debugDump(const hidl_handle& fd) { } #endif -Return<void> Device::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& /* options */) { +Return<void> Device::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) { if (fd.getNativeHandle() != nullptr && fd->numFds == 1) { - analyzeStatus("dump", mDevice->dump(mDevice, fd->data[0])); + const int fd0 = fd->data[0]; + bool dumpMem = false; + bool unreachableMemory = false; + for (const auto& option : options) { + if (option == "-m") { + dumpMem = true; + } else if (option == "--unreachable") { + unreachableMemory = true; + } + } + + if (dumpMem) { + dprintf(fd0, "\nDumping memory:\n"); + std::string s = dumpMemoryAddresses(100 /* limit */); + write(fd0, s.c_str(), s.size()); + } + if (unreachableMemory) { + dprintf(fd0, "\nDumping unreachable memory:\n"); + // TODO - should limit be an argument parameter? + std::string s = GetUnreachableMemoryString(true /* contents */, 100 /* limit */); + write(fd0, s.c_str(), s.size()); + } + + analyzeStatus("dump", mDevice->dump(mDevice, fd0)); } return Void(); } diff --git a/automotive/can/1.0/default/Android.bp b/automotive/can/1.0/default/Android.bp index c0c17e27f5..163fdb7265 100644 --- a/automotive/can/1.0/default/Android.bp +++ b/automotive/can/1.0/default/Android.bp @@ -64,4 +64,5 @@ cc_binary { "android.hardware.automotive@libc++fs", "libnl++", ], + vintf_fragments: ["manifest_android.hardware.automotive.can@1.0.xml"], } diff --git a/automotive/can/1.0/default/manifest_android.hardware.automotive.can@1.0.xml b/automotive/can/1.0/default/manifest_android.hardware.automotive.can@1.0.xml new file mode 100644 index 0000000000..2078ce54df --- /dev/null +++ b/automotive/can/1.0/default/manifest_android.hardware.automotive.can@1.0.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright (C) 2020 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. +--> +<manifest version="1.0" type="device" > + <hal format="hidl"> + <name>android.hardware.automotive.can</name> + <transport>hwbinder</transport> + <fqname>@1.0::ICanController/socketcan</fqname> + </hal> +</manifest> diff --git a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp index 8cc18822f2..1216d36eda 100644 --- a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp +++ b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp @@ -79,19 +79,24 @@ using IEvsCamera_1_1 = ::android::hardware::automotive::evs::V1_1::IEvsCamera; using IEvsDisplay_1_0 = ::android::hardware::automotive::evs::V1_0::IEvsDisplay; using IEvsDisplay_1_1 = ::android::hardware::automotive::evs::V1_1::IEvsDisplay; +namespace { + /* * Plese note that this is different from what is defined in * libhardware/modules/camera/3_4/metadata/types.h; this has one additional * field to store a framerate. */ -const size_t kStreamCfgSz = 5; typedef struct { + int32_t id; int32_t width; int32_t height; int32_t format; int32_t direction; int32_t framerate; } RawStreamConfig; +constexpr const size_t kStreamCfgSz = sizeof(RawStreamConfig) / sizeof(int32_t); + +} // anonymous namespace // The main test class for EVS @@ -236,6 +241,28 @@ protected: return physicalCameras; } + Stream getFirstStreamConfiguration(camera_metadata_t* metadata) { + Stream targetCfg = {}; + camera_metadata_entry_t streamCfgs; + if (!find_camera_metadata_entry(metadata, + ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, + &streamCfgs)) { + // Stream configurations are found in metadata + RawStreamConfig *ptr = reinterpret_cast<RawStreamConfig *>(streamCfgs.data.i32); + for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) { + if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT && + ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) { + targetCfg.width = ptr->width; + targetCfg.height = ptr->height; + targetCfg.format = static_cast<PixelFormat>(ptr->format); + break; + } + ++ptr; + } + } + + return targetCfg; + } sp<IEvsEnumerator> pEnumerator; // Every test needs access to the service std::vector<CameraDesc> cameraInfo; // Empty unless/until loadCameraList() is called @@ -265,10 +292,6 @@ TEST_P(EvsHidlTest, CameraOpenClean) { // Get the camera list loadCameraList(); - // Using null stream configuration makes EVS uses the default resolution and - // output format. - Stream nullCfg = {}; - // Open and close each camera twice for (auto&& cam: cameraInfo) { bool isLogicalCam = false; @@ -278,8 +301,14 @@ TEST_P(EvsHidlTest, CameraOpenClean) { continue; } + // Read a target resolution from the metadata + Stream targetCfg = + getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data())); + ASSERT_GT(targetCfg.width, 0); + ASSERT_GT(targetCfg.height, 0); + for (int pass = 0; pass < 2; pass++) { - sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg); + sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg); ASSERT_NE(pCam, nullptr); for (auto&& devName : devices) { @@ -343,10 +372,6 @@ TEST_P(EvsHidlTest, CameraOpenAggressive) { // Get the camera list loadCameraList(); - // Using null stream configuration makes EVS uses the default resolution and - // output format. - Stream nullCfg = {}; - // Open and close each camera twice for (auto&& cam: cameraInfo) { bool isLogicalCam = false; @@ -356,10 +381,14 @@ TEST_P(EvsHidlTest, CameraOpenAggressive) { continue; } + // Read a target resolution from the metadata + Stream targetCfg = + getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data())); + ASSERT_GT(targetCfg.width, 0); + ASSERT_GT(targetCfg.height, 0); + activeCameras.clear(); - sp<IEvsCamera_1_1> pCam = - IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg)) - .withDefault(nullptr); + sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg); ASSERT_NE(pCam, nullptr); // Store a camera handle for a clean-up @@ -372,9 +401,7 @@ TEST_P(EvsHidlTest, CameraOpenAggressive) { } ); - sp<IEvsCamera_1_1> pCam2 = - IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg)) - .withDefault(nullptr); + sp<IEvsCamera_1_1> pCam2 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg); ASSERT_NE(pCam2, nullptr); // Store a camera handle for a clean-up @@ -422,10 +449,6 @@ TEST_P(EvsHidlTest, CameraStreamPerformance) { // Get the camera list loadCameraList(); - // Using null stream configuration makes EVS uses the default resolution and - // output format. - Stream nullCfg = {}; - // Test each reported camera for (auto&& cam: cameraInfo) { bool isLogicalCam = false; @@ -435,9 +458,13 @@ TEST_P(EvsHidlTest, CameraStreamPerformance) { continue; } - sp<IEvsCamera_1_1> pCam = - IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg)) - .withDefault(nullptr); + // Read a target resolution from the metadata + Stream targetCfg = + getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data())); + ASSERT_GT(targetCfg.width, 0); + ASSERT_GT(targetCfg.height, 0); + + sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg); ASSERT_NE(pCam, nullptr); // Store a camera handle for a clean-up @@ -519,10 +546,6 @@ TEST_P(EvsHidlTest, CameraStreamBuffering) { // Get the camera list loadCameraList(); - // Using null stream configuration makes EVS uses the default resolution and - // output format. - Stream nullCfg = {}; - // Test each reported camera for (auto&& cam: cameraInfo) { bool isLogicalCam = false; @@ -532,9 +555,13 @@ TEST_P(EvsHidlTest, CameraStreamBuffering) { continue; } - sp<IEvsCamera_1_1> pCam = - IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg)) - .withDefault(nullptr); + // Read a target resolution from the metadata + Stream targetCfg = + getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data())); + ASSERT_GT(targetCfg.width, 0); + ASSERT_GT(targetCfg.height, 0); + + sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg); ASSERT_NE(pCam, nullptr); // Store a camera handle for a clean-up @@ -601,10 +628,6 @@ TEST_P(EvsHidlTest, CameraToDisplayRoundTrip) { // Get the camera list loadCameraList(); - // Using null stream configuration makes EVS uses the default resolution and - // output format. - Stream nullCfg = {}; - // Request available display IDs uint8_t targetDisplayId = 0; pEnumerator->getDisplayIdList([&targetDisplayId](auto ids) { @@ -642,9 +665,13 @@ TEST_P(EvsHidlTest, CameraToDisplayRoundTrip) { continue; } - sp<IEvsCamera_1_1> pCam = - IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg)) - .withDefault(nullptr); + // Read a target resolution from the metadata + Stream targetCfg = + getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data())); + ASSERT_GT(targetCfg.width, 0); + ASSERT_GT(targetCfg.height, 0); + + sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg); ASSERT_NE(pCam, nullptr); // Store a camera handle for a clean-up @@ -708,24 +735,22 @@ TEST_P(EvsHidlTest, MultiCameraStream) { // Get the camera list loadCameraList(); - // Using null stream configuration makes EVS uses the default resolution and - // output format. - Stream nullCfg = {}; - // Test each reported camera for (auto&& cam: cameraInfo) { + // Read a target resolution from the metadata + Stream targetCfg = + getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data())); + ASSERT_GT(targetCfg.width, 0); + ASSERT_GT(targetCfg.height, 0); + // Create two camera clients. - sp<IEvsCamera_1_1> pCam0 = - IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg)) - .withDefault(nullptr); + sp<IEvsCamera_1_1> pCam0 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg); ASSERT_NE(pCam0, nullptr); // Store a camera handle for a clean-up activeCameras.push_back(pCam0); - sp<IEvsCamera_1_1> pCam1 = - IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg)) - .withDefault(nullptr); + sp<IEvsCamera_1_1> pCam1 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg); ASSERT_NE(pCam1, nullptr); // Store a camera handle for a clean-up @@ -812,10 +837,6 @@ TEST_P(EvsHidlTest, CameraParameter) { // Get the camera list loadCameraList(); - // Using null stream configuration makes EVS uses the default resolution and - // output format. - Stream nullCfg = {}; - // Test each reported camera Return<EvsResult> result = EvsResult::OK; for (auto&& cam: cameraInfo) { @@ -828,10 +849,14 @@ TEST_P(EvsHidlTest, CameraParameter) { continue; } + // Read a target resolution from the metadata + Stream targetCfg = + getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data())); + ASSERT_GT(targetCfg.width, 0); + ASSERT_GT(targetCfg.height, 0); + // Create a camera client - sp<IEvsCamera_1_1> pCam = - IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg)) - .withDefault(nullptr); + sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg); ASSERT_NE(pCam, nullptr); // Store a camera @@ -961,10 +986,6 @@ TEST_P(EvsHidlTest, CameraPrimaryClientRelease) { // Get the camera list loadCameraList(); - // Using null stream configuration makes EVS uses the default resolution and - // output format. - Stream nullCfg = {}; - // Test each reported camera for (auto&& cam: cameraInfo) { bool isLogicalCam = false; @@ -976,18 +997,20 @@ TEST_P(EvsHidlTest, CameraPrimaryClientRelease) { continue; } + // Read a target resolution from the metadata + Stream targetCfg = + getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data())); + ASSERT_GT(targetCfg.width, 0); + ASSERT_GT(targetCfg.height, 0); + // Create two camera clients. - sp<IEvsCamera_1_1> pCamPrimary = - IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg)) - .withDefault(nullptr); + sp<IEvsCamera_1_1> pCamPrimary = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg); ASSERT_NE(pCamPrimary, nullptr); // Store a camera handle for a clean-up activeCameras.push_back(pCamPrimary); - sp<IEvsCamera_1_1> pCamSecondary = - IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg)) - .withDefault(nullptr); + sp<IEvsCamera_1_1> pCamSecondary = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg); ASSERT_NE(pCamSecondary, nullptr); // Store a camera handle for a clean-up @@ -1142,10 +1165,6 @@ TEST_P(EvsHidlTest, MultiCameraParameter) { // Get the camera list loadCameraList(); - // Using null stream configuration makes EVS uses the default resolution and - // output format. - Stream nullCfg = {}; - // Test each reported camera for (auto&& cam: cameraInfo) { bool isLogicalCam = false; @@ -1157,18 +1176,20 @@ TEST_P(EvsHidlTest, MultiCameraParameter) { continue; } + // Read a target resolution from the metadata + Stream targetCfg = + getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data())); + ASSERT_GT(targetCfg.width, 0); + ASSERT_GT(targetCfg.height, 0); + // Create two camera clients. - sp<IEvsCamera_1_1> pCamPrimary = - IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg)) - .withDefault(nullptr); + sp<IEvsCamera_1_1> pCamPrimary = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg); ASSERT_NE(pCamPrimary, nullptr); // Store a camera handle for a clean-up activeCameras.push_back(pCamPrimary); - sp<IEvsCamera_1_1> pCamSecondary = - IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg)) - .withDefault(nullptr); + sp<IEvsCamera_1_1> pCamSecondary = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg); ASSERT_NE(pCamSecondary, nullptr); // Store a camera handle for a clean-up @@ -1615,28 +1636,26 @@ TEST_P(EvsHidlTest, HighPriorityCameraClient) { // Get the camera list loadCameraList(); - // Using null stream configuration makes EVS uses the default resolution and - // output format. - Stream nullCfg = {}; - // Request exclusive access to the EVS display sp<IEvsDisplay_1_0> pDisplay = pEnumerator->openDisplay(); ASSERT_NE(pDisplay, nullptr); // Test each reported camera for (auto&& cam: cameraInfo) { + // Read a target resolution from the metadata + Stream targetCfg = + getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data())); + ASSERT_GT(targetCfg.width, 0); + ASSERT_GT(targetCfg.height, 0); + // Create two clients - sp<IEvsCamera_1_1> pCam0 = - IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg)) - .withDefault(nullptr); + sp<IEvsCamera_1_1> pCam0 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg); ASSERT_NE(pCam0, nullptr); // Store a camera handle for a clean-up activeCameras.push_back(pCam0); - sp<IEvsCamera_1_1> pCam1 = - IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg)) - .withDefault(nullptr); + sp<IEvsCamera_1_1> pCam1 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg); ASSERT_NE(pCam1, nullptr); // Store a camera handle for a clean-up @@ -2001,7 +2020,7 @@ TEST_P(EvsHidlTest, CameraUseStreamConfigToDisplay) { &streamCfgs)) { // Stream configurations are found in metadata RawStreamConfig *ptr = reinterpret_cast<RawStreamConfig *>(streamCfgs.data.i32); - for (unsigned idx = 0; idx < streamCfgs.count; idx += kStreamCfgSz) { + for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) { if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT && ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) { @@ -2026,9 +2045,7 @@ TEST_P(EvsHidlTest, CameraUseStreamConfigToDisplay) { continue; } - sp<IEvsCamera_1_1> pCam = - IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg)) - .withDefault(nullptr); + sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg); ASSERT_NE(pCam, nullptr); // Store a camera handle for a clean-up @@ -2106,7 +2123,7 @@ TEST_P(EvsHidlTest, MultiCameraStreamUseConfig) { &streamCfgs)) { // Stream configurations are found in metadata RawStreamConfig *ptr = reinterpret_cast<RawStreamConfig *>(streamCfgs.data.i32); - for (unsigned idx = 0; idx < streamCfgs.count; idx += kStreamCfgSz) { + for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) { if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT && ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) { @@ -2132,9 +2149,7 @@ TEST_P(EvsHidlTest, MultiCameraStreamUseConfig) { } // Create the first camera client with a selected stream configuration. - sp<IEvsCamera_1_1> pCam0 = - IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg)) - .withDefault(nullptr); + sp<IEvsCamera_1_1> pCam0 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg); ASSERT_NE(pCam0, nullptr); // Store a camera handle for a clean-up @@ -2144,9 +2159,7 @@ TEST_P(EvsHidlTest, MultiCameraStreamUseConfig) { // configuration. int32_t id = targetCfg.id; targetCfg.id += 1; // EVS manager sees only the stream id. - sp<IEvsCamera_1_1> pCam1 = - IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg)) - .withDefault(nullptr); + sp<IEvsCamera_1_1> pCam1 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg); ASSERT_EQ(pCam1, nullptr); // Store a camera handle for a clean-up @@ -2154,9 +2167,7 @@ TEST_P(EvsHidlTest, MultiCameraStreamUseConfig) { // Try again with same stream configuration. targetCfg.id = id; - pCam1 = - IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg)) - .withDefault(nullptr); + pCam1 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg); ASSERT_NE(pCam1, nullptr); // Set up per-client frame receiver objects which will fire up its own thread @@ -2258,52 +2269,23 @@ TEST_P(EvsHidlTest, CameraStreamExternalBuffering) { LOG(INFO) << "Starting CameraStreamExternalBuffering test"; // Arbitrary constant (should be > 1 and not too big) - static const unsigned int kBuffersToHold = 6; + static const unsigned int kBuffersToHold = 3; // Get the camera list loadCameraList(); - // Using null stream configuration makes EVS uses the default resolution and - // output format. - Stream nullCfg = {}; - // Acquire the graphics buffer allocator android::GraphicBufferAllocator& alloc(android::GraphicBufferAllocator::get()); const auto usage = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_OFTEN; - const auto format = HAL_PIXEL_FORMAT_RGBA_8888; - uint32_t width = 640; - uint32_t height = 360; - camera_metadata_entry_t streamCfgs; // Test each reported camera for (auto&& cam : cameraInfo) { - bool foundCfg = false; - if (!find_camera_metadata_entry(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()), - ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, - &streamCfgs)) { - // Stream configurations are found in metadata - RawStreamConfig* ptr = reinterpret_cast<RawStreamConfig*>(streamCfgs.data.i32); - - LOG(DEBUG) << __LINE__ << " start searching " << streamCfgs.count; - for (unsigned idx = 0; idx < streamCfgs.count; idx++) { - LOG(DEBUG) << "ptr->direction= " << ptr->direction - << " ptr->format= " << ptr->format; - if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT && - ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) { - width = ptr->width; - height = ptr->height; - foundCfg = true; - // Always use the 1st available configuration - break; - } - ++ptr; - } - } - - if (!foundCfg) { - LOG(INFO) << "No configuration found. Use default stream configurations."; - } + // Read a target resolution from the metadata + Stream targetCfg = + getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data())); + ASSERT_GT(targetCfg.width, 0); + ASSERT_GT(targetCfg.height, 0); // Allocate buffers to use hidl_vec<BufferDesc> buffers; @@ -2312,8 +2294,11 @@ TEST_P(EvsHidlTest, CameraStreamExternalBuffering) { unsigned pixelsPerLine; buffer_handle_t memHandle = nullptr; android::status_t result = - alloc.allocate(width, height, format, 1, usage, &memHandle, &pixelsPerLine, 0, - "CameraStreamExternalBufferingTest"); + alloc.allocate(targetCfg.width, targetCfg.height, + (android::PixelFormat)targetCfg.format, + /* layerCount = */ 1, usage, &memHandle, &pixelsPerLine, + /* graphicBufferId = */ 0, + /* requestorName = */ "CameraStreamExternalBufferingTest"); if (result != android::NO_ERROR) { LOG(ERROR) << __FUNCTION__ << " failed to allocate memory."; // Release previous allocated buffers @@ -2325,10 +2310,10 @@ TEST_P(EvsHidlTest, CameraStreamExternalBuffering) { BufferDesc buf; AHardwareBuffer_Desc* pDesc = reinterpret_cast<AHardwareBuffer_Desc*>(&buf.buffer.description); - pDesc->width = width; - pDesc->height = height; + pDesc->width = targetCfg.width; + pDesc->height = targetCfg.height; pDesc->layers = 1; - pDesc->format = format; + pDesc->format = static_cast<uint32_t>(targetCfg.format); pDesc->usage = usage; pDesc->stride = pixelsPerLine; buf.buffer.nativeHandle = memHandle; @@ -2340,9 +2325,7 @@ TEST_P(EvsHidlTest, CameraStreamExternalBuffering) { bool isLogicalCam = false; getPhysicalCameraIds(cam.v1.cameraId, isLogicalCam); - sp<IEvsCamera_1_1> pCam = - IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg)) - .withDefault(nullptr); + sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg); ASSERT_NE(pCam, nullptr); // Store a camera handle for a clean-up @@ -2362,7 +2345,7 @@ TEST_P(EvsHidlTest, CameraStreamExternalBuffering) { } EXPECT_EQ(result, EvsResult::OK); - EXPECT_GE(delta, 0); + EXPECT_GE(delta, kBuffersToHold); // Set up a frame receiver object which will fire up its own thread. sp<FrameHandler> frameHandler = new FrameHandler(pCam, cam, @@ -2378,7 +2361,7 @@ TEST_P(EvsHidlTest, CameraStreamExternalBuffering) { sleep(1); // 1 second should be enough for at least 5 frames to be delivered worst case unsigned framesReceived = 0; frameHandler->getFramesCounters(&framesReceived, nullptr); - ASSERT_EQ(kBuffersToHold, framesReceived) << "Stream didn't stall at expected buffer limit"; + ASSERT_LE(kBuffersToHold, framesReceived) << "Stream didn't stall at expected buffer limit"; // Give back one buffer @@ -2387,9 +2370,10 @@ TEST_P(EvsHidlTest, CameraStreamExternalBuffering) { // Once we return a buffer, it shouldn't take more than 1/10 second to get a new one // filled since we require 10fps minimum -- but give a 10% allowance just in case. + unsigned framesReceivedAfter = 0; usleep(110 * kMillisecondsToMicroseconds); - frameHandler->getFramesCounters(&framesReceived, nullptr); - EXPECT_EQ(kBuffersToHold+1, framesReceived) << "Stream should've resumed"; + frameHandler->getFramesCounters(&framesReceivedAfter, nullptr); + EXPECT_EQ(framesReceived + 1, framesReceivedAfter) << "Stream should've resumed"; // Even when the camera pointer goes out of scope, the FrameHandler object will // keep the stream alive unless we tell it to shutdown. diff --git a/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp b/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp index 583a455160..58423c8187 100644 --- a/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp +++ b/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include <fuzzer/FuzzedDataProvider.h> #include <cmath> #include <cstdlib> #include <cstring> @@ -21,36 +22,43 @@ #include "FormatConvert.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, std::size_t size) { - if (size < 256) { + // 1 random value (4bytes) + min imagesize = 16*2 times bytes per pixel (worse case 2) + if (size < (4 + 16 * 2 * 2)) { return 0; } + FuzzedDataProvider fdp(data, size); + std::size_t image_pixel_size = size - 4; + image_pixel_size = (image_pixel_size & INT_MAX) / 2; - std::srand(std::time(nullptr)); // use current time as seed for random generator - int random_variable = std::rand() % 10; - int width = (int)sqrt(size); - int height = width * ((float)random_variable / 10.0); + // API have a requirement that width must be divied by 16 except yuyvtorgb + int min_height = 2; + int max_height = (image_pixel_size / 16) & ~(1); // must be even number + int height = fdp.ConsumeIntegralInRange<uint32_t>(min_height, max_height); + int width = (image_pixel_size / height) & ~(16); // must be divisible by 16 - uint8_t* src = (uint8_t*)malloc(sizeof(uint8_t) * size); - memcpy(src, data, sizeof(uint8_t) * (size)); - uint32_t* tgt = (uint32_t*)malloc(sizeof(uint32_t) * size); + uint8_t* src = (uint8_t*)(data + 4); + uint32_t* tgt = (uint32_t*)malloc(sizeof(uint32_t) * image_pixel_size); #ifdef COPY_NV21_TO_RGB32 - android::hardware::automotive::evs::common::Utils::copyNV21toRGB32(width, height, src, tgt, 0); + android::hardware::automotive::evs::common::Utils::copyNV21toRGB32(width, height, src, tgt, + width); #elif COPY_NV21_TO_BGR32 - android::hardware::automotive::evs::common::Utils::copyNV21toBGR32(width, height, src, tgt, 0); + android::hardware::automotive::evs::common::Utils::copyNV21toBGR32(width, height, src, tgt, + width); #elif COPY_YV12_TO_RGB32 - android::hardware::automotive::evs::common::Utils::copyYV12toRGB32(width, height, src, tgt, 0); + android::hardware::automotive::evs::common::Utils::copyYV12toRGB32(width, height, src, tgt, + width); #elif COPY_YV12_TO_BGR32 - android::hardware::automotive::evs::common::Utils::copyYV12toBGR32(width, height, src, tgt, 0); + android::hardware::automotive::evs::common::Utils::copyYV12toBGR32(width, height, src, tgt, + width); #elif COPY_YUYV_TO_RGB32 - android::hardware::automotive::evs::common::Utils::copyYUYVtoRGB32(width, height, src, 0, tgt, - 0); + android::hardware::automotive::evs::common::Utils::copyYUYVtoRGB32(width, height, src, width, + tgt, width); #elif COPY_YUYV_TO_BGR32 - android::hardware::automotive::evs::common::Utils::copyYUYVtoBGR32(width, height, src, 0, tgt, - 0); + android::hardware::automotive::evs::common::Utils::copyYUYVtoBGR32(width, height, src, width, + tgt, width); #endif - free(src); free(tgt); return 0; diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp index 869c0c9124..ba11a49204 100644 --- a/automotive/vehicle/2.0/default/Android.bp +++ b/automotive/vehicle/2.0/default/Android.bp @@ -182,6 +182,7 @@ cc_test { ], shared_libs: [ "libbase", + "libcutils", ], header_libs: ["libbase_headers"], test_suites: ["general-tests"], diff --git a/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc b/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc index c8c89dc821..44f9134714 100644 --- a/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc +++ b/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc @@ -1,4 +1,4 @@ service vendor.vehicle-hal-2.0 /vendor/bin/hw/android.hardware.automotive.vehicle@2.0-service - class hal + class early_hal user vehicle_network group system inet diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h index fcfe7612ac..6706258717 100644 --- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h +++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h @@ -76,6 +76,9 @@ public: Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override; private: + // Set unit test class as friend class to test private functions. + friend class VehicleHalManagerTestHelper; + using VehiclePropValuePtr = VehicleHal::VehiclePropValuePtr; // Returns true if needs to call again shortly. using RetriableAction = std::function<bool()>; @@ -105,14 +108,20 @@ public: void cmdDumpOneProperty(int fd, int32_t prop, int32_t areaId); void cmdDumpOneProperty(int fd, int rowNumber, const VehiclePropConfig& config); + bool cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options); + static bool checkArgumentsSize(int fd, const hidl_vec<hidl_string>& options, size_t minSize); static bool checkCallerHasWritePermissions(int fd); - static bool safelyParseInt(int fd, int index, std::string s, int* out); + template <typename T> + static bool safelyParseInt(int fd, int index, const std::string& s, T* out); + static bool safelyParseFloat(int fd, int index, const std::string& s, float* out); + // Parses "s" as a hex string and populate "*bytes". The hex string must be in the format of + // valid hex format, e.g. "0xABCD". + static bool parseHexString(int fd, const std::string& s, std::vector<uint8_t>* bytes); void cmdHelp(int fd) const; void cmdListAllProperties(int fd) const; void cmdDumpAllProperties(int fd); void cmdDumpSpecificProperties(int fd, const hidl_vec<hidl_string>& options); - void cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options); static bool isSubscribable(const VehiclePropConfig& config, SubscribeFlags flags); @@ -120,7 +129,18 @@ public: static float checkSampleRate(const VehiclePropConfig& config, float sampleRate); static ClientId getClientId(const sp<IVehicleCallback>& callback); -private: + + // Parses the cmdline options for "--set" command. "*prop" would be populated with the + // the properties to be set. Returns true when the cmdline options are valid, false otherwise. + static bool parseSetPropOptions(int fd, const hidl_vec<hidl_string>& options, + VehiclePropValue* prop); + // Parses the options and get the values for the current option specified by "*index". "*index" + // would advance to the next option field (e.g., the next "-f"). Returns a list of values for + // the current option. + static std::vector<std::string> getOptionValues(const hidl_vec<hidl_string>& options, + size_t* index); + + private: VehicleHal* mHal; std::unique_ptr<VehiclePropConfigIndex> mConfigIndex; SubscriptionManager mSubscriptionManager; diff --git a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp index dc5d3d300e..e34e692bfc 100644 --- a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp +++ b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp @@ -20,7 +20,9 @@ #include <cmath> #include <fstream> +#include <unordered_set> +#include <android-base/parsedouble.h> #include <android-base/parseint.h> #include <android-base/strings.h> #include <android/hardware/automotive/vehicle/2.0/BpHwVehicleCallback.h> @@ -44,15 +46,34 @@ using ::android::base::EqualsIgnoreCase; using ::android::hardware::hidl_handle; using ::android::hardware::hidl_string; +namespace { + constexpr std::chrono::milliseconds kHalEventBatchingTimeWindow(10); const VehiclePropValue kEmptyValue{}; +// A list of supported options for "--set" command. +const std::unordered_set<std::string> kSetPropOptions = { + // integer. + "-i", + // 64bit integer. + "-i64", + // float. + "-f", + // string. + "-s", + // bytes in hex format, e.g. 0xDEADBEEF. + "-b", + // Area id in integer. + "-a"}; + +} // namespace + /** * Indicates what's the maximum size of hidl_vec<VehiclePropValue> we want * to store in reusable object pool. */ -constexpr auto kMaxHidlVecOfVehiclPropValuePoolSize = 20; +constexpr auto kMaxHidlVecOfVehiclePropValuePoolSize = 20; Return<void> VehicleHalManager::getAllPropConfigs(getAllPropConfigs_cb _hidl_cb) { ALOGI("getAllPropConfigs called"); @@ -213,6 +234,11 @@ void VehicleHalManager::cmdDump(int fd, const hidl_vec<hidl_string>& options) { } else if (EqualsIgnoreCase(option, "--get")) { cmdDumpSpecificProperties(fd, options); } else if (EqualsIgnoreCase(option, "--set")) { + if (!checkCallerHasWritePermissions(fd)) { + dprintf(fd, "Caller does not have write permission\n"); + return; + } + // Ignore the return value for this. cmdSetOneProperty(fd, options); } else { dprintf(fd, "Invalid option: %s\n", option.c_str()); @@ -239,7 +265,8 @@ bool VehicleHalManager::checkArgumentsSize(int fd, const hidl_vec<hidl_string>& return false; } -bool VehicleHalManager::safelyParseInt(int fd, int index, std::string s, int* out) { +template <typename T> +bool VehicleHalManager::safelyParseInt(int fd, int index, const std::string& s, T* out) { if (!android::base::ParseInt(s, out)) { dprintf(fd, "non-integer argument at index %d: %s\n", index, s.c_str()); return false; @@ -247,19 +274,27 @@ bool VehicleHalManager::safelyParseInt(int fd, int index, std::string s, int* ou return true; } +bool VehicleHalManager::safelyParseFloat(int fd, int index, const std::string& s, float* out) { + if (!android::base::ParseFloat(s, out)) { + dprintf(fd, "non-float argument at index %d: %s\n", index, s.c_str()); + return false; + } + return true; +} + void VehicleHalManager::cmdHelp(int fd) const { dprintf(fd, "Usage: \n\n"); dprintf(fd, "[no args]: dumps (id and value) all supported properties \n"); dprintf(fd, "--help: shows this help\n"); dprintf(fd, "--list: lists the ids of all supported properties\n"); dprintf(fd, "--get <PROP1> [PROP2] [PROPN]: dumps the value of specific properties \n"); - // TODO: support other formats (int64, float, bytes) dprintf(fd, - "--set <PROP> <i|s> <VALUE_1> [<i|s> <VALUE_N>] [a AREA_ID] : sets the value of " - "property PROP, using arbitrary number of key/value parameters (i for int32, " - "s for string) and an optional area.\n" - "Notice that the string value can be set just once, while the other can have multiple " - "values (so they're used in the respective array)\n"); + "--set <PROP> [-i INT_VALUE [INT_VALUE ...]] [-i64 INT64_VALUE [INT64_VALUE ...]] " + "[-f FLOAT_VALUE [FLOAT_VALUE ...]] [-s STR_VALUE] " + "[-b BYTES_VALUE] [-a AREA_ID] : sets the value of property PROP. " + "Notice that the string, bytes and area value can be set just once, while the other can" + " have multiple values (so they're used in the respective array), " + "BYTES_VALUE is in the form of 0xXXXX, e.g. 0xdeadbeef.\n"); } void VehicleHalManager::cmdListAllProperties(int fd) const { @@ -337,102 +372,49 @@ void VehicleHalManager::cmdDumpOneProperty(int fd, int32_t prop, int32_t areaId) VehiclePropValue input; input.prop = prop; input.areaId = areaId; - auto callback = [&](StatusCode status, const VehiclePropValue& output) { + auto callback = [&fd, &prop](StatusCode status, const VehiclePropValue& output) { if (status == StatusCode::OK) { dprintf(fd, "%s\n", toString(output).c_str()); } else { dprintf(fd, "Could not get property %d. Error: %s\n", prop, toString(status).c_str()); } }; - get(input, callback); -} - -void VehicleHalManager::cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options) { - if (!checkCallerHasWritePermissions(fd) || !checkArgumentsSize(fd, options, 3)) return; - size_t size = options.size(); + StatusCode status; + auto value = mHal->get(input, &status); + callback(status, value.get() ? *value : kEmptyValue); +} - // Syntax is --set PROP Type1 Value1 TypeN ValueN, so number of arguments must be even - if (size % 2 != 0) { - dprintf(fd, "must pass even number of arguments (passed %zu)\n", size); - return; +bool VehicleHalManager::cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options) { + if (!checkArgumentsSize(fd, options, 4)) { + dprintf(fd, "Requires at least 4 options, see help\n"); + return false; } - int numberValues = (size - 2) / 2; - - VehiclePropValue prop; - if (!safelyParseInt(fd, 1, options[1], &prop.prop)) return; - prop.timestamp = elapsedRealtimeNano(); - prop.status = VehiclePropertyStatus::AVAILABLE; - - // First pass: calculate sizes - int sizeInt32 = 0; - int stringIndex = 0; - int areaIndex = 0; - for (int i = 2, kv = 1; kv <= numberValues; kv++) { - // iterate through the kv=1..n key/value pairs, accessing indexes i / i+1 at each step - std::string type = options[i]; - std::string value = options[i + 1]; - if (EqualsIgnoreCase(type, "i")) { - sizeInt32++; - } else if (EqualsIgnoreCase(type, "s")) { - if (stringIndex != 0) { - dprintf(fd, - "defining string value (%s) again at index %d (already defined at %d=%s" - ")\n", - value.c_str(), i, stringIndex, options[stringIndex + 1].c_str()); - return; - } - stringIndex = i; - } else if (EqualsIgnoreCase(type, "a")) { - if (areaIndex != 0) { - dprintf(fd, - "defining area value (%s) again at index %d (already defined at %d=%s" - ")\n", - value.c_str(), i, areaIndex, options[areaIndex + 1].c_str()); - return; - } - areaIndex = i; - } else { - dprintf(fd, "invalid (%s) type at index %d\n", type.c_str(), i); - return; - } - i += 2; - } - prop.value.int32Values.resize(sizeInt32); - - // Second pass: populate it - int indexInt32 = 0; - for (int i = 2, kv = 1; kv <= numberValues; kv++) { - // iterate through the kv=1..n key/value pairs, accessing indexes i / i+1 at each step - int valueIndex = i + 1; - std::string type = options[i]; - std::string value = options[valueIndex]; - if (EqualsIgnoreCase(type, "i")) { - int safeInt; - if (!safelyParseInt(fd, valueIndex, value, &safeInt)) return; - prop.value.int32Values[indexInt32++] = safeInt; - } else if (EqualsIgnoreCase(type, "s")) { - prop.value.stringValue = value; - } else if (EqualsIgnoreCase(type, "a")) { - if (!safelyParseInt(fd, valueIndex, value, &prop.areaId)) return; - } - i += 2; + + VehiclePropValue prop = {}; + if (!parseSetPropOptions(fd, options, &prop)) { + return false; } ALOGD("Setting prop %s", toString(prop).c_str()); - auto status = set(prop); + + // Do not use VehicleHalManager::set here because we don't want to check write permission. + // Caller should be able to use the debug interface to set read-only properties. + handlePropertySetEvent(prop); + auto status = mHal->set(prop); + if (status == StatusCode::OK) { dprintf(fd, "Set property %s\n", toString(prop).c_str()); - } else { - dprintf(fd, "Failed to set property %s: %s\n", toString(prop).c_str(), - toString(status).c_str()); + return true; } + dprintf(fd, "Failed to set property %s: %s\n", toString(prop).c_str(), + toString(status).c_str()); + return false; } void VehicleHalManager::init() { ALOGI("VehicleHalManager::init"); - mHidlVecOfVehiclePropValuePool.resize(kMaxHidlVecOfVehiclPropValuePoolSize); - + mHidlVecOfVehiclePropValuePool.resize(kMaxHidlVecOfVehiclePropValuePoolSize); mBatchingConsumer.run(&mEventQueue, kHalEventBatchingTimeWindow, @@ -486,7 +468,7 @@ void VehicleHalManager::onBatchHalEvent(const std::vector<VehiclePropValuePtr>& for (const HalClientValues& cv : clientValues) { auto vecSize = cv.values.size(); hidl_vec<VehiclePropValue> vec; - if (vecSize < kMaxHidlVecOfVehiclPropValuePoolSize) { + if (vecSize < kMaxHidlVecOfVehiclePropValuePoolSize) { vec.setToExternal(&mHidlVecOfVehiclePropValuePool[0], vecSize); } else { vec.resize(vecSize); @@ -595,6 +577,158 @@ ClientId VehicleHalManager::getClientId(const sp<IVehicleCallback>& callback) { } } +std::vector<std::string> VehicleHalManager::getOptionValues(const hidl_vec<hidl_string>& options, + size_t* index) { + std::vector<std::string> values; + while (*index < options.size()) { + std::string option = options[*index]; + if (kSetPropOptions.find(option) != kSetPropOptions.end()) { + return std::move(values); + } + values.push_back(option); + (*index)++; + } + return std::move(values); +} + +bool VehicleHalManager::parseSetPropOptions(int fd, const hidl_vec<hidl_string>& options, + VehiclePropValue* prop) { + // Options format: + // --set PROP [-f f1 f2...] [-i i1 i2...] [-i64 i1 i2...] [-s s1 s2...] [-b b1 b2...] [-a a] + size_t optionIndex = 1; + int propValue; + if (!safelyParseInt(fd, optionIndex, options[optionIndex], &propValue)) { + dprintf(fd, "property value: \"%s\" is not a valid int\n", options[optionIndex].c_str()); + return false; + } + prop->prop = propValue; + prop->timestamp = elapsedRealtimeNano(); + prop->status = VehiclePropertyStatus::AVAILABLE; + optionIndex++; + std::unordered_set<std::string> parsedOptions; + + while (optionIndex < options.size()) { + std::string type = options[optionIndex]; + optionIndex++; + size_t currentIndex = optionIndex; + std::vector<std::string> values = getOptionValues(options, &optionIndex); + if (parsedOptions.find(type) != parsedOptions.end()) { + dprintf(fd, "duplicate \"%s\" options\n", type.c_str()); + return false; + } + parsedOptions.insert(type); + if (EqualsIgnoreCase(type, "-i")) { + if (values.size() == 0) { + dprintf(fd, "no values specified when using \"-i\"\n"); + return false; + } + prop->value.int32Values.resize(values.size()); + for (size_t i = 0; i < values.size(); i++) { + int32_t safeInt; + if (!safelyParseInt(fd, currentIndex + i, values[i], &safeInt)) { + dprintf(fd, "value: \"%s\" is not a valid int\n", values[i].c_str()); + return false; + } + prop->value.int32Values[i] = safeInt; + } + } else if (EqualsIgnoreCase(type, "-i64")) { + if (values.size() == 0) { + dprintf(fd, "no values specified when using \"-i64\"\n"); + return false; + } + prop->value.int64Values.resize(values.size()); + for (size_t i = 0; i < values.size(); i++) { + int64_t safeInt; + if (!safelyParseInt(fd, currentIndex + i, values[i], &safeInt)) { + dprintf(fd, "value: \"%s\" is not a valid int64\n", values[i].c_str()); + return false; + } + prop->value.int64Values[i] = safeInt; + } + } else if (EqualsIgnoreCase(type, "-f")) { + if (values.size() == 0) { + dprintf(fd, "no values specified when using \"-f\"\n"); + return false; + } + prop->value.floatValues.resize(values.size()); + for (size_t i = 0; i < values.size(); i++) { + float safeFloat; + if (!safelyParseFloat(fd, currentIndex + i, values[i], &safeFloat)) { + dprintf(fd, "value: \"%s\" is not a valid float\n", values[i].c_str()); + return false; + } + prop->value.floatValues[i] = safeFloat; + } + } else if (EqualsIgnoreCase(type, "-s")) { + if (values.size() != 1) { + dprintf(fd, "expect exact one value when using \"-s\"\n"); + return false; + } + prop->value.stringValue = values[0]; + } else if (EqualsIgnoreCase(type, "-b")) { + if (values.size() != 1) { + dprintf(fd, "expect exact one value when using \"-b\"\n"); + return false; + } + std::vector<uint8_t> bytes; + if (!parseHexString(fd, values[0], &bytes)) { + dprintf(fd, "value: \"%s\" is not a valid hex string\n", values[0].c_str()); + return false; + } + prop->value.bytes = bytes; + } else if (EqualsIgnoreCase(type, "-a")) { + if (values.size() != 1) { + dprintf(fd, "expect exact one value when using \"-a\"\n"); + return false; + } + if (!safelyParseInt(fd, currentIndex, values[0], &(prop->areaId))) { + dprintf(fd, "area ID: \"%s\" is not a valid int\n", values[0].c_str()); + return false; + } + } else { + dprintf(fd, "unknown option: %s\n", type.c_str()); + return false; + } + } + + return true; +} + +bool VehicleHalManager::parseHexString(int fd, const std::string& s, std::vector<uint8_t>* bytes) { + if (s.size() % 2 != 0) { + dprintf(fd, "invalid hex string: %s, should have even size\n", s.c_str()); + return false; + } + if (strncmp(s.substr(0, 2).c_str(), "0x", 2)) { + dprintf(fd, "hex string should start with \"0x\", got %s\n", s.c_str()); + return false; + } + std::string subs = s.substr(2); + std::transform(subs.begin(), subs.end(), subs.begin(), + [](unsigned char c) { return std::tolower(c); }); + + bool highDigit = true; + for (size_t i = 0; i < subs.size(); i++) { + char c = subs[i]; + uint8_t v; + if (c >= '0' && c <= '9') { + v = c - '0'; + } else if (c >= 'a' && c <= 'f') { + v = c - 'a' + 10; + } else { + dprintf(fd, "invalid character %c in hex string %s\n", c, subs.c_str()); + return false; + } + if (highDigit) { + (*bytes).push_back(v * 16); + } else { + (*bytes)[bytes->size() - 1] += v; + } + highDigit = !highDigit; + } + return true; +} + } // namespace V2_0 } // namespace vehicle } // namespace automotive diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h index 8ff492471d..55617be30d 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h @@ -307,6 +307,18 @@ const ConfigDeclaration kVehicleProperties[]{ .prop = toInt(VehicleProperty::CRITICALLY_LOW_TIRE_PRESSURE), .access = VehiclePropertyAccess::READ, .changeMode = VehiclePropertyChangeMode::STATIC, + .areaConfigs = {VehicleAreaConfig{ + .areaId = WHEEL_FRONT_LEFT, + }, + VehicleAreaConfig{ + .areaId = WHEEL_FRONT_RIGHT, + }, + VehicleAreaConfig{ + .areaId = WHEEL_REAR_LEFT, + }, + VehicleAreaConfig{ + .areaId = WHEEL_REAR_RIGHT, + }}, }, .initialAreaValues = {{WHEEL_FRONT_LEFT, {.floatValues = {137.0f}}}, {WHEEL_FRONT_RIGHT, {.floatValues = {137.0f}}}, @@ -1032,14 +1044,6 @@ const ConfigDeclaration kVehicleProperties[]{ { .config = { - .prop = toInt(VehicleProperty::STORAGE_ENCRYPTION_BINDING_SEED), - .access = VehiclePropertyAccess::READ_WRITE, - .changeMode = VehiclePropertyChangeMode::ON_CHANGE, - }, - }, - { - .config = - { .prop = toInt(VehicleProperty::WATCHDOG_ALIVE), .access = VehiclePropertyAccess::WRITE, .changeMode = VehiclePropertyChangeMode::ON_CHANGE, @@ -1105,6 +1109,42 @@ const ConfigDeclaration kVehicleProperties[]{ .changeMode = VehiclePropertyChangeMode::ON_CHANGE, }, }, + { + .config = + { + .prop = PLACEHOLDER_PROPERTY_INT, + .access = VehiclePropertyAccess::READ_WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + }, + .initialValue = {.int32Values = {0}}, + }, + { + .config = + { + .prop = PLACEHOLDER_PROPERTY_FLOAT, + .access = VehiclePropertyAccess::READ_WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + }, + .initialValue = {.floatValues = {0.0f}}, + }, + { + .config = + { + .prop = PLACEHOLDER_PROPERTY_BOOLEAN, + .access = VehiclePropertyAccess::READ_WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + }, + .initialValue = {.int32Values = {0 /* false */}}, + }, + { + .config = + { + .prop = PLACEHOLDER_PROPERTY_STRING, + .access = VehiclePropertyAccess::READ_WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + }, + .initialValue = {.stringValue = {"Test"}}, + }, #ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING // Vendor propetry for E2E ClusterHomeService testing. { diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h index d5f6a1841e..51251a7e70 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h @@ -189,6 +189,19 @@ enum class FakeDataCommand : int32_t { KeyPress = 100, }; +/** + * These properties are placeholder properties for developers to test new features without + * implementing a real property. + */ +constexpr int32_t PLACEHOLDER_PROPERTY_INT = + 0x2a11 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::INT32; +constexpr int32_t PLACEHOLDER_PROPERTY_FLOAT = + 0x2a11 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::FLOAT; +constexpr int32_t PLACEHOLDER_PROPERTY_BOOLEAN = + 0x2a11 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::BOOLEAN; +constexpr int32_t PLACEHOLDER_PROPERTY_STRING = + 0x2a11 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::STRING; + const int32_t kHvacPowerProperties[] = { toInt(VehicleProperty::HVAC_FAN_SPEED), toInt(VehicleProperty::HVAC_FAN_DIRECTION), diff --git a/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp b/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp index 09750718a0..bdf46fb24c 100644 --- a/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp +++ b/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp @@ -18,6 +18,7 @@ #include <iostream> #include <android-base/macros.h> +#include <cutils/native_handle.h> #include <utils/SystemClock.h> #include <gtest/gtest.h> @@ -32,6 +33,18 @@ namespace automotive { namespace vehicle { namespace V2_0 { +// A simple helper class to expose 'cmdSetOneProperty' to the unit tests. +class VehicleHalManagerTestHelper { + public: + VehicleHalManagerTestHelper(VehicleHalManager* manager) { mManager = manager; } + bool cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options) { + return mManager->cmdSetOneProperty(fd, options); + } + + public: + VehicleHalManager* mManager; +}; + namespace { using namespace std::placeholders; @@ -57,33 +70,21 @@ public: auto property = static_cast<VehicleProperty>(requestedPropValue.prop); int32_t areaId = requestedPropValue.areaId; - switch (property) { - case VehicleProperty::INFO_MAKE: - pValue = getValuePool()->obtainString(kCarMake); - break; - case VehicleProperty::INFO_FUEL_CAPACITY: - if (fuelCapacityAttemptsLeft-- > 0) { - // Emulate property not ready yet. - *outStatus = StatusCode::TRY_AGAIN; - } else { - pValue = getValuePool()->obtainFloat(42.42); - } - break; - default: - if (requestedPropValue.prop == kCustomComplexProperty) { - pValue = getValuePool()->obtainComplex(); - pValue->value.int32Values = hidl_vec<int32_t> { 10, 20 }; - pValue->value.int64Values = hidl_vec<int64_t> { 30, 40 }; - pValue->value.floatValues = hidl_vec<float_t> { 1.1, 2.2 }; - pValue->value.bytes = hidl_vec<uint8_t> { 1, 2, 3 }; - pValue->value.stringValue = kCarMake; - break; - } - auto key = makeKey(toInt(property), areaId); - if (mValues.count(key) == 0) { - ALOGW(""); - } - pValue = getValuePool()->obtain(mValues[key]); + if (property == VehicleProperty::INFO_FUEL_CAPACITY) { + if (fuelCapacityAttemptsLeft-- > 0) { + // Emulate property not ready yet. + *outStatus = StatusCode::TRY_AGAIN; + } else { + pValue = getValuePool()->obtainFloat(42.42); + } + } else { + auto key = makeKey(requestedPropValue); + if (mValues.count(key) == 0) { + ALOGW("key not found\n"); + *outStatus = StatusCode::INVALID_ARG; + return pValue; + } + pValue = getValuePool()->obtain(mValues[key]); } if (*outStatus == StatusCode::OK && pValue.get() != nullptr) { @@ -100,7 +101,6 @@ public: && mirrorFoldAttemptsLeft-- > 0) { return StatusCode::TRY_AGAIN; } - mValues[makeKey(propValue)] = propValue; return StatusCode::OK; } @@ -181,6 +181,18 @@ public: actualStatusCode = refStatus; } + MockedVehicleHal::VehiclePropValuePtr getComplexProperty() { + auto pValue = objectPool->obtainComplex(); + pValue->prop = kCustomComplexProperty; + pValue->areaId = 0; + pValue->value.int32Values = hidl_vec<int32_t>{10, 20}; + pValue->value.int64Values = hidl_vec<int64_t>{30, 40}; + pValue->value.floatValues = hidl_vec<float_t>{1.1, 2.2}; + pValue->value.bytes = hidl_vec<uint8_t>{1, 2, 3}; + pValue->value.stringValue = kCarMake; + return pValue; + } + public: VehiclePropValue actualValue; StatusCode actualStatusCode; @@ -308,6 +320,8 @@ TEST_F(VehicleHalManagerTest, subscribe_WriteOnly) { } TEST_F(VehicleHalManagerTest, get_Complex) { + ASSERT_EQ(StatusCode::OK, hal->set(*getComplexProperty().get())); + invokeGet(kCustomComplexProperty, 0); ASSERT_EQ(StatusCode::OK, actualStatusCode); @@ -334,6 +348,11 @@ TEST_F(VehicleHalManagerTest, get_Complex) { } TEST_F(VehicleHalManagerTest, get_StaticString) { + auto pValue = objectPool->obtainString(kCarMake); + pValue->prop = toInt(VehicleProperty::INFO_MAKE); + pValue->areaId = 0; + ASSERT_EQ(StatusCode::OK, hal->set(*pValue.get())); + invokeGet(toInt(VehicleProperty::INFO_MAKE), 0); ASSERT_EQ(StatusCode::OK, actualStatusCode); @@ -458,6 +477,138 @@ TEST(HalClientVectorTest, basic) { ASSERT_TRUE(clients.isEmpty()); } +TEST_F(VehicleHalManagerTest, debug) { + hidl_handle fd = {}; + fd.setTo(native_handle_create(/*numFds=*/1, /*numInts=*/0), /*shouldOwn=*/true); + + // Because debug function returns void, so no way to check return value. + manager->debug(fd, {}); + manager->debug(fd, {"--help"}); + manager->debug(fd, {"--list"}); + manager->debug(fd, {"--get"}); + manager->debug(fd, {"--set"}); + manager->debug(fd, {"invalid"}); +} + +struct SetPropTestCase { + std::string test_name; + const hidl_vec<hidl_string> configs; + bool success; +}; + +class VehicleHalManagerSetPropTest : public VehicleHalManagerTest, + public testing::WithParamInterface<SetPropTestCase> {}; + +TEST_P(VehicleHalManagerSetPropTest, cmdSetOneProperty) { + const SetPropTestCase& tc = GetParam(); + VehicleHalManagerTestHelper helper(manager.get()); + ASSERT_EQ(tc.success, helper.cmdSetOneProperty(STDERR_FILENO, tc.configs)); +} + +std::vector<SetPropTestCase> GenSetPropParams() { + char infoMakeProperty[100] = {}; + snprintf(infoMakeProperty, sizeof(infoMakeProperty), "%d", toInt(VehicleProperty::INFO_MAKE)); + return { + {"success_set_string", {"--set", infoMakeProperty, "-s", kCarMake}, true}, + {"success_set_bytes", {"--set", infoMakeProperty, "-b", "0xdeadbeef"}, true}, + {"success_set_bytes_caps", {"--set", infoMakeProperty, "-b", "0xDEADBEEF"}, true}, + {"success_set_int", {"--set", infoMakeProperty, "-i", "2147483647"}, true}, + {"success_set_ints", + {"--set", infoMakeProperty, "-i", "2147483647", "0", "-2147483648"}, + true}, + {"success_set_int64", + {"--set", infoMakeProperty, "-i64", "-9223372036854775808"}, + true}, + {"success_set_int64s", + {"--set", infoMakeProperty, "-i64", "-9223372036854775808", "0", + "9223372036854775807"}, + true}, + {"success_set_float", {"--set", infoMakeProperty, "-f", "1.175494351E-38"}, true}, + {"success_set_floats", + {"--set", infoMakeProperty, "-f", "-3.402823466E+38", "0", "3.402823466E+38"}, + true}, + {"success_set_area", {"--set", infoMakeProperty, "-a", "2147483647"}, true}, + {"fail_no_options", {}, false}, + {"fail_less_than_4_options", {"--set", infoMakeProperty, "-i"}, false}, + {"fail_unknown_options", {"--set", infoMakeProperty, "-s", kCarMake, "-abcd"}, false}, + {"fail_invalid_property", {"--set", "not valid", "-s", kCarMake}, false}, + {"fail_duplicate_string", + {"--set", infoMakeProperty, "-s", kCarMake, "-s", kCarMake}, + false}, + {"fail_multiple_strings", {"--set", infoMakeProperty, "-s", kCarMake, kCarMake}, false}, + {"fail_no_string_value", {"--set", infoMakeProperty, "-s", "-a", "1234"}, false}, + {"fail_duplicate_bytes", + {"--set", infoMakeProperty, "-b", "0xdeadbeef", "-b", "0xdeadbeef"}, + false}, + {"fail_multiple_bytes", + {"--set", infoMakeProperty, "-b", "0xdeadbeef", "0xdeadbeef"}, + false}, + {"fail_invalid_bytes", {"--set", infoMakeProperty, "-b", "0xgood"}, false}, + {"fail_invalid_bytes_no_prefix", {"--set", infoMakeProperty, "-b", "deadbeef"}, false}, + {"fail_invalid_int", {"--set", infoMakeProperty, "-i", "abc"}, false}, + {"fail_int_out_of_range", {"--set", infoMakeProperty, "-i", "2147483648"}, false}, + {"fail_no_int_value", {"--set", infoMakeProperty, "-i", "-s", kCarMake}, false}, + {"fail_invalid_int64", {"--set", infoMakeProperty, "-i64", "abc"}, false}, + {"fail_int64_out_of_range", + {"--set", infoMakeProperty, "-i64", "-9223372036854775809"}, + false}, + {"fail_no_int64_value", {"--set", infoMakeProperty, "-i64", "-s", kCarMake}, false}, + {"fail_invalid_float", {"--set", infoMakeProperty, "-f", "abc"}, false}, + {"fail_float_out_of_range", + {"--set", infoMakeProperty, "-f", "-3.402823466E+39"}, + false}, + {"fail_no_float_value", {"--set", infoMakeProperty, "-f", "-s", kCarMake}, false}, + {"fail_multiple_areas", {"--set", infoMakeProperty, "-a", "2147483648", "0"}, false}, + {"fail_invalid_area", {"--set", infoMakeProperty, "-a", "abc"}, false}, + {"fail_area_out_of_range", {"--set", infoMakeProperty, "-a", "2147483648"}, false}, + {"fail_no_area_value", {"--set", infoMakeProperty, "-a", "-s", kCarMake}, false}, + }; +} + +INSTANTIATE_TEST_SUITE_P( + VehicleHalManagerSetPropTests, VehicleHalManagerSetPropTest, + testing::ValuesIn(GenSetPropParams()), + [](const testing::TestParamInfo<VehicleHalManagerSetPropTest::ParamType>& info) { + return info.param.test_name; + }); + +TEST_F(VehicleHalManagerTest, SetComplexPropTest) { + char infoMakeProperty[100] = {}; + snprintf(infoMakeProperty, sizeof(infoMakeProperty), "%d", toInt(VehicleProperty::INFO_MAKE)); + VehicleHalManagerTestHelper helper(manager.get()); + ASSERT_TRUE(helper.cmdSetOneProperty( + STDERR_FILENO, {"--set", infoMakeProperty, "-s", kCarMake, + "-b", "0xdeadbeef", "-i", "2147483647", + "0", "-2147483648", "-i64", "-9223372036854775808", + "0", "9223372036854775807", "-f", "-3.402823466E+38", + "0", "3.402823466E+38", "-a", "123"})); + StatusCode status = StatusCode::OK; + VehiclePropValue requestProp; + requestProp.prop = toInt(VehicleProperty::INFO_MAKE); + requestProp.areaId = 123; + auto value = hal->get(requestProp, &status); + ASSERT_EQ(StatusCode::OK, status); + ASSERT_EQ(value->prop, toInt(VehicleProperty::INFO_MAKE)); + ASSERT_EQ(value->areaId, 123); + ASSERT_STREQ(kCarMake, value->value.stringValue.c_str()); + uint8_t bytes[] = {0xde, 0xad, 0xbe, 0xef}; + ASSERT_FALSE(memcmp(bytes, value->value.bytes.data(), sizeof(bytes))); + ASSERT_EQ(3u, value->value.int32Values.size()); + ASSERT_EQ(2147483647, value->value.int32Values[0]); + ASSERT_EQ(0, value->value.int32Values[1]); + ASSERT_EQ(-2147483648, value->value.int32Values[2]); + ASSERT_EQ(3u, value->value.int64Values.size()); + // -9223372036854775808 is not a valid literal since '-' and '9223372036854775808' would be two + // tokens and the later does not fit in unsigned long long. + ASSERT_EQ(-9223372036854775807 - 1, value->value.int64Values[0]); + ASSERT_EQ(0, value->value.int64Values[1]); + ASSERT_EQ(9223372036854775807, value->value.int64Values[2]); + ASSERT_EQ(3u, value->value.floatValues.size()); + ASSERT_EQ(-3.402823466E+38f, value->value.floatValues[0]); + ASSERT_EQ(0.0f, value->value.floatValues[1]); + ASSERT_EQ(3.402823466E+38f, value->value.floatValues[2]); +} + } // namespace anonymous } // namespace V2_0 diff --git a/camera/metadata/3.7/types.hal b/camera/metadata/3.7/types.hal new file mode 100644 index 0000000000..a09bdf9977 --- /dev/null +++ b/camera/metadata/3.7/types.hal @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2021 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. + */ + +/* + * Autogenerated from camera metadata definitions in + * /system/media/camera/docs/metadata_definitions.xml + * *** DO NOT EDIT BY HAND *** + */ + +package android.hardware.camera.metadata@3.7; + +import android.hardware.camera.metadata@3.2; +import android.hardware.camera.metadata@3.3; +import android.hardware.camera.metadata@3.4; +import android.hardware.camera.metadata@3.5; +import android.hardware.camera.metadata@3.6; + +// No new metadata sections added in this revision + +/** + * Main enumeration for defining camera metadata tags added in this revision + * + * <p>Partial documentation is included for each tag; for complete documentation, reference + * '/system/media/camera/docs/docs.html' in the corresponding Android source tree.</p> + */ +enum CameraMetadataTag : @3.6::CameraMetadataTag { + /** android.info.deviceStateOrientations [static, int64[], ndk_public] + */ + ANDROID_INFO_DEVICE_STATE_ORIENTATIONS = android.hardware.camera.metadata@3.4::CameraMetadataTag:ANDROID_INFO_END_3_4, + + ANDROID_INFO_END_3_7, + +}; + +/* + * Enumeration definitions for the various entries that need them + */ diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp index 37d2973bb8..052103d784 100644 --- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp +++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp @@ -882,6 +882,7 @@ public: camera_metadata* oldSessionParams, camera_metadata* newSessionParams); void verifyRequestTemplate(const camera_metadata_t* metadata, RequestTemplate requestTemplate); + static void overrideRotateAndCrop(::android::hardware::hidl_vec<uint8_t> *settings /*in/out*/); static bool isDepthOnly(const camera_metadata_t* staticMeta); @@ -935,6 +936,9 @@ public: camera_metadata_ro_entry* streamConfigs, camera_metadata_ro_entry* maxResolutionStreamConfigs, const camera_metadata_t* staticMetadata); + void getPrivacyTestPatternModes( + const camera_metadata_t* staticMetadata, + std::unordered_set<int32_t>* privacyTestPatternModes/*out*/); static V3_2::DataspaceFlags getDataspace(PixelFormat format); @@ -4659,6 +4663,7 @@ void CameraHidlTest::processCaptureRequestInternal(uint64_t bufferUsage, settings = req; }); ASSERT_TRUE(ret.isOk()); + overrideRotateAndCrop(&settings); hidl_handle buffer_handle; StreamBuffer outputBuffer; @@ -4835,6 +4840,7 @@ TEST_P(CameraHidlTest, processMultiCaptureRequestPreview) { settings.setToExternal( reinterpret_cast<uint8_t *> (const_cast<camera_metadata_t *> (settingsBuffer)), get_camera_metadata_size(settingsBuffer)); + overrideRotateAndCrop(&settings); free_camera_metadata(staticMeta); ret = session->close(); @@ -4912,6 +4918,7 @@ TEST_P(CameraHidlTest, processMultiCaptureRequestPreview) { reinterpret_cast<uint8_t *> (const_cast<camera_metadata_t *> ( filteredSettingsBuffer)), get_camera_metadata_size(filteredSettingsBuffer)); + overrideRotateAndCrop(&camSettings[0].settings); camSettings[0].fmqSettingsSize = 0; camSettings[0].physicalCameraId = physicalDeviceId; @@ -5069,6 +5076,7 @@ TEST_P(CameraHidlTest, processUltraHighResolutionRequest) { settings.setToExternal( reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(settingsBuffer)), get_camera_metadata_size(settingsBuffer)); + overrideRotateAndCrop(&settings); free_camera_metadata(staticMeta); ret = session->close(); @@ -5304,6 +5312,7 @@ TEST_P(CameraHidlTest, processCaptureRequestBurstISO) { camera_metadata_t *metaBuffer = requestMeta.release(); requestSettings[i].setToExternal(reinterpret_cast<uint8_t *> (metaBuffer), get_camera_metadata_size(metaBuffer), true); + overrideRotateAndCrop(&requestSettings[i]); requests[i] = {frameNumber + i, 0 /* fmqSettingsSize */, requestSettings[i], emptyInputBuffer, {outputBuffers[i]}}; @@ -5530,6 +5539,7 @@ TEST_P(CameraHidlTest, switchToOffline) { camera_metadata_t *metaBuffer = requestMeta.release(); requestSettings[i].setToExternal(reinterpret_cast<uint8_t *> (metaBuffer), get_camera_metadata_size(metaBuffer), true); + overrideRotateAndCrop(&requestSettings[i]); requests[i] = {frameNumber + i, 0 /* fmqSettingsSize */, requestSettings[i], emptyInputBuffer, {outputBuffers[i]}}; @@ -5670,6 +5680,7 @@ TEST_P(CameraHidlTest, processCaptureRequestInvalidBuffer) { settings = req; }); ASSERT_TRUE(ret.isOk()); + overrideRotateAndCrop(&settings); ::android::hardware::hidl_vec<StreamBuffer> emptyOutputBuffers; StreamBuffer emptyInputBuffer = {-1, 0, nullptr, BufferStatus::ERROR, nullptr, @@ -5754,6 +5765,7 @@ TEST_P(CameraHidlTest, flushPreviewRequest) { settings = req; }); ASSERT_TRUE(ret.isOk()); + overrideRotateAndCrop(&settings); hidl_handle buffer_handle; if (useHalBufManager) { @@ -6617,6 +6629,25 @@ void CameraHidlTest::getMultiResolutionStreamConfigurations( ASSERT_TRUE(-ENOENT == retcode || 0 == retcode); } +void CameraHidlTest::getPrivacyTestPatternModes( + const camera_metadata_t* staticMetadata, + std::unordered_set<int32_t>* privacyTestPatternModes/*out*/) { + ASSERT_NE(staticMetadata, nullptr); + ASSERT_NE(privacyTestPatternModes, nullptr); + + camera_metadata_ro_entry entry; + int retcode = find_camera_metadata_ro_entry( + staticMetadata, ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES, &entry); + ASSERT_TRUE(0 == retcode); + + for (auto i = 0; i < entry.count; i++) { + if (entry.data.i32[i] == ANDROID_SENSOR_TEST_PATTERN_MODE_SOLID_COLOR || + entry.data.i32[i] == ANDROID_SENSOR_TEST_PATTERN_MODE_BLACK) { + privacyTestPatternModes->insert(entry.data.i32[i]); + } + } +} + // Select an appropriate dataspace given a specific pixel format. V3_2::DataspaceFlags CameraHidlTest::getDataspace(PixelFormat format) { switch (format) { @@ -7654,6 +7685,16 @@ void CameraHidlTest::verifyLogicalOrUltraHighResCameraMetadata( ASSERT_TRUE(isUltraHighResCamera && !isMultiCamera); physicalIds.insert(cameraId); } + + std::unordered_set<int32_t> physicalRequestKeyIDs; + rc = getSupportedKeys(const_cast<camera_metadata_t *>(metadata), + ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS, &physicalRequestKeyIDs); + ASSERT_TRUE(Status::OK == rc); + bool hasTestPatternPhysicalRequestKey = physicalRequestKeyIDs.find( + ANDROID_SENSOR_TEST_PATTERN_MODE) != physicalRequestKeyIDs.end(); + std::unordered_set<int32_t> privacyTestPatternModes; + getPrivacyTestPatternModes(metadata, &privacyTestPatternModes); + // Map from image format to number of multi-resolution sizes for that format std::unordered_map<int32_t, size_t> multiResOutputFormatCounterMap; std::unordered_map<int32_t, size_t> multiResInputFormatCounterMap; @@ -7675,6 +7716,7 @@ void CameraHidlTest::verifyLogicalOrUltraHighResCameraMetadata( camera_metadata_ro_entry physicalStreamConfigs; camera_metadata_ro_entry physicalMaxResolutionStreamConfigs; bool isUltraHighRes = false; + std::unordered_set<int32_t> subCameraPrivacyTestPatterns; if (isPublicId) { ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> subDevice; Return<void> ret; @@ -7705,6 +7747,8 @@ void CameraHidlTest::verifyLogicalOrUltraHighResCameraMetadata( &physicalMultiResStreamConfigs, &physicalStreamConfigs, &physicalMaxResolutionStreamConfigs, staticMetadata); isUltraHighRes = isUltraHighResolution(staticMetadata); + + getPrivacyTestPatternModes(staticMetadata, &subCameraPrivacyTestPatterns); }); ASSERT_TRUE(ret.isOk()); } else { @@ -7731,6 +7775,7 @@ void CameraHidlTest::verifyLogicalOrUltraHighResCameraMetadata( &physicalMultiResStreamConfigs, &physicalStreamConfigs, &physicalMaxResolutionStreamConfigs, staticMetadata); isUltraHighRes = isUltraHighResolution(staticMetadata); + getPrivacyTestPatternModes(staticMetadata, &subCameraPrivacyTestPatterns); }); ASSERT_TRUE(ret.isOk()); @@ -7747,6 +7792,10 @@ void CameraHidlTest::verifyLogicalOrUltraHighResCameraMetadata( ASSERT_TRUE(ret.isOk()); } + if (hasTestPatternPhysicalRequestKey) { + ASSERT_TRUE(privacyTestPatternModes == subCameraPrivacyTestPatterns); + } + if (physicalMultiResStreamConfigs.count > 0) { ASSERT_GE(deviceVersion, CAMERA_DEVICE_API_VERSION_3_7); ASSERT_EQ(physicalMultiResStreamConfigs.count % 4, 0); @@ -7982,6 +8031,20 @@ void CameraHidlTest::verifyCameraCharacteristics(Status status, const CameraMeta poseReference >= ANDROID_LENS_POSE_REFERENCE_PRIMARY_CAMERA); } + retcode = find_camera_metadata_ro_entry(metadata, + ANDROID_INFO_DEVICE_STATE_ORIENTATIONS, &entry); + if (0 == retcode && entry.count > 0) { + ASSERT_TRUE((entry.count % 2) == 0); + uint64_t maxPublicState = ((uint64_t) provider::V2_5::DeviceState::FOLDED) << 1; + uint64_t vendorStateStart = 1UL << 31; // Reserved for vendor specific states + uint64_t stateMask = (1 << vendorStateStart) - 1; + stateMask &= ~((1 << maxPublicState) - 1); + for (int i = 0; i < entry.count; i += 2){ + ASSERT_TRUE((entry.data.i64[i] & stateMask) == 0); + ASSERT_TRUE((entry.data.i64[i+1] % 90) == 0); + } + } + verifyExtendedSceneModeCharacteristics(metadata); verifyZoomCharacteristics(metadata); } @@ -8742,6 +8805,25 @@ void CameraHidlTest::verifyRequestTemplate(const camera_metadata_t* metadata, } } +void CameraHidlTest::overrideRotateAndCrop( + ::android::hardware::hidl_vec<uint8_t> *settings /*in/out*/) { + if (settings == nullptr) { + return; + } + + ::android::hardware::camera::common::V1_0::helper::CameraMetadata requestMeta; + requestMeta.append(reinterpret_cast<camera_metadata_t *> (settings->data())); + auto entry = requestMeta.find(ANDROID_SCALER_ROTATE_AND_CROP); + if ((entry.count > 0) && (entry.data.u8[0] == ANDROID_SCALER_ROTATE_AND_CROP_AUTO)) { + uint8_t disableRotateAndCrop = ANDROID_SCALER_ROTATE_AND_CROP_NONE; + requestMeta.update(ANDROID_SCALER_ROTATE_AND_CROP, &disableRotateAndCrop, 1); + settings->releaseData(); + camera_metadata_t *metaBuffer = requestMeta.release(); + settings->setToExternal(reinterpret_cast<uint8_t *> (metaBuffer), + get_camera_metadata_size(metaBuffer), true); + } +} + GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CameraHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, CameraHidlTest, diff --git a/current.txt b/current.txt index 7718b98519..6a77e19f7b 100644 --- a/current.txt +++ b/current.txt @@ -901,6 +901,9 @@ c8a57364f6ad20842be14f4db284df5304f7521ca8eac6bcc1fa6c5b466fb8a6 android.hardwar 4a087a308608d146b022ebc15633de989f5f4dfe1491a83fa41763290a82e40d android.hardware.automotive.vehicle@2.0::types 70eb14415391f835fb218b43a1e25f5d6495f098f96fa2acaea70985e98e1ce8 android.hardware.automotive.vehicle@2.0::types +# HALs released in Android SCv2 +77f6fcf3fd0dd3e424d8a0292094ebd17e4c35454bb9abbd3a6cbed1aba70765 android.hardware.camera.metadata@3.7::types + # ABI preserving changes to HALs during Android T 62ace52d9c3ff1f60f94118557a2aaf0b953513e59dcd34d5f94ae28d4c7e780 android.hardware.fastboot@1.0::IFastboot d0fb32f3ddeb9af7115ab32905225ea69b930d2472be8e9610f0cf136c15aefb android.hardware.keymaster@4.0::IKeymasterDevice # b/210424594 diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp index 8cb7e22f0e..114fe4f32c 100644 --- a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp +++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp @@ -317,7 +317,7 @@ bool turnOnExcessiveLogging(const sp<ISupplicant>& supplicant) { } bool waitForFrameworkReady() { - int waitCount = 10; + int waitCount = 15; do { // Check whether package service is ready or not. if (!testing::checkSubstringInCommandOutput( diff --git a/wifi/supplicant/1.4/vts/functional/Android.bp b/wifi/supplicant/1.4/vts/functional/Android.bp index 8cbe04f686..57ee83073b 100644 --- a/wifi/supplicant/1.4/vts/functional/Android.bp +++ b/wifi/supplicant/1.4/vts/functional/Android.bp @@ -77,7 +77,6 @@ cc_test { "general-tests", "vts", ], - disable_framework: true, } cc_test { @@ -108,5 +107,4 @@ cc_test { "general-tests", "vts", ], - disable_framework: true, } |