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