Merge sc-v2-dev-plus-aosp-without-vendor@8084891
Bug: 214455710 Merged-In: Id9e06f88539b59480d5cf57a4ba67cef4676c1d5 Change-Id: Id6b1ea4f8700446b044255e80f21c137aeb7acf1
This commit is contained in:
commit
0bf8f21279
19 changed files with 857 additions and 292 deletions
|
@ -48,6 +48,8 @@ cc_defaults {
|
||||||
"libhidlbase",
|
"libhidlbase",
|
||||||
"liblog",
|
"liblog",
|
||||||
"libmedia_helper",
|
"libmedia_helper",
|
||||||
|
"libmediautils_vendor",
|
||||||
|
"libmemunreachable",
|
||||||
"libutils",
|
"libutils",
|
||||||
"android.hardware.audio.common-util",
|
"android.hardware.audio.common-util",
|
||||||
],
|
],
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include <android/log.h>
|
#include <android/log.h>
|
||||||
|
#include <mediautils/MemoryLeakTrackUtil.h>
|
||||||
|
#include <memunreachable/memunreachable.h>
|
||||||
|
|
||||||
#include <HidlUtils.h>
|
#include <HidlUtils.h>
|
||||||
|
|
||||||
|
@ -501,9 +503,32 @@ Return<void> Device::debugDump(const hidl_handle& fd) {
|
||||||
}
|
}
|
||||||
#endif
|
#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) {
|
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();
|
return Void();
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,4 +64,5 @@ cc_binary {
|
||||||
"android.hardware.automotive@libc++fs",
|
"android.hardware.automotive@libc++fs",
|
||||||
"libnl++",
|
"libnl++",
|
||||||
],
|
],
|
||||||
|
vintf_fragments: ["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>
|
|
@ -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_0 = ::android::hardware::automotive::evs::V1_0::IEvsDisplay;
|
||||||
using IEvsDisplay_1_1 = ::android::hardware::automotive::evs::V1_1::IEvsDisplay;
|
using IEvsDisplay_1_1 = ::android::hardware::automotive::evs::V1_1::IEvsDisplay;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Plese note that this is different from what is defined in
|
* Plese note that this is different from what is defined in
|
||||||
* libhardware/modules/camera/3_4/metadata/types.h; this has one additional
|
* libhardware/modules/camera/3_4/metadata/types.h; this has one additional
|
||||||
* field to store a framerate.
|
* field to store a framerate.
|
||||||
*/
|
*/
|
||||||
const size_t kStreamCfgSz = 5;
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
int32_t id;
|
||||||
int32_t width;
|
int32_t width;
|
||||||
int32_t height;
|
int32_t height;
|
||||||
int32_t format;
|
int32_t format;
|
||||||
int32_t direction;
|
int32_t direction;
|
||||||
int32_t framerate;
|
int32_t framerate;
|
||||||
} RawStreamConfig;
|
} RawStreamConfig;
|
||||||
|
constexpr const size_t kStreamCfgSz = sizeof(RawStreamConfig) / sizeof(int32_t);
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
|
||||||
// The main test class for EVS
|
// The main test class for EVS
|
||||||
|
@ -236,6 +241,28 @@ protected:
|
||||||
return physicalCameras;
|
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
|
sp<IEvsEnumerator> pEnumerator; // Every test needs access to the service
|
||||||
std::vector<CameraDesc> cameraInfo; // Empty unless/until loadCameraList() is called
|
std::vector<CameraDesc> cameraInfo; // Empty unless/until loadCameraList() is called
|
||||||
|
@ -265,10 +292,6 @@ TEST_P(EvsHidlTest, CameraOpenClean) {
|
||||||
// Get the camera list
|
// Get the camera list
|
||||||
loadCameraList();
|
loadCameraList();
|
||||||
|
|
||||||
// Using null stream configuration makes EVS uses the default resolution and
|
|
||||||
// output format.
|
|
||||||
Stream nullCfg = {};
|
|
||||||
|
|
||||||
// Open and close each camera twice
|
// Open and close each camera twice
|
||||||
for (auto&& cam: cameraInfo) {
|
for (auto&& cam: cameraInfo) {
|
||||||
bool isLogicalCam = false;
|
bool isLogicalCam = false;
|
||||||
|
@ -278,8 +301,14 @@ TEST_P(EvsHidlTest, CameraOpenClean) {
|
||||||
continue;
|
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++) {
|
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);
|
ASSERT_NE(pCam, nullptr);
|
||||||
|
|
||||||
for (auto&& devName : devices) {
|
for (auto&& devName : devices) {
|
||||||
|
@ -343,10 +372,6 @@ TEST_P(EvsHidlTest, CameraOpenAggressive) {
|
||||||
// Get the camera list
|
// Get the camera list
|
||||||
loadCameraList();
|
loadCameraList();
|
||||||
|
|
||||||
// Using null stream configuration makes EVS uses the default resolution and
|
|
||||||
// output format.
|
|
||||||
Stream nullCfg = {};
|
|
||||||
|
|
||||||
// Open and close each camera twice
|
// Open and close each camera twice
|
||||||
for (auto&& cam: cameraInfo) {
|
for (auto&& cam: cameraInfo) {
|
||||||
bool isLogicalCam = false;
|
bool isLogicalCam = false;
|
||||||
|
@ -356,10 +381,14 @@ TEST_P(EvsHidlTest, CameraOpenAggressive) {
|
||||||
continue;
|
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();
|
activeCameras.clear();
|
||||||
sp<IEvsCamera_1_1> pCam =
|
sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
|
||||||
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
|
|
||||||
.withDefault(nullptr);
|
|
||||||
ASSERT_NE(pCam, nullptr);
|
ASSERT_NE(pCam, nullptr);
|
||||||
|
|
||||||
// Store a camera handle for a clean-up
|
// Store a camera handle for a clean-up
|
||||||
|
@ -372,9 +401,7 @@ TEST_P(EvsHidlTest, CameraOpenAggressive) {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
sp<IEvsCamera_1_1> pCam2 =
|
sp<IEvsCamera_1_1> pCam2 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
|
||||||
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
|
|
||||||
.withDefault(nullptr);
|
|
||||||
ASSERT_NE(pCam2, nullptr);
|
ASSERT_NE(pCam2, nullptr);
|
||||||
|
|
||||||
// Store a camera handle for a clean-up
|
// Store a camera handle for a clean-up
|
||||||
|
@ -422,10 +449,6 @@ TEST_P(EvsHidlTest, CameraStreamPerformance) {
|
||||||
// Get the camera list
|
// Get the camera list
|
||||||
loadCameraList();
|
loadCameraList();
|
||||||
|
|
||||||
// Using null stream configuration makes EVS uses the default resolution and
|
|
||||||
// output format.
|
|
||||||
Stream nullCfg = {};
|
|
||||||
|
|
||||||
// Test each reported camera
|
// Test each reported camera
|
||||||
for (auto&& cam: cameraInfo) {
|
for (auto&& cam: cameraInfo) {
|
||||||
bool isLogicalCam = false;
|
bool isLogicalCam = false;
|
||||||
|
@ -435,9 +458,13 @@ TEST_P(EvsHidlTest, CameraStreamPerformance) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
sp<IEvsCamera_1_1> pCam =
|
// Read a target resolution from the metadata
|
||||||
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
|
Stream targetCfg =
|
||||||
.withDefault(nullptr);
|
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);
|
ASSERT_NE(pCam, nullptr);
|
||||||
|
|
||||||
// Store a camera handle for a clean-up
|
// Store a camera handle for a clean-up
|
||||||
|
@ -519,10 +546,6 @@ TEST_P(EvsHidlTest, CameraStreamBuffering) {
|
||||||
// Get the camera list
|
// Get the camera list
|
||||||
loadCameraList();
|
loadCameraList();
|
||||||
|
|
||||||
// Using null stream configuration makes EVS uses the default resolution and
|
|
||||||
// output format.
|
|
||||||
Stream nullCfg = {};
|
|
||||||
|
|
||||||
// Test each reported camera
|
// Test each reported camera
|
||||||
for (auto&& cam: cameraInfo) {
|
for (auto&& cam: cameraInfo) {
|
||||||
bool isLogicalCam = false;
|
bool isLogicalCam = false;
|
||||||
|
@ -532,9 +555,13 @@ TEST_P(EvsHidlTest, CameraStreamBuffering) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
sp<IEvsCamera_1_1> pCam =
|
// Read a target resolution from the metadata
|
||||||
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
|
Stream targetCfg =
|
||||||
.withDefault(nullptr);
|
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);
|
ASSERT_NE(pCam, nullptr);
|
||||||
|
|
||||||
// Store a camera handle for a clean-up
|
// Store a camera handle for a clean-up
|
||||||
|
@ -601,10 +628,6 @@ TEST_P(EvsHidlTest, CameraToDisplayRoundTrip) {
|
||||||
// Get the camera list
|
// Get the camera list
|
||||||
loadCameraList();
|
loadCameraList();
|
||||||
|
|
||||||
// Using null stream configuration makes EVS uses the default resolution and
|
|
||||||
// output format.
|
|
||||||
Stream nullCfg = {};
|
|
||||||
|
|
||||||
// Request available display IDs
|
// Request available display IDs
|
||||||
uint8_t targetDisplayId = 0;
|
uint8_t targetDisplayId = 0;
|
||||||
pEnumerator->getDisplayIdList([&targetDisplayId](auto ids) {
|
pEnumerator->getDisplayIdList([&targetDisplayId](auto ids) {
|
||||||
|
@ -642,9 +665,13 @@ TEST_P(EvsHidlTest, CameraToDisplayRoundTrip) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
sp<IEvsCamera_1_1> pCam =
|
// Read a target resolution from the metadata
|
||||||
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
|
Stream targetCfg =
|
||||||
.withDefault(nullptr);
|
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);
|
ASSERT_NE(pCam, nullptr);
|
||||||
|
|
||||||
// Store a camera handle for a clean-up
|
// Store a camera handle for a clean-up
|
||||||
|
@ -708,24 +735,22 @@ TEST_P(EvsHidlTest, MultiCameraStream) {
|
||||||
// Get the camera list
|
// Get the camera list
|
||||||
loadCameraList();
|
loadCameraList();
|
||||||
|
|
||||||
// Using null stream configuration makes EVS uses the default resolution and
|
|
||||||
// output format.
|
|
||||||
Stream nullCfg = {};
|
|
||||||
|
|
||||||
// Test each reported camera
|
// Test each reported camera
|
||||||
for (auto&& cam: cameraInfo) {
|
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.
|
// Create two camera clients.
|
||||||
sp<IEvsCamera_1_1> pCam0 =
|
sp<IEvsCamera_1_1> pCam0 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
|
||||||
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
|
|
||||||
.withDefault(nullptr);
|
|
||||||
ASSERT_NE(pCam0, nullptr);
|
ASSERT_NE(pCam0, nullptr);
|
||||||
|
|
||||||
// Store a camera handle for a clean-up
|
// Store a camera handle for a clean-up
|
||||||
activeCameras.push_back(pCam0);
|
activeCameras.push_back(pCam0);
|
||||||
|
|
||||||
sp<IEvsCamera_1_1> pCam1 =
|
sp<IEvsCamera_1_1> pCam1 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
|
||||||
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
|
|
||||||
.withDefault(nullptr);
|
|
||||||
ASSERT_NE(pCam1, nullptr);
|
ASSERT_NE(pCam1, nullptr);
|
||||||
|
|
||||||
// Store a camera handle for a clean-up
|
// Store a camera handle for a clean-up
|
||||||
|
@ -812,10 +837,6 @@ TEST_P(EvsHidlTest, CameraParameter) {
|
||||||
// Get the camera list
|
// Get the camera list
|
||||||
loadCameraList();
|
loadCameraList();
|
||||||
|
|
||||||
// Using null stream configuration makes EVS uses the default resolution and
|
|
||||||
// output format.
|
|
||||||
Stream nullCfg = {};
|
|
||||||
|
|
||||||
// Test each reported camera
|
// Test each reported camera
|
||||||
Return<EvsResult> result = EvsResult::OK;
|
Return<EvsResult> result = EvsResult::OK;
|
||||||
for (auto&& cam: cameraInfo) {
|
for (auto&& cam: cameraInfo) {
|
||||||
|
@ -828,10 +849,14 @@ TEST_P(EvsHidlTest, CameraParameter) {
|
||||||
continue;
|
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
|
// Create a camera client
|
||||||
sp<IEvsCamera_1_1> pCam =
|
sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
|
||||||
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
|
|
||||||
.withDefault(nullptr);
|
|
||||||
ASSERT_NE(pCam, nullptr);
|
ASSERT_NE(pCam, nullptr);
|
||||||
|
|
||||||
// Store a camera
|
// Store a camera
|
||||||
|
@ -961,10 +986,6 @@ TEST_P(EvsHidlTest, CameraPrimaryClientRelease) {
|
||||||
// Get the camera list
|
// Get the camera list
|
||||||
loadCameraList();
|
loadCameraList();
|
||||||
|
|
||||||
// Using null stream configuration makes EVS uses the default resolution and
|
|
||||||
// output format.
|
|
||||||
Stream nullCfg = {};
|
|
||||||
|
|
||||||
// Test each reported camera
|
// Test each reported camera
|
||||||
for (auto&& cam: cameraInfo) {
|
for (auto&& cam: cameraInfo) {
|
||||||
bool isLogicalCam = false;
|
bool isLogicalCam = false;
|
||||||
|
@ -976,18 +997,20 @@ TEST_P(EvsHidlTest, CameraPrimaryClientRelease) {
|
||||||
continue;
|
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.
|
// Create two camera clients.
|
||||||
sp<IEvsCamera_1_1> pCamPrimary =
|
sp<IEvsCamera_1_1> pCamPrimary = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
|
||||||
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
|
|
||||||
.withDefault(nullptr);
|
|
||||||
ASSERT_NE(pCamPrimary, nullptr);
|
ASSERT_NE(pCamPrimary, nullptr);
|
||||||
|
|
||||||
// Store a camera handle for a clean-up
|
// Store a camera handle for a clean-up
|
||||||
activeCameras.push_back(pCamPrimary);
|
activeCameras.push_back(pCamPrimary);
|
||||||
|
|
||||||
sp<IEvsCamera_1_1> pCamSecondary =
|
sp<IEvsCamera_1_1> pCamSecondary = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
|
||||||
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
|
|
||||||
.withDefault(nullptr);
|
|
||||||
ASSERT_NE(pCamSecondary, nullptr);
|
ASSERT_NE(pCamSecondary, nullptr);
|
||||||
|
|
||||||
// Store a camera handle for a clean-up
|
// Store a camera handle for a clean-up
|
||||||
|
@ -1142,10 +1165,6 @@ TEST_P(EvsHidlTest, MultiCameraParameter) {
|
||||||
// Get the camera list
|
// Get the camera list
|
||||||
loadCameraList();
|
loadCameraList();
|
||||||
|
|
||||||
// Using null stream configuration makes EVS uses the default resolution and
|
|
||||||
// output format.
|
|
||||||
Stream nullCfg = {};
|
|
||||||
|
|
||||||
// Test each reported camera
|
// Test each reported camera
|
||||||
for (auto&& cam: cameraInfo) {
|
for (auto&& cam: cameraInfo) {
|
||||||
bool isLogicalCam = false;
|
bool isLogicalCam = false;
|
||||||
|
@ -1157,18 +1176,20 @@ TEST_P(EvsHidlTest, MultiCameraParameter) {
|
||||||
continue;
|
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.
|
// Create two camera clients.
|
||||||
sp<IEvsCamera_1_1> pCamPrimary =
|
sp<IEvsCamera_1_1> pCamPrimary = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
|
||||||
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
|
|
||||||
.withDefault(nullptr);
|
|
||||||
ASSERT_NE(pCamPrimary, nullptr);
|
ASSERT_NE(pCamPrimary, nullptr);
|
||||||
|
|
||||||
// Store a camera handle for a clean-up
|
// Store a camera handle for a clean-up
|
||||||
activeCameras.push_back(pCamPrimary);
|
activeCameras.push_back(pCamPrimary);
|
||||||
|
|
||||||
sp<IEvsCamera_1_1> pCamSecondary =
|
sp<IEvsCamera_1_1> pCamSecondary = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
|
||||||
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
|
|
||||||
.withDefault(nullptr);
|
|
||||||
ASSERT_NE(pCamSecondary, nullptr);
|
ASSERT_NE(pCamSecondary, nullptr);
|
||||||
|
|
||||||
// Store a camera handle for a clean-up
|
// Store a camera handle for a clean-up
|
||||||
|
@ -1615,28 +1636,26 @@ TEST_P(EvsHidlTest, HighPriorityCameraClient) {
|
||||||
// Get the camera list
|
// Get the camera list
|
||||||
loadCameraList();
|
loadCameraList();
|
||||||
|
|
||||||
// Using null stream configuration makes EVS uses the default resolution and
|
|
||||||
// output format.
|
|
||||||
Stream nullCfg = {};
|
|
||||||
|
|
||||||
// Request exclusive access to the EVS display
|
// Request exclusive access to the EVS display
|
||||||
sp<IEvsDisplay_1_0> pDisplay = pEnumerator->openDisplay();
|
sp<IEvsDisplay_1_0> pDisplay = pEnumerator->openDisplay();
|
||||||
ASSERT_NE(pDisplay, nullptr);
|
ASSERT_NE(pDisplay, nullptr);
|
||||||
|
|
||||||
// Test each reported camera
|
// Test each reported camera
|
||||||
for (auto&& cam: cameraInfo) {
|
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
|
// Create two clients
|
||||||
sp<IEvsCamera_1_1> pCam0 =
|
sp<IEvsCamera_1_1> pCam0 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
|
||||||
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
|
|
||||||
.withDefault(nullptr);
|
|
||||||
ASSERT_NE(pCam0, nullptr);
|
ASSERT_NE(pCam0, nullptr);
|
||||||
|
|
||||||
// Store a camera handle for a clean-up
|
// Store a camera handle for a clean-up
|
||||||
activeCameras.push_back(pCam0);
|
activeCameras.push_back(pCam0);
|
||||||
|
|
||||||
sp<IEvsCamera_1_1> pCam1 =
|
sp<IEvsCamera_1_1> pCam1 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
|
||||||
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
|
|
||||||
.withDefault(nullptr);
|
|
||||||
ASSERT_NE(pCam1, nullptr);
|
ASSERT_NE(pCam1, nullptr);
|
||||||
|
|
||||||
// Store a camera handle for a clean-up
|
// Store a camera handle for a clean-up
|
||||||
|
@ -2001,7 +2020,7 @@ TEST_P(EvsHidlTest, CameraUseStreamConfigToDisplay) {
|
||||||
&streamCfgs)) {
|
&streamCfgs)) {
|
||||||
// Stream configurations are found in metadata
|
// Stream configurations are found in metadata
|
||||||
RawStreamConfig *ptr = reinterpret_cast<RawStreamConfig *>(streamCfgs.data.i32);
|
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 &&
|
if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
|
||||||
ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
|
ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
|
||||||
|
|
||||||
|
@ -2026,9 +2045,7 @@ TEST_P(EvsHidlTest, CameraUseStreamConfigToDisplay) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
sp<IEvsCamera_1_1> pCam =
|
sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
|
||||||
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg))
|
|
||||||
.withDefault(nullptr);
|
|
||||||
ASSERT_NE(pCam, nullptr);
|
ASSERT_NE(pCam, nullptr);
|
||||||
|
|
||||||
// Store a camera handle for a clean-up
|
// Store a camera handle for a clean-up
|
||||||
|
@ -2106,7 +2123,7 @@ TEST_P(EvsHidlTest, MultiCameraStreamUseConfig) {
|
||||||
&streamCfgs)) {
|
&streamCfgs)) {
|
||||||
// Stream configurations are found in metadata
|
// Stream configurations are found in metadata
|
||||||
RawStreamConfig *ptr = reinterpret_cast<RawStreamConfig *>(streamCfgs.data.i32);
|
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 &&
|
if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
|
||||||
ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
|
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.
|
// Create the first camera client with a selected stream configuration.
|
||||||
sp<IEvsCamera_1_1> pCam0 =
|
sp<IEvsCamera_1_1> pCam0 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
|
||||||
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg))
|
|
||||||
.withDefault(nullptr);
|
|
||||||
ASSERT_NE(pCam0, nullptr);
|
ASSERT_NE(pCam0, nullptr);
|
||||||
|
|
||||||
// Store a camera handle for a clean-up
|
// Store a camera handle for a clean-up
|
||||||
|
@ -2144,9 +2159,7 @@ TEST_P(EvsHidlTest, MultiCameraStreamUseConfig) {
|
||||||
// configuration.
|
// configuration.
|
||||||
int32_t id = targetCfg.id;
|
int32_t id = targetCfg.id;
|
||||||
targetCfg.id += 1; // EVS manager sees only the stream id.
|
targetCfg.id += 1; // EVS manager sees only the stream id.
|
||||||
sp<IEvsCamera_1_1> pCam1 =
|
sp<IEvsCamera_1_1> pCam1 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
|
||||||
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg))
|
|
||||||
.withDefault(nullptr);
|
|
||||||
ASSERT_EQ(pCam1, nullptr);
|
ASSERT_EQ(pCam1, nullptr);
|
||||||
|
|
||||||
// Store a camera handle for a clean-up
|
// Store a camera handle for a clean-up
|
||||||
|
@ -2154,9 +2167,7 @@ TEST_P(EvsHidlTest, MultiCameraStreamUseConfig) {
|
||||||
|
|
||||||
// Try again with same stream configuration.
|
// Try again with same stream configuration.
|
||||||
targetCfg.id = id;
|
targetCfg.id = id;
|
||||||
pCam1 =
|
pCam1 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
|
||||||
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg))
|
|
||||||
.withDefault(nullptr);
|
|
||||||
ASSERT_NE(pCam1, nullptr);
|
ASSERT_NE(pCam1, nullptr);
|
||||||
|
|
||||||
// Set up per-client frame receiver objects which will fire up its own thread
|
// 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";
|
LOG(INFO) << "Starting CameraStreamExternalBuffering test";
|
||||||
|
|
||||||
// Arbitrary constant (should be > 1 and not too big)
|
// 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
|
// Get the camera list
|
||||||
loadCameraList();
|
loadCameraList();
|
||||||
|
|
||||||
// Using null stream configuration makes EVS uses the default resolution and
|
|
||||||
// output format.
|
|
||||||
Stream nullCfg = {};
|
|
||||||
|
|
||||||
// Acquire the graphics buffer allocator
|
// Acquire the graphics buffer allocator
|
||||||
android::GraphicBufferAllocator& alloc(android::GraphicBufferAllocator::get());
|
android::GraphicBufferAllocator& alloc(android::GraphicBufferAllocator::get());
|
||||||
const auto usage =
|
const auto usage =
|
||||||
GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_OFTEN;
|
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
|
// Test each reported camera
|
||||||
for (auto&& cam : cameraInfo) {
|
for (auto&& cam : cameraInfo) {
|
||||||
bool foundCfg = false;
|
// Read a target resolution from the metadata
|
||||||
if (!find_camera_metadata_entry(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()),
|
Stream targetCfg =
|
||||||
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
|
getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
|
||||||
&streamCfgs)) {
|
ASSERT_GT(targetCfg.width, 0);
|
||||||
// Stream configurations are found in metadata
|
ASSERT_GT(targetCfg.height, 0);
|
||||||
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.";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate buffers to use
|
// Allocate buffers to use
|
||||||
hidl_vec<BufferDesc> buffers;
|
hidl_vec<BufferDesc> buffers;
|
||||||
|
@ -2312,8 +2294,11 @@ TEST_P(EvsHidlTest, CameraStreamExternalBuffering) {
|
||||||
unsigned pixelsPerLine;
|
unsigned pixelsPerLine;
|
||||||
buffer_handle_t memHandle = nullptr;
|
buffer_handle_t memHandle = nullptr;
|
||||||
android::status_t result =
|
android::status_t result =
|
||||||
alloc.allocate(width, height, format, 1, usage, &memHandle, &pixelsPerLine, 0,
|
alloc.allocate(targetCfg.width, targetCfg.height,
|
||||||
"CameraStreamExternalBufferingTest");
|
(android::PixelFormat)targetCfg.format,
|
||||||
|
/* layerCount = */ 1, usage, &memHandle, &pixelsPerLine,
|
||||||
|
/* graphicBufferId = */ 0,
|
||||||
|
/* requestorName = */ "CameraStreamExternalBufferingTest");
|
||||||
if (result != android::NO_ERROR) {
|
if (result != android::NO_ERROR) {
|
||||||
LOG(ERROR) << __FUNCTION__ << " failed to allocate memory.";
|
LOG(ERROR) << __FUNCTION__ << " failed to allocate memory.";
|
||||||
// Release previous allocated buffers
|
// Release previous allocated buffers
|
||||||
|
@ -2325,10 +2310,10 @@ TEST_P(EvsHidlTest, CameraStreamExternalBuffering) {
|
||||||
BufferDesc buf;
|
BufferDesc buf;
|
||||||
AHardwareBuffer_Desc* pDesc =
|
AHardwareBuffer_Desc* pDesc =
|
||||||
reinterpret_cast<AHardwareBuffer_Desc*>(&buf.buffer.description);
|
reinterpret_cast<AHardwareBuffer_Desc*>(&buf.buffer.description);
|
||||||
pDesc->width = width;
|
pDesc->width = targetCfg.width;
|
||||||
pDesc->height = height;
|
pDesc->height = targetCfg.height;
|
||||||
pDesc->layers = 1;
|
pDesc->layers = 1;
|
||||||
pDesc->format = format;
|
pDesc->format = static_cast<uint32_t>(targetCfg.format);
|
||||||
pDesc->usage = usage;
|
pDesc->usage = usage;
|
||||||
pDesc->stride = pixelsPerLine;
|
pDesc->stride = pixelsPerLine;
|
||||||
buf.buffer.nativeHandle = memHandle;
|
buf.buffer.nativeHandle = memHandle;
|
||||||
|
@ -2340,9 +2325,7 @@ TEST_P(EvsHidlTest, CameraStreamExternalBuffering) {
|
||||||
bool isLogicalCam = false;
|
bool isLogicalCam = false;
|
||||||
getPhysicalCameraIds(cam.v1.cameraId, isLogicalCam);
|
getPhysicalCameraIds(cam.v1.cameraId, isLogicalCam);
|
||||||
|
|
||||||
sp<IEvsCamera_1_1> pCam =
|
sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
|
||||||
IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
|
|
||||||
.withDefault(nullptr);
|
|
||||||
ASSERT_NE(pCam, nullptr);
|
ASSERT_NE(pCam, nullptr);
|
||||||
|
|
||||||
// Store a camera handle for a clean-up
|
// Store a camera handle for a clean-up
|
||||||
|
@ -2362,7 +2345,7 @@ TEST_P(EvsHidlTest, CameraStreamExternalBuffering) {
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_EQ(result, EvsResult::OK);
|
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.
|
// Set up a frame receiver object which will fire up its own thread.
|
||||||
sp<FrameHandler> frameHandler = new FrameHandler(pCam, cam,
|
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
|
sleep(1); // 1 second should be enough for at least 5 frames to be delivered worst case
|
||||||
unsigned framesReceived = 0;
|
unsigned framesReceived = 0;
|
||||||
frameHandler->getFramesCounters(&framesReceived, nullptr);
|
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
|
// 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
|
// 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.
|
// filled since we require 10fps minimum -- but give a 10% allowance just in case.
|
||||||
|
unsigned framesReceivedAfter = 0;
|
||||||
usleep(110 * kMillisecondsToMicroseconds);
|
usleep(110 * kMillisecondsToMicroseconds);
|
||||||
frameHandler->getFramesCounters(&framesReceived, nullptr);
|
frameHandler->getFramesCounters(&framesReceivedAfter, nullptr);
|
||||||
EXPECT_EQ(kBuffersToHold+1, framesReceived) << "Stream should've resumed";
|
EXPECT_EQ(framesReceived + 1, framesReceivedAfter) << "Stream should've resumed";
|
||||||
|
|
||||||
// Even when the camera pointer goes out of scope, the FrameHandler object will
|
// Even when the camera pointer goes out of scope, the FrameHandler object will
|
||||||
// keep the stream alive unless we tell it to shutdown.
|
// keep the stream alive unless we tell it to shutdown.
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <fuzzer/FuzzedDataProvider.h>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
@ -21,36 +22,43 @@
|
||||||
#include "FormatConvert.h"
|
#include "FormatConvert.h"
|
||||||
|
|
||||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, std::size_t size) {
|
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;
|
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
|
// API have a requirement that width must be divied by 16 except yuyvtorgb
|
||||||
int random_variable = std::rand() % 10;
|
int min_height = 2;
|
||||||
int width = (int)sqrt(size);
|
int max_height = (image_pixel_size / 16) & ~(1); // must be even number
|
||||||
int height = width * ((float)random_variable / 10.0);
|
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);
|
uint8_t* src = (uint8_t*)(data + 4);
|
||||||
memcpy(src, data, sizeof(uint8_t) * (size));
|
uint32_t* tgt = (uint32_t*)malloc(sizeof(uint32_t) * image_pixel_size);
|
||||||
uint32_t* tgt = (uint32_t*)malloc(sizeof(uint32_t) * size);
|
|
||||||
|
|
||||||
#ifdef COPY_NV21_TO_RGB32
|
#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
|
#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
|
#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
|
#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
|
#elif COPY_YUYV_TO_RGB32
|
||||||
android::hardware::automotive::evs::common::Utils::copyYUYVtoRGB32(width, height, src, 0, tgt,
|
android::hardware::automotive::evs::common::Utils::copyYUYVtoRGB32(width, height, src, width,
|
||||||
0);
|
tgt, width);
|
||||||
#elif COPY_YUYV_TO_BGR32
|
#elif COPY_YUYV_TO_BGR32
|
||||||
android::hardware::automotive::evs::common::Utils::copyYUYVtoBGR32(width, height, src, 0, tgt,
|
android::hardware::automotive::evs::common::Utils::copyYUYVtoBGR32(width, height, src, width,
|
||||||
0);
|
tgt, width);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
free(src);
|
|
||||||
free(tgt);
|
free(tgt);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -182,6 +182,7 @@ cc_test {
|
||||||
],
|
],
|
||||||
shared_libs: [
|
shared_libs: [
|
||||||
"libbase",
|
"libbase",
|
||||||
|
"libcutils",
|
||||||
],
|
],
|
||||||
header_libs: ["libbase_headers"],
|
header_libs: ["libbase_headers"],
|
||||||
test_suites: ["general-tests"],
|
test_suites: ["general-tests"],
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
service vendor.vehicle-hal-2.0 /vendor/bin/hw/android.hardware.automotive.vehicle@2.0-service
|
service vendor.vehicle-hal-2.0 /vendor/bin/hw/android.hardware.automotive.vehicle@2.0-service
|
||||||
class hal
|
class early_hal
|
||||||
user vehicle_network
|
user vehicle_network
|
||||||
group system inet
|
group system inet
|
||||||
|
|
|
@ -76,6 +76,9 @@ public:
|
||||||
Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
|
Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Set unit test class as friend class to test private functions.
|
||||||
|
friend class VehicleHalManagerTestHelper;
|
||||||
|
|
||||||
using VehiclePropValuePtr = VehicleHal::VehiclePropValuePtr;
|
using VehiclePropValuePtr = VehicleHal::VehiclePropValuePtr;
|
||||||
// Returns true if needs to call again shortly.
|
// Returns true if needs to call again shortly.
|
||||||
using RetriableAction = std::function<bool()>;
|
using RetriableAction = std::function<bool()>;
|
||||||
|
@ -105,14 +108,20 @@ public:
|
||||||
void cmdDumpOneProperty(int fd, int32_t prop, int32_t areaId);
|
void cmdDumpOneProperty(int fd, int32_t prop, int32_t areaId);
|
||||||
void cmdDumpOneProperty(int fd, int rowNumber, const VehiclePropConfig& config);
|
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 checkArgumentsSize(int fd, const hidl_vec<hidl_string>& options, size_t minSize);
|
||||||
static bool checkCallerHasWritePermissions(int fd);
|
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 cmdHelp(int fd) const;
|
||||||
void cmdListAllProperties(int fd) const;
|
void cmdListAllProperties(int fd) const;
|
||||||
void cmdDumpAllProperties(int fd);
|
void cmdDumpAllProperties(int fd);
|
||||||
void cmdDumpSpecificProperties(int fd, const hidl_vec<hidl_string>& options);
|
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,
|
static bool isSubscribable(const VehiclePropConfig& config,
|
||||||
SubscribeFlags flags);
|
SubscribeFlags flags);
|
||||||
|
@ -120,7 +129,18 @@ public:
|
||||||
static float checkSampleRate(const VehiclePropConfig& config,
|
static float checkSampleRate(const VehiclePropConfig& config,
|
||||||
float sampleRate);
|
float sampleRate);
|
||||||
static ClientId getClientId(const sp<IVehicleCallback>& callback);
|
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;
|
VehicleHal* mHal;
|
||||||
std::unique_ptr<VehiclePropConfigIndex> mConfigIndex;
|
std::unique_ptr<VehiclePropConfigIndex> mConfigIndex;
|
||||||
SubscriptionManager mSubscriptionManager;
|
SubscriptionManager mSubscriptionManager;
|
||||||
|
|
|
@ -20,7 +20,9 @@
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
#include <android-base/parsedouble.h>
|
||||||
#include <android-base/parseint.h>
|
#include <android-base/parseint.h>
|
||||||
#include <android-base/strings.h>
|
#include <android-base/strings.h>
|
||||||
#include <android/hardware/automotive/vehicle/2.0/BpHwVehicleCallback.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_handle;
|
||||||
using ::android::hardware::hidl_string;
|
using ::android::hardware::hidl_string;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
constexpr std::chrono::milliseconds kHalEventBatchingTimeWindow(10);
|
constexpr std::chrono::milliseconds kHalEventBatchingTimeWindow(10);
|
||||||
|
|
||||||
const VehiclePropValue kEmptyValue{};
|
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
|
* Indicates what's the maximum size of hidl_vec<VehiclePropValue> we want
|
||||||
* to store in reusable object pool.
|
* to store in reusable object pool.
|
||||||
*/
|
*/
|
||||||
constexpr auto kMaxHidlVecOfVehiclPropValuePoolSize = 20;
|
constexpr auto kMaxHidlVecOfVehiclePropValuePoolSize = 20;
|
||||||
|
|
||||||
Return<void> VehicleHalManager::getAllPropConfigs(getAllPropConfigs_cb _hidl_cb) {
|
Return<void> VehicleHalManager::getAllPropConfigs(getAllPropConfigs_cb _hidl_cb) {
|
||||||
ALOGI("getAllPropConfigs called");
|
ALOGI("getAllPropConfigs called");
|
||||||
|
@ -213,6 +234,11 @@ void VehicleHalManager::cmdDump(int fd, const hidl_vec<hidl_string>& options) {
|
||||||
} else if (EqualsIgnoreCase(option, "--get")) {
|
} else if (EqualsIgnoreCase(option, "--get")) {
|
||||||
cmdDumpSpecificProperties(fd, options);
|
cmdDumpSpecificProperties(fd, options);
|
||||||
} else if (EqualsIgnoreCase(option, "--set")) {
|
} 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);
|
cmdSetOneProperty(fd, options);
|
||||||
} else {
|
} else {
|
||||||
dprintf(fd, "Invalid option: %s\n", option.c_str());
|
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;
|
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)) {
|
if (!android::base::ParseInt(s, out)) {
|
||||||
dprintf(fd, "non-integer argument at index %d: %s\n", index, s.c_str());
|
dprintf(fd, "non-integer argument at index %d: %s\n", index, s.c_str());
|
||||||
return false;
|
return false;
|
||||||
|
@ -247,19 +274,27 @@ bool VehicleHalManager::safelyParseInt(int fd, int index, std::string s, int* ou
|
||||||
return true;
|
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 {
|
void VehicleHalManager::cmdHelp(int fd) const {
|
||||||
dprintf(fd, "Usage: \n\n");
|
dprintf(fd, "Usage: \n\n");
|
||||||
dprintf(fd, "[no args]: dumps (id and value) all supported properties \n");
|
dprintf(fd, "[no args]: dumps (id and value) all supported properties \n");
|
||||||
dprintf(fd, "--help: shows this help\n");
|
dprintf(fd, "--help: shows this help\n");
|
||||||
dprintf(fd, "--list: lists the ids of all supported properties\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");
|
dprintf(fd, "--get <PROP1> [PROP2] [PROPN]: dumps the value of specific properties \n");
|
||||||
// TODO: support other formats (int64, float, bytes)
|
|
||||||
dprintf(fd,
|
dprintf(fd,
|
||||||
"--set <PROP> <i|s> <VALUE_1> [<i|s> <VALUE_N>] [a AREA_ID] : sets the value of "
|
"--set <PROP> [-i INT_VALUE [INT_VALUE ...]] [-i64 INT64_VALUE [INT64_VALUE ...]] "
|
||||||
"property PROP, using arbitrary number of key/value parameters (i for int32, "
|
"[-f FLOAT_VALUE [FLOAT_VALUE ...]] [-s STR_VALUE] "
|
||||||
"s for string) and an optional area.\n"
|
"[-b BYTES_VALUE] [-a AREA_ID] : sets the value of property PROP. "
|
||||||
"Notice that the string value can be set just once, while the other can have multiple "
|
"Notice that the string, bytes and area value can be set just once, while the other can"
|
||||||
"values (so they're used in the respective array)\n");
|
" 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 {
|
void VehicleHalManager::cmdListAllProperties(int fd) const {
|
||||||
|
@ -337,102 +372,49 @@ void VehicleHalManager::cmdDumpOneProperty(int fd, int32_t prop, int32_t areaId)
|
||||||
VehiclePropValue input;
|
VehiclePropValue input;
|
||||||
input.prop = prop;
|
input.prop = prop;
|
||||||
input.areaId = areaId;
|
input.areaId = areaId;
|
||||||
auto callback = [&](StatusCode status, const VehiclePropValue& output) {
|
auto callback = [&fd, &prop](StatusCode status, const VehiclePropValue& output) {
|
||||||
if (status == StatusCode::OK) {
|
if (status == StatusCode::OK) {
|
||||||
dprintf(fd, "%s\n", toString(output).c_str());
|
dprintf(fd, "%s\n", toString(output).c_str());
|
||||||
} else {
|
} else {
|
||||||
dprintf(fd, "Could not get property %d. Error: %s\n", prop, toString(status).c_str());
|
dprintf(fd, "Could not get property %d. Error: %s\n", prop, toString(status).c_str());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
get(input, callback);
|
|
||||||
|
StatusCode status;
|
||||||
|
auto value = mHal->get(input, &status);
|
||||||
|
callback(status, value.get() ? *value : kEmptyValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VehicleHalManager::cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options) {
|
bool VehicleHalManager::cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options) {
|
||||||
if (!checkCallerHasWritePermissions(fd) || !checkArgumentsSize(fd, options, 3)) return;
|
if (!checkArgumentsSize(fd, options, 4)) {
|
||||||
|
dprintf(fd, "Requires at least 4 options, see help\n");
|
||||||
size_t size = options.size();
|
return false;
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
int numberValues = (size - 2) / 2;
|
|
||||||
|
|
||||||
VehiclePropValue prop;
|
VehiclePropValue prop = {};
|
||||||
if (!safelyParseInt(fd, 1, options[1], &prop.prop)) return;
|
if (!parseSetPropOptions(fd, options, &prop)) {
|
||||||
prop.timestamp = elapsedRealtimeNano();
|
return false;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
ALOGD("Setting prop %s", toString(prop).c_str());
|
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) {
|
if (status == StatusCode::OK) {
|
||||||
dprintf(fd, "Set property %s\n", toString(prop).c_str());
|
dprintf(fd, "Set property %s\n", toString(prop).c_str());
|
||||||
} else {
|
return true;
|
||||||
dprintf(fd, "Failed to set property %s: %s\n", toString(prop).c_str(),
|
|
||||||
toString(status).c_str());
|
|
||||||
}
|
}
|
||||||
|
dprintf(fd, "Failed to set property %s: %s\n", toString(prop).c_str(),
|
||||||
|
toString(status).c_str());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VehicleHalManager::init() {
|
void VehicleHalManager::init() {
|
||||||
ALOGI("VehicleHalManager::init");
|
ALOGI("VehicleHalManager::init");
|
||||||
|
|
||||||
mHidlVecOfVehiclePropValuePool.resize(kMaxHidlVecOfVehiclPropValuePoolSize);
|
mHidlVecOfVehiclePropValuePool.resize(kMaxHidlVecOfVehiclePropValuePoolSize);
|
||||||
|
|
||||||
|
|
||||||
mBatchingConsumer.run(&mEventQueue,
|
mBatchingConsumer.run(&mEventQueue,
|
||||||
kHalEventBatchingTimeWindow,
|
kHalEventBatchingTimeWindow,
|
||||||
|
@ -486,7 +468,7 @@ void VehicleHalManager::onBatchHalEvent(const std::vector<VehiclePropValuePtr>&
|
||||||
for (const HalClientValues& cv : clientValues) {
|
for (const HalClientValues& cv : clientValues) {
|
||||||
auto vecSize = cv.values.size();
|
auto vecSize = cv.values.size();
|
||||||
hidl_vec<VehiclePropValue> vec;
|
hidl_vec<VehiclePropValue> vec;
|
||||||
if (vecSize < kMaxHidlVecOfVehiclPropValuePoolSize) {
|
if (vecSize < kMaxHidlVecOfVehiclePropValuePoolSize) {
|
||||||
vec.setToExternal(&mHidlVecOfVehiclePropValuePool[0], vecSize);
|
vec.setToExternal(&mHidlVecOfVehiclePropValuePool[0], vecSize);
|
||||||
} else {
|
} else {
|
||||||
vec.resize(vecSize);
|
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 V2_0
|
||||||
} // namespace vehicle
|
} // namespace vehicle
|
||||||
} // namespace automotive
|
} // namespace automotive
|
||||||
|
|
|
@ -307,6 +307,18 @@ const ConfigDeclaration kVehicleProperties[]{
|
||||||
.prop = toInt(VehicleProperty::CRITICALLY_LOW_TIRE_PRESSURE),
|
.prop = toInt(VehicleProperty::CRITICALLY_LOW_TIRE_PRESSURE),
|
||||||
.access = VehiclePropertyAccess::READ,
|
.access = VehiclePropertyAccess::READ,
|
||||||
.changeMode = VehiclePropertyChangeMode::STATIC,
|
.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}}},
|
.initialAreaValues = {{WHEEL_FRONT_LEFT, {.floatValues = {137.0f}}},
|
||||||
{WHEEL_FRONT_RIGHT, {.floatValues = {137.0f}}},
|
{WHEEL_FRONT_RIGHT, {.floatValues = {137.0f}}},
|
||||||
|
@ -1029,14 +1041,6 @@ const ConfigDeclaration kVehicleProperties[]{
|
||||||
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
|
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
.config =
|
|
||||||
{
|
|
||||||
.prop = toInt(VehicleProperty::STORAGE_ENCRYPTION_BINDING_SEED),
|
|
||||||
.access = VehiclePropertyAccess::READ_WRITE,
|
|
||||||
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
.config =
|
.config =
|
||||||
{
|
{
|
||||||
|
@ -1105,6 +1109,42 @@ const ConfigDeclaration kVehicleProperties[]{
|
||||||
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
|
.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
|
#ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
|
||||||
// Vendor propetry for E2E ClusterHomeService testing.
|
// Vendor propetry for E2E ClusterHomeService testing.
|
||||||
{
|
{
|
||||||
|
|
|
@ -189,6 +189,19 @@ enum class FakeDataCommand : int32_t {
|
||||||
KeyPress = 100,
|
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[] = {
|
const int32_t kHvacPowerProperties[] = {
|
||||||
toInt(VehicleProperty::HVAC_FAN_SPEED),
|
toInt(VehicleProperty::HVAC_FAN_SPEED),
|
||||||
toInt(VehicleProperty::HVAC_FAN_DIRECTION),
|
toInt(VehicleProperty::HVAC_FAN_DIRECTION),
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <android-base/macros.h>
|
#include <android-base/macros.h>
|
||||||
|
#include <cutils/native_handle.h>
|
||||||
#include <utils/SystemClock.h>
|
#include <utils/SystemClock.h>
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
@ -32,6 +33,18 @@ namespace automotive {
|
||||||
namespace vehicle {
|
namespace vehicle {
|
||||||
namespace V2_0 {
|
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 {
|
namespace {
|
||||||
|
|
||||||
using namespace std::placeholders;
|
using namespace std::placeholders;
|
||||||
|
@ -57,33 +70,21 @@ public:
|
||||||
auto property = static_cast<VehicleProperty>(requestedPropValue.prop);
|
auto property = static_cast<VehicleProperty>(requestedPropValue.prop);
|
||||||
int32_t areaId = requestedPropValue.areaId;
|
int32_t areaId = requestedPropValue.areaId;
|
||||||
|
|
||||||
switch (property) {
|
if (property == VehicleProperty::INFO_FUEL_CAPACITY) {
|
||||||
case VehicleProperty::INFO_MAKE:
|
if (fuelCapacityAttemptsLeft-- > 0) {
|
||||||
pValue = getValuePool()->obtainString(kCarMake);
|
// Emulate property not ready yet.
|
||||||
break;
|
*outStatus = StatusCode::TRY_AGAIN;
|
||||||
case VehicleProperty::INFO_FUEL_CAPACITY:
|
} else {
|
||||||
if (fuelCapacityAttemptsLeft-- > 0) {
|
pValue = getValuePool()->obtainFloat(42.42);
|
||||||
// Emulate property not ready yet.
|
}
|
||||||
*outStatus = StatusCode::TRY_AGAIN;
|
} else {
|
||||||
} else {
|
auto key = makeKey(requestedPropValue);
|
||||||
pValue = getValuePool()->obtainFloat(42.42);
|
if (mValues.count(key) == 0) {
|
||||||
}
|
ALOGW("key not found\n");
|
||||||
break;
|
*outStatus = StatusCode::INVALID_ARG;
|
||||||
default:
|
return pValue;
|
||||||
if (requestedPropValue.prop == kCustomComplexProperty) {
|
}
|
||||||
pValue = getValuePool()->obtainComplex();
|
pValue = getValuePool()->obtain(mValues[key]);
|
||||||
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 (*outStatus == StatusCode::OK && pValue.get() != nullptr) {
|
if (*outStatus == StatusCode::OK && pValue.get() != nullptr) {
|
||||||
|
@ -100,7 +101,6 @@ public:
|
||||||
&& mirrorFoldAttemptsLeft-- > 0) {
|
&& mirrorFoldAttemptsLeft-- > 0) {
|
||||||
return StatusCode::TRY_AGAIN;
|
return StatusCode::TRY_AGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
mValues[makeKey(propValue)] = propValue;
|
mValues[makeKey(propValue)] = propValue;
|
||||||
return StatusCode::OK;
|
return StatusCode::OK;
|
||||||
}
|
}
|
||||||
|
@ -181,6 +181,18 @@ public:
|
||||||
actualStatusCode = refStatus;
|
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:
|
public:
|
||||||
VehiclePropValue actualValue;
|
VehiclePropValue actualValue;
|
||||||
StatusCode actualStatusCode;
|
StatusCode actualStatusCode;
|
||||||
|
@ -308,6 +320,8 @@ TEST_F(VehicleHalManagerTest, subscribe_WriteOnly) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(VehicleHalManagerTest, get_Complex) {
|
TEST_F(VehicleHalManagerTest, get_Complex) {
|
||||||
|
ASSERT_EQ(StatusCode::OK, hal->set(*getComplexProperty().get()));
|
||||||
|
|
||||||
invokeGet(kCustomComplexProperty, 0);
|
invokeGet(kCustomComplexProperty, 0);
|
||||||
|
|
||||||
ASSERT_EQ(StatusCode::OK, actualStatusCode);
|
ASSERT_EQ(StatusCode::OK, actualStatusCode);
|
||||||
|
@ -334,6 +348,11 @@ TEST_F(VehicleHalManagerTest, get_Complex) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(VehicleHalManagerTest, get_StaticString) {
|
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);
|
invokeGet(toInt(VehicleProperty::INFO_MAKE), 0);
|
||||||
|
|
||||||
ASSERT_EQ(StatusCode::OK, actualStatusCode);
|
ASSERT_EQ(StatusCode::OK, actualStatusCode);
|
||||||
|
@ -458,6 +477,138 @@ TEST(HalClientVectorTest, basic) {
|
||||||
ASSERT_TRUE(clients.isEmpty());
|
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 anonymous
|
||||||
|
|
||||||
} // namespace V2_0
|
} // namespace V2_0
|
||||||
|
|
50
camera/metadata/3.7/types.hal
Normal file
50
camera/metadata/3.7/types.hal
Normal file
|
@ -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
|
||||||
|
*/
|
|
@ -882,6 +882,7 @@ public:
|
||||||
camera_metadata* oldSessionParams, camera_metadata* newSessionParams);
|
camera_metadata* oldSessionParams, camera_metadata* newSessionParams);
|
||||||
|
|
||||||
void verifyRequestTemplate(const camera_metadata_t* metadata, RequestTemplate requestTemplate);
|
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);
|
static bool isDepthOnly(const camera_metadata_t* staticMeta);
|
||||||
|
|
||||||
|
@ -935,6 +936,9 @@ public:
|
||||||
camera_metadata_ro_entry* streamConfigs,
|
camera_metadata_ro_entry* streamConfigs,
|
||||||
camera_metadata_ro_entry* maxResolutionStreamConfigs,
|
camera_metadata_ro_entry* maxResolutionStreamConfigs,
|
||||||
const camera_metadata_t* staticMetadata);
|
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);
|
static V3_2::DataspaceFlags getDataspace(PixelFormat format);
|
||||||
|
|
||||||
|
@ -4659,6 +4663,7 @@ void CameraHidlTest::processCaptureRequestInternal(uint64_t bufferUsage,
|
||||||
settings = req;
|
settings = req;
|
||||||
});
|
});
|
||||||
ASSERT_TRUE(ret.isOk());
|
ASSERT_TRUE(ret.isOk());
|
||||||
|
overrideRotateAndCrop(&settings);
|
||||||
|
|
||||||
hidl_handle buffer_handle;
|
hidl_handle buffer_handle;
|
||||||
StreamBuffer outputBuffer;
|
StreamBuffer outputBuffer;
|
||||||
|
@ -4835,6 +4840,7 @@ TEST_P(CameraHidlTest, processMultiCaptureRequestPreview) {
|
||||||
settings.setToExternal(
|
settings.setToExternal(
|
||||||
reinterpret_cast<uint8_t *> (const_cast<camera_metadata_t *> (settingsBuffer)),
|
reinterpret_cast<uint8_t *> (const_cast<camera_metadata_t *> (settingsBuffer)),
|
||||||
get_camera_metadata_size(settingsBuffer));
|
get_camera_metadata_size(settingsBuffer));
|
||||||
|
overrideRotateAndCrop(&settings);
|
||||||
|
|
||||||
free_camera_metadata(staticMeta);
|
free_camera_metadata(staticMeta);
|
||||||
ret = session->close();
|
ret = session->close();
|
||||||
|
@ -4912,6 +4918,7 @@ TEST_P(CameraHidlTest, processMultiCaptureRequestPreview) {
|
||||||
reinterpret_cast<uint8_t *> (const_cast<camera_metadata_t *> (
|
reinterpret_cast<uint8_t *> (const_cast<camera_metadata_t *> (
|
||||||
filteredSettingsBuffer)),
|
filteredSettingsBuffer)),
|
||||||
get_camera_metadata_size(filteredSettingsBuffer));
|
get_camera_metadata_size(filteredSettingsBuffer));
|
||||||
|
overrideRotateAndCrop(&camSettings[0].settings);
|
||||||
camSettings[0].fmqSettingsSize = 0;
|
camSettings[0].fmqSettingsSize = 0;
|
||||||
camSettings[0].physicalCameraId = physicalDeviceId;
|
camSettings[0].physicalCameraId = physicalDeviceId;
|
||||||
|
|
||||||
|
@ -5069,6 +5076,7 @@ TEST_P(CameraHidlTest, processUltraHighResolutionRequest) {
|
||||||
settings.setToExternal(
|
settings.setToExternal(
|
||||||
reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(settingsBuffer)),
|
reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(settingsBuffer)),
|
||||||
get_camera_metadata_size(settingsBuffer));
|
get_camera_metadata_size(settingsBuffer));
|
||||||
|
overrideRotateAndCrop(&settings);
|
||||||
|
|
||||||
free_camera_metadata(staticMeta);
|
free_camera_metadata(staticMeta);
|
||||||
ret = session->close();
|
ret = session->close();
|
||||||
|
@ -5304,6 +5312,7 @@ TEST_P(CameraHidlTest, processCaptureRequestBurstISO) {
|
||||||
camera_metadata_t *metaBuffer = requestMeta.release();
|
camera_metadata_t *metaBuffer = requestMeta.release();
|
||||||
requestSettings[i].setToExternal(reinterpret_cast<uint8_t *> (metaBuffer),
|
requestSettings[i].setToExternal(reinterpret_cast<uint8_t *> (metaBuffer),
|
||||||
get_camera_metadata_size(metaBuffer), true);
|
get_camera_metadata_size(metaBuffer), true);
|
||||||
|
overrideRotateAndCrop(&requestSettings[i]);
|
||||||
|
|
||||||
requests[i] = {frameNumber + i, 0 /* fmqSettingsSize */, requestSettings[i],
|
requests[i] = {frameNumber + i, 0 /* fmqSettingsSize */, requestSettings[i],
|
||||||
emptyInputBuffer, {outputBuffers[i]}};
|
emptyInputBuffer, {outputBuffers[i]}};
|
||||||
|
@ -5530,6 +5539,7 @@ TEST_P(CameraHidlTest, switchToOffline) {
|
||||||
camera_metadata_t *metaBuffer = requestMeta.release();
|
camera_metadata_t *metaBuffer = requestMeta.release();
|
||||||
requestSettings[i].setToExternal(reinterpret_cast<uint8_t *> (metaBuffer),
|
requestSettings[i].setToExternal(reinterpret_cast<uint8_t *> (metaBuffer),
|
||||||
get_camera_metadata_size(metaBuffer), true);
|
get_camera_metadata_size(metaBuffer), true);
|
||||||
|
overrideRotateAndCrop(&requestSettings[i]);
|
||||||
|
|
||||||
requests[i] = {frameNumber + i, 0 /* fmqSettingsSize */, requestSettings[i],
|
requests[i] = {frameNumber + i, 0 /* fmqSettingsSize */, requestSettings[i],
|
||||||
emptyInputBuffer, {outputBuffers[i]}};
|
emptyInputBuffer, {outputBuffers[i]}};
|
||||||
|
@ -5670,6 +5680,7 @@ TEST_P(CameraHidlTest, processCaptureRequestInvalidBuffer) {
|
||||||
settings = req;
|
settings = req;
|
||||||
});
|
});
|
||||||
ASSERT_TRUE(ret.isOk());
|
ASSERT_TRUE(ret.isOk());
|
||||||
|
overrideRotateAndCrop(&settings);
|
||||||
|
|
||||||
::android::hardware::hidl_vec<StreamBuffer> emptyOutputBuffers;
|
::android::hardware::hidl_vec<StreamBuffer> emptyOutputBuffers;
|
||||||
StreamBuffer emptyInputBuffer = {-1, 0, nullptr, BufferStatus::ERROR, nullptr,
|
StreamBuffer emptyInputBuffer = {-1, 0, nullptr, BufferStatus::ERROR, nullptr,
|
||||||
|
@ -5754,6 +5765,7 @@ TEST_P(CameraHidlTest, flushPreviewRequest) {
|
||||||
settings = req;
|
settings = req;
|
||||||
});
|
});
|
||||||
ASSERT_TRUE(ret.isOk());
|
ASSERT_TRUE(ret.isOk());
|
||||||
|
overrideRotateAndCrop(&settings);
|
||||||
|
|
||||||
hidl_handle buffer_handle;
|
hidl_handle buffer_handle;
|
||||||
if (useHalBufManager) {
|
if (useHalBufManager) {
|
||||||
|
@ -6617,6 +6629,25 @@ void CameraHidlTest::getMultiResolutionStreamConfigurations(
|
||||||
ASSERT_TRUE(-ENOENT == retcode || 0 == retcode);
|
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.
|
// Select an appropriate dataspace given a specific pixel format.
|
||||||
V3_2::DataspaceFlags CameraHidlTest::getDataspace(PixelFormat format) {
|
V3_2::DataspaceFlags CameraHidlTest::getDataspace(PixelFormat format) {
|
||||||
switch (format) {
|
switch (format) {
|
||||||
|
@ -7654,6 +7685,16 @@ void CameraHidlTest::verifyLogicalOrUltraHighResCameraMetadata(
|
||||||
ASSERT_TRUE(isUltraHighResCamera && !isMultiCamera);
|
ASSERT_TRUE(isUltraHighResCamera && !isMultiCamera);
|
||||||
physicalIds.insert(cameraId);
|
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
|
// 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> multiResOutputFormatCounterMap;
|
||||||
std::unordered_map<int32_t, size_t> multiResInputFormatCounterMap;
|
std::unordered_map<int32_t, size_t> multiResInputFormatCounterMap;
|
||||||
|
@ -7675,6 +7716,7 @@ void CameraHidlTest::verifyLogicalOrUltraHighResCameraMetadata(
|
||||||
camera_metadata_ro_entry physicalStreamConfigs;
|
camera_metadata_ro_entry physicalStreamConfigs;
|
||||||
camera_metadata_ro_entry physicalMaxResolutionStreamConfigs;
|
camera_metadata_ro_entry physicalMaxResolutionStreamConfigs;
|
||||||
bool isUltraHighRes = false;
|
bool isUltraHighRes = false;
|
||||||
|
std::unordered_set<int32_t> subCameraPrivacyTestPatterns;
|
||||||
if (isPublicId) {
|
if (isPublicId) {
|
||||||
::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> subDevice;
|
::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> subDevice;
|
||||||
Return<void> ret;
|
Return<void> ret;
|
||||||
|
@ -7705,6 +7747,8 @@ void CameraHidlTest::verifyLogicalOrUltraHighResCameraMetadata(
|
||||||
&physicalMultiResStreamConfigs, &physicalStreamConfigs,
|
&physicalMultiResStreamConfigs, &physicalStreamConfigs,
|
||||||
&physicalMaxResolutionStreamConfigs, staticMetadata);
|
&physicalMaxResolutionStreamConfigs, staticMetadata);
|
||||||
isUltraHighRes = isUltraHighResolution(staticMetadata);
|
isUltraHighRes = isUltraHighResolution(staticMetadata);
|
||||||
|
|
||||||
|
getPrivacyTestPatternModes(staticMetadata, &subCameraPrivacyTestPatterns);
|
||||||
});
|
});
|
||||||
ASSERT_TRUE(ret.isOk());
|
ASSERT_TRUE(ret.isOk());
|
||||||
} else {
|
} else {
|
||||||
|
@ -7731,6 +7775,7 @@ void CameraHidlTest::verifyLogicalOrUltraHighResCameraMetadata(
|
||||||
&physicalMultiResStreamConfigs, &physicalStreamConfigs,
|
&physicalMultiResStreamConfigs, &physicalStreamConfigs,
|
||||||
&physicalMaxResolutionStreamConfigs, staticMetadata);
|
&physicalMaxResolutionStreamConfigs, staticMetadata);
|
||||||
isUltraHighRes = isUltraHighResolution(staticMetadata);
|
isUltraHighRes = isUltraHighResolution(staticMetadata);
|
||||||
|
getPrivacyTestPatternModes(staticMetadata, &subCameraPrivacyTestPatterns);
|
||||||
});
|
});
|
||||||
ASSERT_TRUE(ret.isOk());
|
ASSERT_TRUE(ret.isOk());
|
||||||
|
|
||||||
|
@ -7747,6 +7792,10 @@ void CameraHidlTest::verifyLogicalOrUltraHighResCameraMetadata(
|
||||||
ASSERT_TRUE(ret.isOk());
|
ASSERT_TRUE(ret.isOk());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasTestPatternPhysicalRequestKey) {
|
||||||
|
ASSERT_TRUE(privacyTestPatternModes == subCameraPrivacyTestPatterns);
|
||||||
|
}
|
||||||
|
|
||||||
if (physicalMultiResStreamConfigs.count > 0) {
|
if (physicalMultiResStreamConfigs.count > 0) {
|
||||||
ASSERT_GE(deviceVersion, CAMERA_DEVICE_API_VERSION_3_7);
|
ASSERT_GE(deviceVersion, CAMERA_DEVICE_API_VERSION_3_7);
|
||||||
ASSERT_EQ(physicalMultiResStreamConfigs.count % 4, 0);
|
ASSERT_EQ(physicalMultiResStreamConfigs.count % 4, 0);
|
||||||
|
@ -7982,6 +8031,20 @@ void CameraHidlTest::verifyCameraCharacteristics(Status status, const CameraMeta
|
||||||
poseReference >= ANDROID_LENS_POSE_REFERENCE_PRIMARY_CAMERA);
|
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);
|
verifyExtendedSceneModeCharacteristics(metadata);
|
||||||
verifyZoomCharacteristics(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);
|
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CameraHidlTest);
|
||||||
INSTANTIATE_TEST_SUITE_P(
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
PerInstance, CameraHidlTest,
|
PerInstance, CameraHidlTest,
|
||||||
|
|
|
@ -901,6 +901,9 @@ c8a57364f6ad20842be14f4db284df5304f7521ca8eac6bcc1fa6c5b466fb8a6 android.hardwar
|
||||||
4a087a308608d146b022ebc15633de989f5f4dfe1491a83fa41763290a82e40d android.hardware.automotive.vehicle@2.0::types
|
4a087a308608d146b022ebc15633de989f5f4dfe1491a83fa41763290a82e40d android.hardware.automotive.vehicle@2.0::types
|
||||||
70eb14415391f835fb218b43a1e25f5d6495f098f96fa2acaea70985e98e1ce8 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
|
# ABI preserving changes to HALs during Android T
|
||||||
62ace52d9c3ff1f60f94118557a2aaf0b953513e59dcd34d5f94ae28d4c7e780 android.hardware.fastboot@1.0::IFastboot
|
62ace52d9c3ff1f60f94118557a2aaf0b953513e59dcd34d5f94ae28d4c7e780 android.hardware.fastboot@1.0::IFastboot
|
||||||
d0fb32f3ddeb9af7115ab32905225ea69b930d2472be8e9610f0cf136c15aefb android.hardware.keymaster@4.0::IKeymasterDevice # b/210424594
|
d0fb32f3ddeb9af7115ab32905225ea69b930d2472be8e9610f0cf136c15aefb android.hardware.keymaster@4.0::IKeymasterDevice # b/210424594
|
||||||
|
|
|
@ -28,6 +28,8 @@
|
||||||
#include "wifi_chip.h"
|
#include "wifi_chip.h"
|
||||||
#include "wifi_status_util.h"
|
#include "wifi_status_util.h"
|
||||||
|
|
||||||
|
#define P2P_MGMT_DEVICE_PREFIX "p2p-dev-"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
using android::sp;
|
using android::sp;
|
||||||
using android::base::unique_fd;
|
using android::base::unique_fd;
|
||||||
|
@ -126,8 +128,37 @@ std::vector<std::string> getPredefinedApIfaceNames(bool is_bridged) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getPredefinedP2pIfaceName() {
|
std::string getPredefinedP2pIfaceName() {
|
||||||
|
std::array<char, PROPERTY_VALUE_MAX> primaryIfaceName;
|
||||||
|
char p2pParentIfname[100];
|
||||||
|
std::string p2pDevIfName = "";
|
||||||
std::array<char, PROPERTY_VALUE_MAX> buffer;
|
std::array<char, PROPERTY_VALUE_MAX> buffer;
|
||||||
property_get("wifi.direct.interface", buffer.data(), "p2p0");
|
property_get("wifi.direct.interface", buffer.data(), "p2p0");
|
||||||
|
if (strncmp(buffer.data(), P2P_MGMT_DEVICE_PREFIX,
|
||||||
|
strlen(P2P_MGMT_DEVICE_PREFIX)) == 0) {
|
||||||
|
/* Get the p2p parent interface name from p2p device interface name set
|
||||||
|
* in property */
|
||||||
|
strncpy(p2pParentIfname, buffer.data() + strlen(P2P_MGMT_DEVICE_PREFIX),
|
||||||
|
strlen(buffer.data()) - strlen(P2P_MGMT_DEVICE_PREFIX));
|
||||||
|
if (property_get(kActiveWlanIfaceNameProperty, primaryIfaceName.data(),
|
||||||
|
nullptr) == 0) {
|
||||||
|
return buffer.data();
|
||||||
|
}
|
||||||
|
/* Check if the parent interface derived from p2p device interface name
|
||||||
|
* is active */
|
||||||
|
if (strncmp(p2pParentIfname, primaryIfaceName.data(),
|
||||||
|
strlen(buffer.data()) - strlen(P2P_MGMT_DEVICE_PREFIX)) !=
|
||||||
|
0) {
|
||||||
|
/*
|
||||||
|
* Update the predefined p2p device interface parent interface name
|
||||||
|
* with current active wlan interface
|
||||||
|
*/
|
||||||
|
p2pDevIfName += P2P_MGMT_DEVICE_PREFIX;
|
||||||
|
p2pDevIfName += primaryIfaceName.data();
|
||||||
|
LOG(INFO) << "update the p2p device interface name to "
|
||||||
|
<< p2pDevIfName.c_str();
|
||||||
|
return p2pDevIfName;
|
||||||
|
}
|
||||||
|
}
|
||||||
return buffer.data();
|
return buffer.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -318,7 +318,7 @@ bool turnOnExcessiveLogging(const sp<ISupplicant>& supplicant) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool waitForFrameworkReady() {
|
bool waitForFrameworkReady() {
|
||||||
int waitCount = 10;
|
int waitCount = 15;
|
||||||
do {
|
do {
|
||||||
// Check whether package service is ready or not.
|
// Check whether package service is ready or not.
|
||||||
if (!testing::checkSubstringInCommandOutput(
|
if (!testing::checkSubstringInCommandOutput(
|
||||||
|
|
|
@ -77,7 +77,6 @@ cc_test {
|
||||||
"general-tests",
|
"general-tests",
|
||||||
"vts",
|
"vts",
|
||||||
],
|
],
|
||||||
disable_framework: true,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cc_test {
|
cc_test {
|
||||||
|
@ -108,5 +107,4 @@ cc_test {
|
||||||
"general-tests",
|
"general-tests",
|
||||||
"vts",
|
"vts",
|
||||||
],
|
],
|
||||||
disable_framework: true,
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue