Merge sc-v2-dev-plus-aosp-without-vendor@8084891

Bug: 214455710
Merged-In: Id9e06f88539b59480d5cf57a4ba67cef4676c1d5
Change-Id: Id6b1ea4f8700446b044255e80f21c137aeb7acf1
This commit is contained in:
Xin Li 2022-02-11 07:27:13 +00:00
commit 0bf8f21279
19 changed files with 857 additions and 292 deletions

View file

@ -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",
], ],

View file

@ -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();
} }

View file

@ -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"],
} }

View file

@ -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>

View file

@ -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.

View file

@ -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;

View file

@ -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"],

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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.
{ {

View file

@ -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),

View file

@ -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

View 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
*/

View file

@ -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,

View file

@ -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

View file

@ -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();
} }

View file

@ -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(

View file

@ -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,
} }