Merge "Remove remoteaccess V1 impl." into main
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index 3117134..819b3c5 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -1277,6 +1277,12 @@
mmapSources.insert(port.id);
}
}
+ if (mmapSources.empty() && mmapSinks.empty()) {
+ AudioMMapPolicyInfo never;
+ never.mmapPolicy = AudioMMapPolicy::NEVER;
+ _aidl_return->push_back(never);
+ return ndk::ScopedAStatus::ok();
+ }
for (const auto& route : getConfig().routes) {
if (mmapSinks.count(route.sinkPortId) != 0) {
// The sink is a mix port, add the sources if they are device ports.
diff --git a/audio/aidl/default/alsa/ModuleAlsa.cpp b/audio/aidl/default/alsa/ModuleAlsa.cpp
index 8e75d56..8512631 100644
--- a/audio/aidl/default/alsa/ModuleAlsa.cpp
+++ b/audio/aidl/default/alsa/ModuleAlsa.cpp
@@ -39,13 +39,14 @@
if (!deviceProfile.has_value()) {
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
- auto profile = alsa::readAlsaDeviceInfo(*deviceProfile);
- if (!profile.has_value()) {
+ auto proxy = alsa::readAlsaDeviceInfo(*deviceProfile);
+ if (proxy.get() == nullptr) {
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
- std::vector<AudioChannelLayout> channels = alsa::getChannelMasksFromProfile(&profile.value());
- std::vector<int> sampleRates = alsa::getSampleRatesFromProfile(&profile.value());
+ alsa_device_profile* profile = proxy.getProfile();
+ std::vector<AudioChannelLayout> channels = alsa::getChannelMasksFromProfile(profile);
+ std::vector<int> sampleRates = alsa::getSampleRatesFromProfile(profile);
for (size_t i = 0; i < std::min(MAX_PROFILE_FORMATS, AUDIO_PORT_MAX_AUDIO_PROFILES) &&
profile->formats[i] != PCM_FORMAT_INVALID;
diff --git a/audio/aidl/default/alsa/StreamAlsa.cpp b/audio/aidl/default/alsa/StreamAlsa.cpp
index 0605d6f..403b94b 100644
--- a/audio/aidl/default/alsa/StreamAlsa.cpp
+++ b/audio/aidl/default/alsa/StreamAlsa.cpp
@@ -83,7 +83,7 @@
proxy = alsa::openProxyForAttachedDevice(
device, const_cast<struct pcm_config*>(&mConfig.value()), mBufferSizeFrames);
}
- if (!proxy) {
+ if (proxy.get() == nullptr) {
return ::android::NO_INIT;
}
alsaDeviceProxies.push_back(std::move(proxy));
diff --git a/audio/aidl/default/alsa/Utils.cpp b/audio/aidl/default/alsa/Utils.cpp
index 9dcd024..c08836c 100644
--- a/audio/aidl/default/alsa/Utils.cpp
+++ b/audio/aidl/default/alsa/Utils.cpp
@@ -37,6 +37,23 @@
namespace aidl::android::hardware::audio::core::alsa {
+DeviceProxy::DeviceProxy() : mProfile(nullptr), mProxy(nullptr, alsaProxyDeleter) {}
+
+DeviceProxy::DeviceProxy(const DeviceProfile& deviceProfile)
+ : mProfile(new alsa_device_profile), mProxy(new alsa_device_proxy, alsaProxyDeleter) {
+ profile_init(mProfile.get(), deviceProfile.direction);
+ mProfile->card = deviceProfile.card;
+ mProfile->device = deviceProfile.device;
+ memset(mProxy.get(), 0, sizeof(alsa_device_proxy));
+}
+
+void DeviceProxy::alsaProxyDeleter(alsa_device_proxy* proxy) {
+ if (proxy != nullptr) {
+ proxy_close(proxy);
+ delete proxy;
+ }
+}
+
namespace {
using AudioChannelCountToMaskMap = std::map<unsigned int, AudioChannelLayout>;
@@ -261,39 +278,24 @@
return sampleRates;
}
-DeviceProxy makeDeviceProxy() {
- DeviceProxy proxy(new alsa_device_proxy, [](alsa_device_proxy* proxy) {
- if (proxy != nullptr) {
- proxy_close(proxy);
- delete proxy;
- }
- });
- memset(proxy.get(), 0, sizeof(alsa_device_proxy));
- return proxy;
-}
-
DeviceProxy openProxyForAttachedDevice(const DeviceProfile& deviceProfile,
struct pcm_config* pcmConfig, size_t bufferFrameCount) {
if (deviceProfile.isExternal) {
LOG(FATAL) << __func__ << ": called for an external device, address=" << deviceProfile;
}
- alsa_device_profile profile;
- profile_init(&profile, deviceProfile.direction);
- profile.card = deviceProfile.card;
- profile.device = deviceProfile.device;
- if (!profile_fill_builtin_device_info(&profile, pcmConfig, bufferFrameCount)) {
+ DeviceProxy proxy(deviceProfile);
+ if (!profile_fill_builtin_device_info(proxy.getProfile(), pcmConfig, bufferFrameCount)) {
LOG(FATAL) << __func__ << ": failed to init for built-in device, address=" << deviceProfile;
}
- auto proxy = makeDeviceProxy();
- if (int err = proxy_prepare_from_default_config(proxy.get(), &profile); err != 0) {
+ if (int err = proxy_prepare_from_default_config(proxy.get(), proxy.getProfile()); err != 0) {
LOG(FATAL) << __func__ << ": fail to prepare for device address=" << deviceProfile
<< " error=" << err;
- return nullptr;
+ return DeviceProxy();
}
if (int err = proxy_open(proxy.get()); err != 0) {
LOG(ERROR) << __func__ << ": failed to open device, address=" << deviceProfile
<< " error=" << err;
- return nullptr;
+ return DeviceProxy();
}
return proxy;
}
@@ -303,42 +305,36 @@
if (!deviceProfile.isExternal) {
LOG(FATAL) << __func__ << ": called for an attached device, address=" << deviceProfile;
}
- auto profile = readAlsaDeviceInfo(deviceProfile);
- if (!profile.has_value()) {
- LOG(ERROR) << __func__ << ": unable to read device info, device address=" << deviceProfile;
- return nullptr;
+ auto proxy = readAlsaDeviceInfo(deviceProfile);
+ if (proxy.get() == nullptr) {
+ return proxy;
}
- auto proxy = makeDeviceProxy();
- if (int err = proxy_prepare(proxy.get(), &profile.value(), pcmConfig, requireExactMatch);
+ if (int err = proxy_prepare(proxy.get(), proxy.getProfile(), pcmConfig, requireExactMatch);
err != 0) {
LOG(ERROR) << __func__ << ": fail to prepare for device address=" << deviceProfile
<< " error=" << err;
- return nullptr;
+ return DeviceProxy();
}
if (int err = proxy_open(proxy.get()); err != 0) {
LOG(ERROR) << __func__ << ": failed to open device, address=" << deviceProfile
<< " error=" << err;
- return nullptr;
+ return DeviceProxy();
}
return proxy;
}
-std::optional<alsa_device_profile> readAlsaDeviceInfo(const DeviceProfile& deviceProfile) {
- alsa_device_profile profile;
- profile_init(&profile, deviceProfile.direction);
- profile.card = deviceProfile.card;
- profile.device = deviceProfile.device;
- if (!profile_read_device_info(&profile)) {
- LOG(ERROR) << __func__ << ": failed to read device info, card=" << profile.card
- << ", device=" << profile.device;
- return std::nullopt;
+DeviceProxy readAlsaDeviceInfo(const DeviceProfile& deviceProfile) {
+ DeviceProxy proxy(deviceProfile);
+ if (!profile_read_device_info(proxy.getProfile())) {
+ LOG(ERROR) << __func__ << ": unable to read device info, device address=" << deviceProfile;
+ return DeviceProxy();
}
- return profile;
+ return proxy;
}
void resetTransferredFrames(DeviceProxy& proxy, uint64_t frames) {
- if (proxy != nullptr) {
- proxy->transferred = frames;
+ if (proxy.get() != nullptr) {
+ proxy.get()->transferred = frames;
}
}
diff --git a/audio/aidl/default/alsa/Utils.h b/audio/aidl/default/alsa/Utils.h
index 37414b3..980f685 100644
--- a/audio/aidl/default/alsa/Utils.h
+++ b/audio/aidl/default/alsa/Utils.h
@@ -43,8 +43,21 @@
bool isExternal;
};
std::ostream& operator<<(std::ostream& os, const DeviceProfile& device);
-using DeviceProxyDeleter = std::function<void(alsa_device_proxy*)>;
-using DeviceProxy = std::unique_ptr<alsa_device_proxy, DeviceProxyDeleter>;
+
+class DeviceProxy {
+ public:
+ DeviceProxy(); // Constructs a "null" proxy.
+ explicit DeviceProxy(const DeviceProfile& deviceProfile);
+ alsa_device_profile* getProfile() { return mProfile.get(); }
+ alsa_device_proxy* get() { return mProxy.get(); }
+
+ private:
+ static void alsaProxyDeleter(alsa_device_proxy* proxy);
+ using AlsaProxy = std::unique_ptr<alsa_device_proxy, decltype(alsaProxyDeleter)*>;
+
+ std::unique_ptr<alsa_device_profile> mProfile;
+ AlsaProxy mProxy;
+};
::aidl::android::media::audio::common::AudioChannelLayout getChannelLayoutMaskFromChannelCount(
unsigned int channelCount, int isInput);
@@ -60,12 +73,11 @@
const ::aidl::android::media::audio::common::AudioPort& audioPort);
std::optional<struct pcm_config> getPcmConfig(const StreamContext& context, bool isInput);
std::vector<int> getSampleRatesFromProfile(const alsa_device_profile* profile);
-DeviceProxy makeDeviceProxy();
DeviceProxy openProxyForAttachedDevice(const DeviceProfile& deviceProfile,
struct pcm_config* pcmConfig, size_t bufferFrameCount);
DeviceProxy openProxyForExternalDevice(const DeviceProfile& deviceProfile,
struct pcm_config* pcmConfig, bool requireExactMatch);
-std::optional<alsa_device_profile> readAlsaDeviceInfo(const DeviceProfile& deviceProfile);
+DeviceProxy readAlsaDeviceInfo(const DeviceProfile& deviceProfile);
void resetTransferredFrames(DeviceProxy& proxy, uint64_t frames);
::aidl::android::media::audio::common::AudioFormatDescription
diff --git a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
index ccf7cfc..a4670db 100644
--- a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
@@ -87,6 +87,7 @@
using aidl::android::media::audio::common::AudioFormatType;
using aidl::android::media::audio::common::AudioIoFlags;
using aidl::android::media::audio::common::AudioLatencyMode;
+using aidl::android::media::audio::common::AudioMMapPolicy;
using aidl::android::media::audio::common::AudioMMapPolicyInfo;
using aidl::android::media::audio::common::AudioMMapPolicyType;
using aidl::android::media::audio::common::AudioMode;
@@ -2133,7 +2134,13 @@
std::vector<AudioMMapPolicyInfo> policyInfos;
EXPECT_IS_OK(module->getMmapPolicyInfos(mmapPolicyType, &policyInfos))
<< toString(mmapPolicyType);
- EXPECT_EQ(isMmapSupported, !policyInfos.empty());
+ const bool isMMapSupportedByPolicyInfos =
+ std::find_if(policyInfos.begin(), policyInfos.end(), [](const auto& info) {
+ return info.mmapPolicy == AudioMMapPolicy::AUTO ||
+ info.mmapPolicy == AudioMMapPolicy::ALWAYS;
+ }) != policyInfos.end();
+ EXPECT_EQ(isMmapSupported, isMMapSupportedByPolicyInfos)
+ << ::android::internal::ToString(policyInfos);
}
}
@@ -4172,58 +4179,32 @@
class WithRemoteSubmix {
public:
WithRemoteSubmix() = default;
- WithRemoteSubmix(AudioDeviceAddress address) : mAddress(address) {}
+ explicit WithRemoteSubmix(AudioDeviceAddress address) : mAddress(address) {}
WithRemoteSubmix(const WithRemoteSubmix&) = delete;
WithRemoteSubmix& operator=(const WithRemoteSubmix&) = delete;
- std::optional<AudioPort> getAudioPort() {
+ static std::optional<AudioPort> getRemoteSubmixAudioPort(
+ ModuleConfig* moduleConfig,
+ const std::optional<AudioDeviceAddress>& address = std::nullopt) {
AudioDeviceType deviceType = IOTraits<Stream>::is_input ? AudioDeviceType::IN_SUBMIX
: AudioDeviceType::OUT_SUBMIX;
- auto ports = mModuleConfig->getAudioPortsForDeviceTypes(
+ auto ports = moduleConfig->getAudioPortsForDeviceTypes(
std::vector<AudioDeviceType>{deviceType},
AudioDeviceDescription::CONNECTION_VIRTUAL);
- if (!ports.empty()) return ports.front();
- return {};
- }
- /* Connect remote submix external device */
- void SetUpPortConnection() {
- auto port = getAudioPort();
- ASSERT_TRUE(port.has_value()) << "Device AudioPort for remote submix not found";
- if (mAddress.has_value()) {
- port.value().ext.template get<AudioPortExt::Tag::device>().device.address =
- mAddress.value();
+ if (ports.empty()) return {};
+ AudioPort port = ports.front();
+ if (address) {
+ port.ext.template get<AudioPortExt::Tag::device>().device.address = address.value();
} else {
- port = GenerateUniqueDeviceAddress(port.value());
+ port = GenerateUniqueDeviceAddress(port);
}
- mConnectedPort = std::make_unique<WithDevicePortConnectedState>(port.value());
- ASSERT_NO_FATAL_FAILURE(mConnectedPort->SetUp(mModule, mModuleConfig));
+ return port;
}
- AudioDeviceAddress getAudioDeviceAddress() {
- if (!mAddress.has_value()) {
- mAddress = mConnectedPort->get()
- .ext.template get<AudioPortExt::Tag::device>()
- .device.address;
- }
- return mAddress.value();
- }
- /* Get mix port config for stream and setup patch for it. */
- void SetupPatch() {
- const auto portConfig =
- mModuleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
- if (!portConfig.has_value()) {
- LOG(DEBUG) << __func__ << ": portConfig not found";
- mSkipTest = true;
- return;
- }
- auto devicePortConfig = mModuleConfig->getSingleConfigForDevicePort(mConnectedPort->get());
- mPatch = std::make_unique<WithAudioPatch>(IOTraits<Stream>::is_input, portConfig.value(),
- devicePortConfig);
- ASSERT_NO_FATAL_FAILURE(mPatch->SetUp(mModule));
- }
- void SetUp(IModule* module, ModuleConfig* moduleConfig) {
+ std::optional<AudioDeviceAddress> getAudioDeviceAddress() const { return mAddress; }
+ void SetUp(IModule* module, ModuleConfig* moduleConfig, const AudioPort& connectedPort) {
mModule = module;
mModuleConfig = moduleConfig;
- ASSERT_NO_FATAL_FAILURE(SetUpPortConnection());
- ASSERT_NO_FATAL_FAILURE(SetupPatch());
+
+ ASSERT_NO_FATAL_FAILURE(SetupPatch(connectedPort));
if (!mSkipTest) {
// open stream
mStream = std::make_unique<WithStream<Stream>>(
@@ -4231,6 +4212,11 @@
ASSERT_NO_FATAL_FAILURE(
mStream->SetUp(mModule, AudioCoreModuleBase::kDefaultBufferSizeFrames));
}
+ mAddress = connectedPort.ext.template get<AudioPortExt::Tag::device>().device.address;
+ }
+ void SetUp(IModule* module, ModuleConfig* moduleConfig) {
+ ASSERT_NO_FATAL_FAILURE(SetUpPortConnection(module, moduleConfig));
+ SetUp(module, moduleConfig, mConnectedPort->get());
}
void sendBurstCommands() {
const StreamContext* context = mStream->getContext();
@@ -4248,9 +4234,31 @@
}
EXPECT_FALSE(driver.hasRetrogradeObservablePosition());
}
- bool skipTest() { return mSkipTest; }
+ bool skipTest() const { return mSkipTest; }
private:
+ /* Connect remote submix external device */
+ void SetUpPortConnection(IModule* module, ModuleConfig* moduleConfig) {
+ auto port = getRemoteSubmixAudioPort(moduleConfig, mAddress);
+ ASSERT_TRUE(port.has_value()) << "Device AudioPort for remote submix not found";
+ mConnectedPort = std::make_unique<WithDevicePortConnectedState>(port.value());
+ ASSERT_NO_FATAL_FAILURE(mConnectedPort->SetUp(module, moduleConfig));
+ }
+ /* Get mix port config for stream and setup patch for it. */
+ void SetupPatch(const AudioPort& connectedPort) {
+ const auto portConfig =
+ mModuleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
+ if (!portConfig.has_value()) {
+ LOG(DEBUG) << __func__ << ": portConfig not found";
+ mSkipTest = true;
+ return;
+ }
+ auto devicePortConfig = mModuleConfig->getSingleConfigForDevicePort(connectedPort);
+ mPatch = std::make_unique<WithAudioPatch>(IOTraits<Stream>::is_input, portConfig.value(),
+ devicePortConfig);
+ ASSERT_NO_FATAL_FAILURE(mPatch->SetUp(mModule));
+ }
+
bool mSkipTest = false;
IModule* mModule = nullptr;
ModuleConfig* mModuleConfig = nullptr;
@@ -4288,9 +4296,11 @@
if (streamOut.skipTest()) {
GTEST_SKIP() << "No mix port for attached devices";
}
+ auto address = streamOut.getAudioDeviceAddress();
+ ASSERT_TRUE(address.has_value());
// open input stream
- WithRemoteSubmix<IStreamIn> streamIn(streamOut.getAudioDeviceAddress());
+ WithRemoteSubmix<IStreamIn> streamIn(address.value());
ASSERT_NO_FATAL_FAILURE(streamIn.SetUp(module.get(), moduleConfig.get()));
if (streamIn.skipTest()) {
GTEST_SKIP() << "No mix port for attached devices";
@@ -4307,9 +4317,11 @@
if (streamOut.skipTest()) {
GTEST_SKIP() << "No mix port for attached devices";
}
+ auto address = streamOut.getAudioDeviceAddress();
+ ASSERT_TRUE(address.has_value());
// open input stream
- WithRemoteSubmix<IStreamIn> streamIn(streamOut.getAudioDeviceAddress());
+ WithRemoteSubmix<IStreamIn> streamIn(address.value());
ASSERT_NO_FATAL_FAILURE(streamIn.SetUp(module.get(), moduleConfig.get()));
if (streamIn.skipTest()) {
GTEST_SKIP() << "No mix port for attached devices";
@@ -4321,6 +4333,43 @@
ASSERT_NO_FATAL_FAILURE(streamIn.sendBurstCommands());
}
+TEST_P(AudioModuleRemoteSubmix, OpenInputMultipleTimes) {
+ // open output stream
+ WithRemoteSubmix<IStreamOut> streamOut;
+ ASSERT_NO_FATAL_FAILURE(streamOut.SetUp(module.get(), moduleConfig.get()));
+ if (streamOut.skipTest()) {
+ GTEST_SKIP() << "No mix port for attached devices";
+ }
+ auto address = streamOut.getAudioDeviceAddress();
+ ASSERT_TRUE(address.has_value());
+
+ // connect remote submix input device port
+ auto port = WithRemoteSubmix<IStreamIn>::getRemoteSubmixAudioPort(moduleConfig.get(),
+ address.value());
+ ASSERT_TRUE(port.has_value()) << "Device AudioPort for remote submix not found";
+ WithDevicePortConnectedState connectedInputPort(port.value());
+ ASSERT_NO_FATAL_FAILURE(connectedInputPort.SetUp(module.get(), moduleConfig.get()));
+
+ // open input streams
+ const int streamInCount = 3;
+ std::vector<std::unique_ptr<WithRemoteSubmix<IStreamIn>>> streamIns(streamInCount);
+ for (int i = 0; i < streamInCount; i++) {
+ streamIns[i] = std::make_unique<WithRemoteSubmix<IStreamIn>>();
+ ASSERT_NO_FATAL_FAILURE(
+ streamIns[i]->SetUp(module.get(), moduleConfig.get(), connectedInputPort.get()));
+ if (streamIns[i]->skipTest()) {
+ GTEST_SKIP() << "No mix port for attached devices";
+ }
+ }
+ // write something to output stream
+ ASSERT_NO_FATAL_FAILURE(streamOut.sendBurstCommands());
+
+ // read from input streams
+ for (int i = 0; i < streamInCount; i++) {
+ ASSERT_NO_FATAL_FAILURE(streamIns[i]->sendBurstCommands());
+ }
+}
+
INSTANTIATE_TEST_SUITE_P(AudioModuleRemoteSubmixTest, AudioModuleRemoteSubmix,
::testing::ValuesIn(getRemoteSubmixModuleInstance()));
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioModuleRemoteSubmix);
diff --git a/automotive/evs/aidl/impl/default/include/EvsAllCameras.h b/automotive/evs/aidl/impl/default/include/EvsAllCameras.h
new file mode 100644
index 0000000..a76501d
--- /dev/null
+++ b/automotive/evs/aidl/impl/default/include/EvsAllCameras.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include "EvsMockCamera.h"
+#include "EvsVideoEmulatedCamera.h"
diff --git a/automotive/evs/aidl/impl/default/include/EvsCamera.h b/automotive/evs/aidl/impl/default/include/EvsCamera.h
index 5774db5..539d5f6 100644
--- a/automotive/evs/aidl/impl/default/include/EvsCamera.h
+++ b/automotive/evs/aidl/impl/default/include/EvsCamera.h
@@ -85,7 +85,7 @@
void closeAllBuffers_unsafe();
- // Returns (ID, handle) if succeeds. (static_cast<size_t>(-1), nullptr) otherwise.
+ // Returns (ID, handle) if succeeds. (kInvalidBufferID, nullptr) otherwise.
[[nodiscard]] std::pair<std::size_t, buffer_handle_t> useBuffer_unsafe();
void returnBuffer_unsafe(const std::size_t id);
@@ -133,6 +133,12 @@
std::size_t mAvailableFrames{0};
std::size_t mFramesInUse{0};
+
+ // We use all 1's as a reserved invalid buffer ID.
+ static constexpr std::size_t kInvalidBufferID = ~static_cast<std::size_t>(0);
+
+ public:
+ static bool IsBufferIDValid(const std::size_t bufferId) { return ~bufferId; }
};
} // namespace aidl::android::hardware::automotive::evs::implementation
diff --git a/automotive/evs/aidl/impl/default/include/EvsMockCamera.h b/automotive/evs/aidl/impl/default/include/EvsMockCamera.h
index c7b9e0f..cd68532 100644
--- a/automotive/evs/aidl/impl/default/include/EvsMockCamera.h
+++ b/automotive/evs/aidl/impl/default/include/EvsMockCamera.h
@@ -17,29 +17,36 @@
#pragma once
#include "ConfigManager.h"
-#include "EvsCameraBase.h"
+#include "EvsCamera.h"
-#include <aidl/android/hardware/automotive/evs/BufferDesc.h>
#include <aidl/android/hardware/automotive/evs/CameraDesc.h>
#include <aidl/android/hardware/automotive/evs/CameraParam.h>
-#include <aidl/android/hardware/automotive/evs/EvsResult.h>
#include <aidl/android/hardware/automotive/evs/IEvsCameraStream.h>
#include <aidl/android/hardware/automotive/evs/IEvsDisplay.h>
#include <aidl/android/hardware/automotive/evs/ParameterRange.h>
#include <aidl/android/hardware/automotive/evs/Stream.h>
-// #include <android-base/result.h>
#include <android/hardware_buffer.h>
#include <ui/GraphicBuffer.h>
-#include <functional>
+#include <cstdint>
+#include <memory>
#include <thread>
+#include <unordered_map>
+#include <vector>
namespace aidl::android::hardware::automotive::evs::implementation {
-class EvsMockCamera : public EvsCameraBase {
+class EvsMockCamera : public EvsCamera {
+ private:
+ using Base = EvsCamera;
+
public:
+ EvsMockCamera(Sigil sigil, const char* deviceName,
+ std::unique_ptr<ConfigManager::CameraInfo>& camInfo);
+ EvsMockCamera(const EvsMockCamera&) = delete;
+ EvsMockCamera& operator=(const EvsMockCamera&) = delete;
+
// Methods from ::android::hardware::automotive::evs::IEvsCamera follow.
- ndk::ScopedAStatus doneWithFrame(const std::vector<evs::BufferDesc>& buffers) override;
ndk::ScopedAStatus forcePrimaryClient(
const std::shared_ptr<evs::IEvsDisplay>& display) override;
ndk::ScopedAStatus getCameraInfo(evs::CameraDesc* _aidl_return) override;
@@ -51,49 +58,37 @@
ndk::ScopedAStatus getParameterList(std::vector<evs::CameraParam>* _aidl_return) override;
ndk::ScopedAStatus getPhysicalCameraInfo(const std::string& deviceId,
evs::CameraDesc* _aidl_return) override;
- ndk::ScopedAStatus importExternalBuffers(const std::vector<evs::BufferDesc>& buffers,
- int32_t* _aidl_return) override;
- ndk::ScopedAStatus pauseVideoStream() override;
- ndk::ScopedAStatus resumeVideoStream() override;
ndk::ScopedAStatus setExtendedInfo(int32_t opaqueIdentifier,
const std::vector<uint8_t>& opaqueValue) override;
ndk::ScopedAStatus setIntParameter(evs::CameraParam id, int32_t value,
std::vector<int32_t>* effectiveValue) override;
ndk::ScopedAStatus setPrimaryClient() override;
- ndk::ScopedAStatus setMaxFramesInFlight(int32_t bufferCount) override;
- ndk::ScopedAStatus startVideoStream(
- const std::shared_ptr<evs::IEvsCameraStream>& receiver) override;
- ndk::ScopedAStatus stopVideoStream() override;
ndk::ScopedAStatus unsetPrimaryClient() override;
+ const evs::CameraDesc& getDesc() { return mDescription; }
+
static std::shared_ptr<EvsMockCamera> Create(const char* deviceName);
static std::shared_ptr<EvsMockCamera> Create(
const char* deviceName, std::unique_ptr<ConfigManager::CameraInfo>& camInfo,
const evs::Stream* streamCfg = nullptr);
- EvsMockCamera(const EvsMockCamera&) = delete;
- EvsMockCamera& operator=(const EvsMockCamera&) = delete;
-
- virtual ~EvsMockCamera() override;
-
- // Methods from EvsCameraBase follow.
- void shutdown() override;
-
- const evs::CameraDesc& getDesc() { return mDescription; }
-
- // Constructors
- EvsMockCamera(Sigil sigil, const char* deviceName,
- std::unique_ptr<ConfigManager::CameraInfo>& camInfo);
private:
- // These three functions are expected to be called while mAccessLock is held
- bool setAvailableFrames_Locked(unsigned bufferCount);
- unsigned increaseAvailableFrames_Locked(unsigned numToAdd);
- unsigned decreaseAvailableFrames_Locked(unsigned numToRemove);
-
void generateFrames();
void fillMockFrame(buffer_handle_t handle, const AHardwareBuffer_Desc* pDesc);
- void returnBufferLocked(const uint32_t bufferId);
- ndk::ScopedAStatus stopVideoStream_impl();
+
+ ::android::status_t allocateOneFrame(buffer_handle_t* handle) override;
+
+ bool startVideoStreamImpl_locked(const std::shared_ptr<evs::IEvsCameraStream>& receiver,
+ ndk::ScopedAStatus& status,
+ std::unique_lock<std::mutex>& lck) override;
+
+ bool stopVideoStreamImpl_locked(ndk::ScopedAStatus& status,
+ std::unique_lock<std::mutex>& lck) override;
+
+ bool postVideoStreamStop_locked(ndk::ScopedAStatus& status,
+ std::unique_lock<std::mutex>& lck) override;
+
+ void initializeParameters();
CameraDesc mDescription = {}; // The properties of this camera
@@ -114,28 +109,6 @@
// Bytes per line in the buffers
uint32_t mStride = 0;
- struct BufferRecord {
- buffer_handle_t handle;
- bool inUse;
-
- explicit BufferRecord(buffer_handle_t h) : handle(h), inUse(false){};
- };
-
- std::vector<BufferRecord> mBuffers; // Graphics buffers to transfer images
- unsigned mFramesAllowed; // How many buffers are we currently using
- unsigned mFramesInUse; // How many buffers are currently outstanding
-
- enum StreamStateValues {
- STOPPED,
- RUNNING,
- STOPPING,
- DEAD,
- };
- StreamStateValues mStreamState;
-
- // Synchronization necessary to deconflict mCaptureThread from the main service thread
- std::mutex mAccessLock;
-
// Static camera module information
std::unique_ptr<ConfigManager::CameraInfo>& mCameraInfo;
@@ -155,7 +128,6 @@
int32_t value;
};
std::unordered_map<CameraParam, std::shared_ptr<CameraParameterDesc>> mParams;
- void initializeParameters();
};
} // namespace aidl::android::hardware::automotive::evs::implementation
diff --git a/automotive/evs/aidl/impl/default/include/EvsVideoEmulatedCamera.h b/automotive/evs/aidl/impl/default/include/EvsVideoEmulatedCamera.h
new file mode 100644
index 0000000..356a42a
--- /dev/null
+++ b/automotive/evs/aidl/impl/default/include/EvsVideoEmulatedCamera.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#pragma once
+
+#include "ConfigManager.h"
+#include "EvsCamera.h"
+
+#include <aidl/android/hardware/automotive/evs/BufferDesc.h>
+#include <aidl/android/hardware/automotive/evs/CameraDesc.h>
+#include <aidl/android/hardware/automotive/evs/CameraParam.h>
+#include <aidl/android/hardware/automotive/evs/IEvsCameraStream.h>
+#include <aidl/android/hardware/automotive/evs/IEvsDisplay.h>
+#include <aidl/android/hardware/automotive/evs/ParameterRange.h>
+#include <aidl/android/hardware/automotive/evs/Stream.h>
+
+#include <cstdint>
+#include <memory>
+#include <unordered_map>
+#include <vector>
+
+namespace aidl::android::hardware::automotive::evs::implementation {
+
+class EvsVideoEmulatedCamera : public EvsCamera {
+ public:
+ EvsVideoEmulatedCamera(Sigil sigil, const char* deviceName,
+ std::unique_ptr<ConfigManager::CameraInfo>& camInfo);
+
+ ~EvsVideoEmulatedCamera() override;
+
+ // Methods from ::android::hardware::automotive::evs::IEvsCamera follow.
+ ndk::ScopedAStatus forcePrimaryClient(
+ const std::shared_ptr<evs::IEvsDisplay>& display) override;
+ ndk::ScopedAStatus getCameraInfo(evs::CameraDesc* _aidl_return) override;
+ ndk::ScopedAStatus getExtendedInfo(int32_t opaqueIdentifier,
+ std::vector<uint8_t>* value) override;
+ ndk::ScopedAStatus getIntParameter(evs::CameraParam id, std::vector<int32_t>* value) override;
+ ndk::ScopedAStatus getIntParameterRange(evs::CameraParam id,
+ evs::ParameterRange* _aidl_return) override;
+ ndk::ScopedAStatus getParameterList(std::vector<evs::CameraParam>* _aidl_return) override;
+ ndk::ScopedAStatus getPhysicalCameraInfo(const std::string& deviceId,
+ evs::CameraDesc* _aidl_return) override;
+ ndk::ScopedAStatus setExtendedInfo(int32_t opaqueIdentifier,
+ const std::vector<uint8_t>& opaqueValue) override;
+ ndk::ScopedAStatus setIntParameter(evs::CameraParam id, int32_t value,
+ std::vector<int32_t>* effectiveValue) override;
+ ndk::ScopedAStatus setPrimaryClient() override;
+ ndk::ScopedAStatus unsetPrimaryClient() override;
+
+ const evs::CameraDesc& getDesc() { return mDescription; }
+
+ static std::shared_ptr<EvsVideoEmulatedCamera> Create(const char* deviceName);
+ static std::shared_ptr<EvsVideoEmulatedCamera> Create(
+ const char* deviceName, std::unique_ptr<ConfigManager::CameraInfo>& camInfo,
+ const evs::Stream* streamCfg = nullptr);
+
+ private:
+ // For the camera parameters.
+ struct CameraParameterDesc {
+ CameraParameterDesc(int min = 0, int max = 0, int step = 0, int value = 0) {
+ this->range.min = min;
+ this->range.max = max;
+ this->range.step = step;
+ this->value = value;
+ }
+
+ ParameterRange range;
+ int32_t value;
+ };
+
+ void initializeParameters();
+
+ ::android::status_t allocateOneFrame(buffer_handle_t* handle) override;
+
+ bool startVideoStreamImpl_locked(const std::shared_ptr<evs::IEvsCameraStream>& receiver,
+ ndk::ScopedAStatus& status,
+ std::unique_lock<std::mutex>& lck) override;
+
+ bool stopVideoStreamImpl_locked(ndk::ScopedAStatus& status,
+ std::unique_lock<std::mutex>& lck) override;
+
+ // The properties of this camera.
+ CameraDesc mDescription = {};
+
+ // Camera parameters.
+ std::unordered_map<CameraParam, std::shared_ptr<CameraParameterDesc>> mParams;
+
+ // Static camera module information
+ std::unique_ptr<ConfigManager::CameraInfo>& mCameraInfo;
+
+ // For the extended info
+ std::unordered_map<uint32_t, std::vector<uint8_t>> mExtInfo;
+};
+
+} // namespace aidl::android::hardware::automotive::evs::implementation
diff --git a/automotive/evs/aidl/impl/default/src/EvsCamera.cpp b/automotive/evs/aidl/impl/default/src/EvsCamera.cpp
index 208a1a4..bc3bfdd 100644
--- a/automotive/evs/aidl/impl/default/src/EvsCamera.cpp
+++ b/automotive/evs/aidl/impl/default/src/EvsCamera.cpp
@@ -292,7 +292,7 @@
std::pair<std::size_t, buffer_handle_t> EvsCamera::useBuffer_unsafe() {
if (mFramesInUse >= mAvailableFrames) {
DCHECK_EQ(mFramesInUse, mAvailableFrames);
- return {static_cast<std::size_t>(-1), nullptr};
+ return {kInvalidBufferID, nullptr};
}
const std::size_t pos = mFramesInUse++;
auto& buffer = mBuffers[pos];
diff --git a/automotive/evs/aidl/impl/default/src/EvsEnumerator.cpp b/automotive/evs/aidl/impl/default/src/EvsEnumerator.cpp
index ec4b18f..80e72a7 100644
--- a/automotive/evs/aidl/impl/default/src/EvsEnumerator.cpp
+++ b/automotive/evs/aidl/impl/default/src/EvsEnumerator.cpp
@@ -17,9 +17,9 @@
#include "EvsEnumerator.h"
#include "ConfigManager.h"
+#include "EvsAllCameras.h"
#include "EvsCameraBase.h"
#include "EvsGlDisplay.h"
-#include "EvsMockCamera.h"
#include <aidl/android/hardware/automotive/evs/EvsResult.h>
#include <aidl/android/hardware/graphics/common/BufferUsage.h>
@@ -264,6 +264,10 @@
pActiveCamera = EvsMockCamera::Create(id.data(), cameraInfo, &cfg);
break;
+ case DeviceType::VIDEO:
+ pActiveCamera = EvsVideoEmulatedCamera::Create(id.data(), cameraInfo, &cfg);
+ break;
+
default:
LOG(ERROR) << __func__ << ": camera device type "
<< static_cast<std::int32_t>(cameraInfo->deviceType)
diff --git a/automotive/evs/aidl/impl/default/src/EvsMockCamera.cpp b/automotive/evs/aidl/impl/default/src/EvsMockCamera.cpp
index 797b221..ef43925 100644
--- a/automotive/evs/aidl/impl/default/src/EvsMockCamera.cpp
+++ b/automotive/evs/aidl/impl/default/src/EvsMockCamera.cpp
@@ -15,28 +15,25 @@
*/
#include "EvsMockCamera.h"
-#include "ConfigManager.h"
-#include "EvsEnumerator.h"
+
+#include <aidl/android/hardware/automotive/evs/EvsResult.h>
#include <aidlcommonsupport/NativeHandle.h>
+#include <android-base/logging.h>
#include <ui/GraphicBufferAllocator.h>
#include <ui/GraphicBufferMapper.h>
#include <utils/SystemClock.h>
+#include <cstddef>
+#include <cstdint>
#include <memory>
+#include <tuple>
namespace {
using ::aidl::android::hardware::graphics::common::BufferUsage;
using ::ndk::ScopedAStatus;
-// Arbitrary limit on number of graphics buffers allowed to be allocated
-// Safeguards against unreasonable resource consumption and provides a testable limit
-constexpr unsigned kMaxBuffersInFlight = 100;
-
-// Minimum number of buffers to run a video stream
-constexpr int kMinimumBuffersInFlight = 1;
-
// Colors for the colorbar test pattern in ABGR format
constexpr uint32_t kColors[] = {
0xFFFFFFFF, // white
@@ -56,7 +53,7 @@
EvsMockCamera::EvsMockCamera([[maybe_unused]] Sigil sigil, const char* id,
std::unique_ptr<ConfigManager::CameraInfo>& camInfo)
- : mFramesAllowed(0), mFramesInUse(0), mStreamState(STOPPED), mCameraInfo(camInfo) {
+ : mCameraInfo(camInfo) {
LOG(DEBUG) << __FUNCTION__;
/* set a camera id */
@@ -73,11 +70,6 @@
initializeParameters();
}
-EvsMockCamera::~EvsMockCamera() {
- LOG(DEBUG) << __FUNCTION__;
- shutdown();
-}
-
void EvsMockCamera::initializeParameters() {
mParams.emplace(
CameraParam::BRIGHTNESS,
@@ -90,35 +82,6 @@
new CameraParameterDesc(/* min= */ 0, /* max= */ 255, /* step= */ 1, /* value= */ 255));
}
-// This gets called if another caller "steals" ownership of the camera
-void EvsMockCamera::shutdown() {
- LOG(DEBUG) << __FUNCTION__;
-
- // Make sure our output stream is cleaned up
- // (It really should be already)
- stopVideoStream_impl();
-
- // Claim the lock while we work on internal state
- std::lock_guard lock(mAccessLock);
-
- // Drop all the graphics buffers we've been using
- if (mBuffers.size() > 0) {
- ::android::GraphicBufferAllocator& alloc(::android::GraphicBufferAllocator::get());
- for (auto&& rec : mBuffers) {
- if (rec.inUse) {
- LOG(WARNING) << "WARNING: releasing a buffer remotely owned.";
- }
- alloc.free(rec.handle);
- rec.handle = nullptr;
- }
- mBuffers.clear();
- }
-
- // Put this object into an unrecoverable error state since somebody else
- // is going to own the underlying camera now
- mStreamState = DEAD;
-}
-
// Methods from ::aidl::android::hardware::automotive::evs::IEvsCamera follow.
ScopedAStatus EvsMockCamera::getCameraInfo(CameraDesc* _aidl_return) {
LOG(DEBUG) << __FUNCTION__;
@@ -128,115 +91,6 @@
return ScopedAStatus::ok();
}
-ScopedAStatus EvsMockCamera::setMaxFramesInFlight(int32_t bufferCount) {
- LOG(DEBUG) << __FUNCTION__ << ", bufferCount = " << bufferCount;
- ;
-
- std::lock_guard lock(mAccessLock);
-
- // If we've been displaced by another owner of the camera, then we can't do anything else
- if (mStreamState == DEAD) {
- LOG(ERROR) << "Ignoring setMaxFramesInFlight call when camera has been lost.";
- return ScopedAStatus::fromServiceSpecificError(static_cast<int>(EvsResult::OWNERSHIP_LOST));
- }
-
- // We cannot function without at least one video buffer to send data
- if (bufferCount < 1) {
- LOG(ERROR) << "Ignoring setMaxFramesInFlight with less than one buffer requested.";
- return ScopedAStatus::fromServiceSpecificError(static_cast<int>(EvsResult::INVALID_ARG));
- }
-
- // Update our internal state
- if (!setAvailableFrames_Locked(bufferCount)) {
- LOG(ERROR) << "Failed to adjust the maximum number of frames in flight.";
- return ScopedAStatus::fromServiceSpecificError(
- static_cast<int>(EvsResult::BUFFER_NOT_AVAILABLE));
- }
-
- return ScopedAStatus::ok();
-}
-
-ScopedAStatus EvsMockCamera::startVideoStream(const std::shared_ptr<IEvsCameraStream>& cb) {
- LOG(DEBUG) << __FUNCTION__;
-
- if (!cb) {
- LOG(ERROR) << "A given stream callback is invalid.";
- return ScopedAStatus::fromServiceSpecificError(static_cast<int>(EvsResult::INVALID_ARG));
- }
-
- std::lock_guard lock(mAccessLock);
-
- // If we've been displaced by another owner of the camera, then we can't do anything else
- if (mStreamState == DEAD) {
- LOG(ERROR) << "Ignoring startVideoStream call when camera has been lost.";
- return ScopedAStatus::fromServiceSpecificError(static_cast<int>(EvsResult::OWNERSHIP_LOST));
- }
-
- if (mStreamState != STOPPED) {
- LOG(ERROR) << "Ignoring startVideoStream call when a stream is already running.";
- return ScopedAStatus::fromServiceSpecificError(
- static_cast<int>(EvsResult::STREAM_ALREADY_RUNNING));
- }
-
- // If the client never indicated otherwise, configure ourselves for a single streaming buffer
- if (mFramesAllowed < kMinimumBuffersInFlight &&
- !setAvailableFrames_Locked(kMinimumBuffersInFlight)) {
- LOG(ERROR) << "Failed to start stream because we couldn't get a graphics buffer";
- return ScopedAStatus::fromServiceSpecificError(
- static_cast<int>(EvsResult::BUFFER_NOT_AVAILABLE));
- }
-
- // Record the user's callback for use when we have a frame ready
- mStream = cb;
-
- // Start the frame generation thread
- mStreamState = RUNNING;
- mCaptureThread = std::thread([this]() { generateFrames(); });
-
- return ScopedAStatus::ok();
-}
-
-ScopedAStatus EvsMockCamera::doneWithFrame(const std::vector<BufferDesc>& list) {
- std::lock_guard lock(mAccessLock);
- for (const auto& desc : list) {
- returnBufferLocked(desc.bufferId);
- }
-
- return ScopedAStatus::ok();
-}
-
-ScopedAStatus EvsMockCamera::stopVideoStream() {
- LOG(DEBUG) << __FUNCTION__;
- return stopVideoStream_impl();
-}
-
-ScopedAStatus EvsMockCamera::stopVideoStream_impl() {
- std::unique_lock lock(mAccessLock);
-
- if (mStreamState != RUNNING) {
- // Safely return here because a stream is not running.
- return ScopedAStatus::ok();
- }
-
- // Tell the GenerateFrames loop we want it to stop
- mStreamState = STOPPING;
-
- // Block outside the mutex until the "stop" flag has been acknowledged
- // We won't send any more frames, but the client might still get some already in flight
- LOG(DEBUG) << "Waiting for stream thread to end...";
- lock.unlock();
- if (mCaptureThread.joinable()) {
- mCaptureThread.join();
- }
- lock.lock();
-
- mStreamState = STOPPED;
- mStream = nullptr;
- LOG(DEBUG) << "Stream marked STOPPED.";
-
- return ScopedAStatus::ok();
-}
-
ScopedAStatus EvsMockCamera::getExtendedInfo(int32_t opaqueIdentifier,
std::vector<uint8_t>* opaqueValue) {
const auto it = mExtInfo.find(opaqueIdentifier);
@@ -264,14 +118,6 @@
return ScopedAStatus::ok();
}
-ScopedAStatus EvsMockCamera::pauseVideoStream() {
- return ScopedAStatus::fromServiceSpecificError(static_cast<int>(EvsResult::NOT_SUPPORTED));
-}
-
-ScopedAStatus EvsMockCamera::resumeVideoStream() {
- return ScopedAStatus::fromServiceSpecificError(static_cast<int>(EvsResult::NOT_SUPPORTED));
-}
-
ScopedAStatus EvsMockCamera::setPrimaryClient() {
/* Because EVS HW module reference implementation expects a single client at
* a time, this returns a success code always.
@@ -346,232 +192,27 @@
return ScopedAStatus::ok();
}
-ScopedAStatus EvsMockCamera::importExternalBuffers(const std::vector<BufferDesc>& buffers,
- int32_t* _aidl_return) {
- size_t numBuffersToAdd = buffers.size();
- if (numBuffersToAdd < 1) {
- LOG(DEBUG) << "Ignoring a request to import external buffers with an empty list.";
- return ScopedAStatus::ok();
- }
-
- std::lock_guard lock(mAccessLock);
- if (numBuffersToAdd > (kMaxBuffersInFlight - mFramesAllowed)) {
- numBuffersToAdd -= (kMaxBuffersInFlight - mFramesAllowed);
- LOG(WARNING) << "Exceed the limit on the number of buffers. " << numBuffersToAdd
- << " buffers will be imported only.";
- }
-
- ::android::GraphicBufferMapper& mapper = ::android::GraphicBufferMapper::get();
- const size_t before = mFramesAllowed;
- for (size_t i = 0; i < numBuffersToAdd; ++i) {
- auto& b = buffers[i];
- const AHardwareBuffer_Desc* pDesc =
- reinterpret_cast<const AHardwareBuffer_Desc*>(&b.buffer.description);
-
- buffer_handle_t handleToImport = ::android::dupFromAidl(b.buffer.handle);
- buffer_handle_t handleToStore = nullptr;
- if (handleToImport == nullptr) {
- LOG(WARNING) << "Failed to duplicate a memory handle. Ignoring a buffer " << b.bufferId;
- continue;
- }
-
- ::android::status_t result =
- mapper.importBuffer(handleToImport, pDesc->width, pDesc->height, pDesc->layers,
- pDesc->format, pDesc->usage, pDesc->stride, &handleToStore);
- if (result != ::android::NO_ERROR || handleToStore == nullptr) {
- LOG(WARNING) << "Failed to import a buffer " << b.bufferId;
- continue;
- }
-
- bool stored = false;
- for (auto&& rec : mBuffers) {
- if (rec.handle != nullptr) {
- continue;
- }
-
- // Use this existing entry.
- rec.handle = handleToStore;
- rec.inUse = false;
- stored = true;
- break;
- }
-
- if (!stored) {
- // Add a BufferRecord wrapping this handle to our set of available buffers.
- mBuffers.push_back(BufferRecord(handleToStore));
- }
- ++mFramesAllowed;
- }
-
- *_aidl_return = mFramesAllowed - before;
- return ScopedAStatus::ok();
-}
-
-bool EvsMockCamera::setAvailableFrames_Locked(unsigned bufferCount) {
- if (bufferCount < 1) {
- LOG(ERROR) << "Ignoring request to set buffer count to zero";
- return false;
- }
- if (bufferCount > kMaxBuffersInFlight) {
- LOG(ERROR) << "Rejecting buffer request in excess of internal limit";
- return false;
- }
-
- // Is an increase required?
- if (mFramesAllowed < bufferCount) {
- // An increase is required
- auto needed = bufferCount - mFramesAllowed;
- LOG(INFO) << "Allocating " << needed << " buffers for camera frames";
-
- auto added = increaseAvailableFrames_Locked(needed);
- if (added != needed) {
- // If we didn't add all the frames we needed, then roll back to the previous state
- LOG(ERROR) << "Rolling back to previous frame queue size";
- decreaseAvailableFrames_Locked(added);
- return false;
- }
- } else if (mFramesAllowed > bufferCount) {
- // A decrease is required
- auto framesToRelease = mFramesAllowed - bufferCount;
- LOG(INFO) << "Returning " << framesToRelease << " camera frame buffers";
-
- auto released = decreaseAvailableFrames_Locked(framesToRelease);
- if (released != framesToRelease) {
- // This shouldn't happen with a properly behaving client because the client
- // should only make this call after returning sufficient outstanding buffers
- // to allow a clean resize.
- LOG(ERROR) << "Buffer queue shrink failed -- too many buffers currently in use?";
- }
- }
-
- return true;
-}
-
-unsigned EvsMockCamera::increaseAvailableFrames_Locked(unsigned numToAdd) {
- // Acquire the graphics buffer allocator
- ::android::GraphicBufferAllocator& alloc(::android::GraphicBufferAllocator::get());
-
- unsigned added = 0;
- while (added < numToAdd) {
- unsigned pixelsPerLine = 0;
- buffer_handle_t memHandle = nullptr;
- auto result = alloc.allocate(mWidth, mHeight, mFormat, 1, mUsage, &memHandle,
- &pixelsPerLine, 0, "EvsMockCamera");
- if (result != ::android::NO_ERROR) {
- LOG(ERROR) << "Error " << result << " allocating " << mWidth << " x " << mHeight
- << " graphics buffer";
- break;
- }
- if (memHandle == nullptr) {
- LOG(ERROR) << "We didn't get a buffer handle back from the allocator";
- break;
- }
- if (mStride > 0) {
- if (mStride != pixelsPerLine) {
- LOG(ERROR) << "We did not expect to get buffers with different strides!";
- }
- } else {
- // Gralloc defines stride in terms of pixels per line
- mStride = pixelsPerLine;
- }
-
- // Find a place to store the new buffer
- auto stored = false;
- for (auto&& rec : mBuffers) {
- if (rec.handle == nullptr) {
- // Use this existing entry
- rec.handle = memHandle;
- rec.inUse = false;
- stored = true;
- break;
- }
- }
- if (!stored) {
- // Add a BufferRecord wrapping this handle to our set of available buffers
- mBuffers.push_back(BufferRecord(memHandle));
- }
-
- ++mFramesAllowed;
- ++added;
- }
-
- return added;
-}
-
-unsigned EvsMockCamera::decreaseAvailableFrames_Locked(unsigned numToRemove) {
- // Acquire the graphics buffer allocator
- ::android::GraphicBufferAllocator& alloc(::android::GraphicBufferAllocator::get());
-
- unsigned removed = 0;
- for (auto&& rec : mBuffers) {
- // Is this record not in use, but holding a buffer that we can free?
- if ((rec.inUse == false) && (rec.handle != nullptr)) {
- // Release buffer and update the record so we can recognize it as "empty"
- alloc.free(rec.handle);
- rec.handle = nullptr;
-
- --mFramesAllowed;
- ++removed;
-
- if (removed == numToRemove) {
- break;
- }
- }
- }
-
- return removed;
-}
-
// This is the asynchronous frame generation thread that runs in parallel with the
// main serving thread. There is one for each active camera instance.
void EvsMockCamera::generateFrames() {
LOG(DEBUG) << "Frame generation loop started.";
- unsigned idx = 0;
while (true) {
- bool timeForFrame = false;
const nsecs_t startTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
- // Lock scope for updating shared state
+ std::size_t bufferId = kInvalidBufferID;
+ buffer_handle_t bufferHandle = nullptr;
{
- std::lock_guard lock(mAccessLock);
-
- if (mStreamState != RUNNING) {
- // Break out of our main thread loop
+ std::lock_guard lock(mMutex);
+ if (mStreamState != StreamState::RUNNING) {
break;
}
-
- // Are we allowed to issue another buffer?
- if (mFramesInUse >= mFramesAllowed) {
- // Can't do anything right now -- skip this frame
- LOG(WARNING) << "Skipped a frame because too many are in flight.";
- } else {
- // Identify an available buffer to fill
- for (idx = 0; idx < mBuffers.size(); idx++) {
- if (!mBuffers[idx].inUse) {
- if (mBuffers[idx].handle != nullptr) {
- // Found an available record, so stop looking
- break;
- }
- }
- }
- if (idx >= mBuffers.size()) {
- // This shouldn't happen since we already checked mFramesInUse vs mFramesAllowed
- ALOGE("Failed to find an available buffer slot\n");
- } else {
- // We're going to make the frame busy
- mBuffers[idx].inUse = true;
- mFramesInUse++;
- timeForFrame = true;
- }
- }
+ std::tie(bufferId, bufferHandle) = useBuffer_unsafe();
}
- if (timeForFrame) {
+ if (bufferHandle != nullptr) {
using AidlPixelFormat = ::aidl::android::hardware::graphics::common::PixelFormat;
// Assemble the buffer description we'll transmit below
- buffer_handle_t memHandle = mBuffers[idx].handle;
BufferDesc newBuffer = {
.buffer =
{
@@ -584,39 +225,31 @@
.usage = static_cast<BufferUsage>(mUsage),
.stride = static_cast<int32_t>(mStride),
},
- .handle = ::android::dupToAidl(memHandle),
+ .handle = ::android::dupToAidl(bufferHandle),
},
- .bufferId = static_cast<int32_t>(idx),
+ .bufferId = static_cast<int32_t>(bufferId),
.deviceId = mDescription.id,
.timestamp = static_cast<int64_t>(::android::elapsedRealtimeNano() *
1e+3), // timestamps is in microseconds
};
// Write test data into the image buffer
- fillMockFrame(memHandle, reinterpret_cast<const AHardwareBuffer_Desc*>(
- &newBuffer.buffer.description));
+ fillMockFrame(bufferHandle, reinterpret_cast<const AHardwareBuffer_Desc*>(
+ &newBuffer.buffer.description));
+
+ std::vector<BufferDesc> frames;
+ frames.push_back(std::move(newBuffer));
// Issue the (asynchronous) callback to the client -- can't be holding the lock
- auto flag = false;
- if (mStream) {
- std::vector<BufferDesc> frames;
- frames.push_back(std::move(newBuffer));
- flag = mStream->deliverFrame(frames).isOk();
- }
-
- if (flag) {
- LOG(DEBUG) << "Delivered " << memHandle << ", id = " << mBuffers[idx].handle;
+ if (mStream && mStream->deliverFrame(frames).isOk()) {
+ LOG(DEBUG) << "Delivered " << bufferHandle << ", id = " << bufferId;
} else {
// This can happen if the client dies and is likely unrecoverable.
// To avoid consuming resources generating failing calls, we stop sending
// frames. Note, however, that the stream remains in the "STREAMING" state
// until cleaned up on the main thread.
LOG(ERROR) << "Frame delivery call failed in the transport layer.";
-
- // Since we didn't actually deliver it, mark the frame as available
- std::lock_guard<std::mutex> lock(mAccessLock);
- mBuffers[idx].inUse = false;
- mFramesInUse--;
+ doneWithFrame(frames);
}
}
@@ -671,34 +304,45 @@
mapper.unlock(handle);
}
-void EvsMockCamera::returnBufferLocked(const uint32_t bufferId) {
- if (bufferId >= mBuffers.size()) {
- ALOGE("ignoring doneWithFrame called with invalid bufferId %d (max is %zu)", bufferId,
- mBuffers.size() - 1);
- return;
+::android::status_t EvsMockCamera::allocateOneFrame(buffer_handle_t* handle) {
+ static auto& alloc = ::android::GraphicBufferAllocator::get();
+ unsigned pixelsPerLine = 0;
+ const auto result = alloc.allocate(mWidth, mHeight, mFormat, 1, mUsage, handle, &pixelsPerLine,
+ 0, "EvsMockCamera");
+ if (mStride < mWidth) {
+ // Gralloc defines stride in terms of pixels per line
+ mStride = pixelsPerLine;
+ } else if (mStride != pixelsPerLine) {
+ LOG(ERROR) << "We did not expect to get buffers with different strides!";
}
+ return result;
+}
- if (!mBuffers[bufferId].inUse) {
- ALOGE("ignoring doneWithFrame called on frame %d which is already free", bufferId);
- return;
+bool EvsMockCamera::startVideoStreamImpl_locked(
+ const std::shared_ptr<evs::IEvsCameraStream>& receiver, ndk::ScopedAStatus& /* status */,
+ std::unique_lock<std::mutex>& /* lck */) {
+ mStream = receiver;
+ mCaptureThread = std::thread([this]() { generateFrames(); });
+ return true;
+}
+
+bool EvsMockCamera::stopVideoStreamImpl_locked(ndk::ScopedAStatus& /* status */,
+ std::unique_lock<std::mutex>& lck) {
+ lck.unlock();
+ if (mCaptureThread.joinable()) {
+ mCaptureThread.join();
}
+ lck.lock();
+ return true;
+}
- // Mark the frame as available
- mBuffers[bufferId].inUse = false;
- mFramesInUse--;
-
- // If this frame's index is high in the array, try to move it down
- // to improve locality after mFramesAllowed has been reduced.
- if (bufferId >= mFramesAllowed) {
- // Find an empty slot lower in the array (which should always exist in this case)
- for (auto&& rec : mBuffers) {
- if (rec.handle == nullptr) {
- rec.handle = mBuffers[bufferId].handle;
- mBuffers[bufferId].handle = nullptr;
- break;
- }
- }
+bool EvsMockCamera::postVideoStreamStop_locked(ndk::ScopedAStatus& status,
+ std::unique_lock<std::mutex>& lck) {
+ if (!Base::postVideoStreamStop_locked(status, lck)) {
+ return false;
}
+ mStream = nullptr;
+ return true;
}
std::shared_ptr<EvsMockCamera> EvsMockCamera::Create(const char* deviceName) {
diff --git a/automotive/evs/aidl/impl/default/src/EvsVideoEmulatedCamera.cpp b/automotive/evs/aidl/impl/default/src/EvsVideoEmulatedCamera.cpp
new file mode 100644
index 0000000..f198a64
--- /dev/null
+++ b/automotive/evs/aidl/impl/default/src/EvsVideoEmulatedCamera.cpp
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "EvsVideoEmulatedCamera.h"
+
+#include <aidl/android/hardware/automotive/evs/EvsResult.h>
+
+#include <android-base/logging.h>
+
+#include <cstddef>
+#include <cstdint>
+
+namespace aidl::android::hardware::automotive::evs::implementation {
+
+EvsVideoEmulatedCamera::EvsVideoEmulatedCamera(Sigil, const char* deviceName,
+ std::unique_ptr<ConfigManager::CameraInfo>& camInfo)
+ : mCameraInfo(camInfo) {
+ mDescription.id = deviceName;
+
+ /* set camera metadata */
+ if (camInfo) {
+ uint8_t* ptr = reinterpret_cast<uint8_t*>(camInfo->characteristics);
+ const size_t len = get_camera_metadata_size(camInfo->characteristics);
+ mDescription.metadata.insert(mDescription.metadata.end(), ptr, ptr + len);
+ }
+
+ initializeParameters();
+}
+
+void EvsVideoEmulatedCamera::initializeParameters() {
+ mParams.emplace(
+ CameraParam::BRIGHTNESS,
+ new CameraParameterDesc(/* min= */ 0, /* max= */ 255, /* step= */ 1, /* value= */ 255));
+ mParams.emplace(
+ CameraParam::CONTRAST,
+ new CameraParameterDesc(/* min= */ 0, /* max= */ 255, /* step= */ 1, /* value= */ 255));
+ mParams.emplace(
+ CameraParam::SHARPNESS,
+ new CameraParameterDesc(/* min= */ 0, /* max= */ 255, /* step= */ 1, /* value= */ 255));
+}
+
+::android::status_t EvsVideoEmulatedCamera::allocateOneFrame(buffer_handle_t* /* handle */) {
+ LOG(FATAL) << __func__ << ": Not implemented yet.";
+ return ::android::UNKNOWN_ERROR;
+}
+
+bool EvsVideoEmulatedCamera::startVideoStreamImpl_locked(
+ const std::shared_ptr<evs::IEvsCameraStream>& /* receiver */,
+ ndk::ScopedAStatus& /* status */, std::unique_lock<std::mutex>& /* lck */) {
+ LOG(FATAL) << __func__ << ": Not implemented yet.";
+ return false;
+}
+
+bool EvsVideoEmulatedCamera::stopVideoStreamImpl_locked(ndk::ScopedAStatus& /* status */,
+ std::unique_lock<std::mutex>& /* lck */) {
+ LOG(FATAL) << __func__ << ": Not implemented yet.";
+ return false;
+}
+
+ndk::ScopedAStatus EvsVideoEmulatedCamera::forcePrimaryClient(
+ const std::shared_ptr<evs::IEvsDisplay>& /* display */) {
+ /* Because EVS HW module reference implementation expects a single client at
+ * a time, this returns a success code always.
+ */
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EvsVideoEmulatedCamera::getCameraInfo(evs::CameraDesc* _aidl_return) {
+ *_aidl_return = mDescription;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EvsVideoEmulatedCamera::getExtendedInfo(int32_t opaqueIdentifier,
+ std::vector<uint8_t>* value) {
+ const auto it = mExtInfo.find(opaqueIdentifier);
+ if (it == mExtInfo.end()) {
+ return ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int>(EvsResult::INVALID_ARG));
+ } else {
+ *value = mExtInfo[opaqueIdentifier];
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EvsVideoEmulatedCamera::getIntParameter(evs::CameraParam id,
+ std::vector<int32_t>* value) {
+ const auto it = mParams.find(id);
+ if (it == mParams.end()) {
+ return ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int>(EvsResult::NOT_SUPPORTED));
+ }
+ value->push_back(it->second->value);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EvsVideoEmulatedCamera::getIntParameterRange(evs::CameraParam id,
+ evs::ParameterRange* _aidl_return) {
+ const auto it = mParams.find(id);
+ if (it == mParams.end()) {
+ return ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int>(EvsResult::NOT_SUPPORTED));
+ }
+ _aidl_return->min = it->second->range.min;
+ _aidl_return->max = it->second->range.max;
+ _aidl_return->step = it->second->range.step;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EvsVideoEmulatedCamera::getParameterList(
+ std::vector<evs::CameraParam>* _aidl_return) {
+ if (mCameraInfo) {
+ _aidl_return->resize(mCameraInfo->controls.size());
+ std::size_t idx = 0;
+ for (const auto& [name, range] : mCameraInfo->controls) {
+ (*_aidl_return)[idx++] = name;
+ }
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EvsVideoEmulatedCamera::getPhysicalCameraInfo(const std::string& /* deviceId */,
+ evs::CameraDesc* _aidl_return) {
+ return getCameraInfo(_aidl_return);
+}
+
+ndk::ScopedAStatus EvsVideoEmulatedCamera::setExtendedInfo(
+ int32_t opaqueIdentifier, const std::vector<uint8_t>& opaqueValue) {
+ mExtInfo.insert_or_assign(opaqueIdentifier, opaqueValue);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EvsVideoEmulatedCamera::setIntParameter(evs::CameraParam id, int32_t value,
+ std::vector<int32_t>* effectiveValue) {
+ const auto it = mParams.find(id);
+ if (it == mParams.end()) {
+ return ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int>(EvsResult::NOT_SUPPORTED));
+ }
+ // Rounding down to the closest value.
+ int32_t candidate = value / it->second->range.step * it->second->range.step;
+ if (candidate < it->second->range.min || candidate > it->second->range.max) {
+ return ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int>(EvsResult::INVALID_ARG));
+ }
+ it->second->value = candidate;
+ effectiveValue->push_back(candidate);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EvsVideoEmulatedCamera::setPrimaryClient() {
+ /* Because EVS HW module reference implementation expects a single client at
+ * a time, this returns a success code always.
+ */
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EvsVideoEmulatedCamera::unsetPrimaryClient() {
+ /* Because EVS HW module reference implementation expects a single client at
+ * a time, there is no chance that this is called by the secondary client and
+ * therefore returns a success code always.
+ */
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EvsVideoEmulatedCamera> EvsVideoEmulatedCamera::Create(const char* deviceName) {
+ std::unique_ptr<ConfigManager::CameraInfo> nullCamInfo = nullptr;
+ return Create(deviceName, nullCamInfo);
+}
+
+std::shared_ptr<EvsVideoEmulatedCamera> EvsVideoEmulatedCamera::Create(
+ const char* deviceName, std::unique_ptr<ConfigManager::CameraInfo>& camInfo,
+ const evs::Stream* /* streamCfg */) {
+ std::shared_ptr<EvsVideoEmulatedCamera> c =
+ ndk::SharedRefBase::make<EvsVideoEmulatedCamera>(Sigil{}, deviceName, camInfo);
+ if (!c) {
+ LOG(ERROR) << "Failed to instantiate EvsVideoEmulatedCamera.";
+ return nullptr;
+ }
+ c->mDescription.vendorFlags = 0xFFFFFFFF; // Arbitrary test value
+ return c;
+}
+
+EvsVideoEmulatedCamera::~EvsVideoEmulatedCamera() {}
+
+} // namespace aidl::android::hardware::automotive::evs::implementation
diff --git a/automotive/evs/aidl/impl/default/tests/EvsCameraBufferTest.cpp b/automotive/evs/aidl/impl/default/tests/EvsCameraBufferTest.cpp
index 3cbc04a..8b4676e 100644
--- a/automotive/evs/aidl/impl/default/tests/EvsCameraBufferTest.cpp
+++ b/automotive/evs/aidl/impl/default/tests/EvsCameraBufferTest.cpp
@@ -134,6 +134,7 @@
for (std::size_t i = 0; i < kNumOfHandles; ++i) {
const auto [id, handle] = evsCam->useBuffer_unsafe();
const std::size_t handleInt = reinterpret_cast<std::size_t>(handle);
+ EXPECT_TRUE(EvsCamera::IsBufferIDValid(id));
EXPECT_NE(handle, nullptr);
EXPECT_LT(id, kNumOfHandles);
@@ -160,6 +161,7 @@
for (std::size_t i = 0; i < kNumOfHandles; ++i) {
const auto [id, handle] = evsCam->useBuffer_unsafe();
const std::size_t handleInt = reinterpret_cast<std::size_t>(handle);
+ EXPECT_TRUE(EvsCamera::IsBufferIDValid(id));
EXPECT_NE(handle, nullptr);
EXPECT_LT(id, kNumOfHandles);
@@ -189,6 +191,7 @@
for (std::size_t i = 0; i < kNumOfHandles; ++i) {
const auto [id, handle] = evsCam->useBuffer_unsafe();
const std::size_t handleInt = reinterpret_cast<std::size_t>(handle);
+ EXPECT_TRUE(EvsCamera::IsBufferIDValid(id));
EXPECT_NE(handle, nullptr);
EXPECT_LT(id, kNumOfHandles);
diff --git a/automotive/sv/1.0/default/tests/fuzzer/AutomotiveSvV1_0Fuzzer.cpp b/automotive/sv/1.0/default/tests/fuzzer/AutomotiveSvV1_0Fuzzer.cpp
index 98834f5..4c4cc70 100644
--- a/automotive/sv/1.0/default/tests/fuzzer/AutomotiveSvV1_0Fuzzer.cpp
+++ b/automotive/sv/1.0/default/tests/fuzzer/AutomotiveSvV1_0Fuzzer.cpp
@@ -41,35 +41,32 @@
void SurroundViewFuzzer::invoke2dSessionAPI() {
sp<ISurroundView2dSession> surroundView2dSession;
+ sp<SurroundViewStream> handler;
+ mSurroundViewService->start2dSession(
+ [&surroundView2dSession](const sp<ISurroundView2dSession>& session, SvResult result) {
+ if (result == SvResult::OK) {
+ surroundView2dSession = session;
+ }
+ });
+
+ if (surroundView2dSession && !mIs2dStreamStarted) {
+ handler = sp<SurroundViewStream>::make(surroundView2dSession);
+ if (surroundView2dSession->startStream(handler) == SvResult::OK) {
+ mIs2dStreamStarted = true;
+ }
+ }
while (mFuzzedDataProvider.remaining_bytes() > 0) {
auto surroundView2dFunc = mFuzzedDataProvider.PickValueInArray<
const std::function<void()>>({
[&]() {
- mSurroundViewService->start2dSession(
- [&surroundView2dSession](const sp<ISurroundView2dSession>& session,
- SvResult result) {
- if (result == SvResult::OK) {
- surroundView2dSession = session;
- }
- });
- },
- [&]() {
- if (surroundView2dSession) {
- sp<SurroundViewStream> handler =
- sp<SurroundViewStream>::make(surroundView2dSession);
- surroundView2dSession->startStream(handler);
- mIs2dStreamStarted = true;
- }
- },
- [&]() {
if (surroundView2dSession) {
surroundView2dSession->get2dMappingInfo(
[]([[maybe_unused]] Sv2dMappingInfo info) {});
}
},
[&]() {
- if (surroundView2dSession) {
+ if (surroundView2dSession && mIs2dStreamStarted) {
Sv2dConfig config;
config.width = mFuzzedDataProvider.ConsumeIntegralInRange<uint32_t>(
kMinConfigDimension, kMaxConfigDimension);
@@ -149,8 +146,11 @@
}
},
[&]() {
- mSurroundViewService->stop2dSession(
+ SvResult result = mSurroundViewService->stop2dSession(
mFuzzedDataProvider.ConsumeBool() ? surroundView2dSession : nullptr);
+ if (result == SvResult::OK) {
+ mIs2dStreamStarted = false;
+ }
},
});
surroundView2dFunc();
@@ -159,31 +159,40 @@
if (surroundView2dSession && mIs2dStreamStarted) {
surroundView2dSession->stopStream();
}
+
+ if (surroundView2dSession) {
+ mSurroundViewService->stop2dSession(surroundView2dSession);
+ }
}
void SurroundViewFuzzer::invoke3dSessionAPI() {
sp<ISurroundView3dSession> surroundView3dSession;
+ sp<SurroundViewStream> handler;
+ mSurroundViewService->start3dSession(
+ [&surroundView3dSession](const sp<ISurroundView3dSession>& session, SvResult result) {
+ if (result == SvResult::OK) {
+ surroundView3dSession = session;
+ }
+ });
+
+ const size_t numViews = mFuzzedDataProvider.ConsumeIntegralInRange<size_t>(1, kMaxViews);
+ std::vector<View3d> views(numViews);
+ for (size_t i = 0; i < numViews; ++i) {
+ views[i].viewId = mFuzzedDataProvider.ConsumeIntegral<uint32_t>();
+ }
+ surroundView3dSession->setViews(views);
+
+ if (surroundView3dSession) {
+ handler = sp<SurroundViewStream>::make(surroundView3dSession);
+
+ if (surroundView3dSession->startStream(handler) == SvResult::OK) {
+ mIs3dStreamStarted = true;
+ }
+ }
while (mFuzzedDataProvider.remaining_bytes() > 0) {
auto surroundView3dFunc = mFuzzedDataProvider.PickValueInArray<
const std::function<void()>>({
[&]() {
- mSurroundViewService->start3dSession(
- [&surroundView3dSession](const sp<ISurroundView3dSession>& session,
- SvResult result) {
- if (result == SvResult::OK) {
- surroundView3dSession = session;
- }
- });
- },
- [&]() {
- if (surroundView3dSession) {
- sp<SurroundViewStream> handler =
- sp<SurroundViewStream>::make(surroundView3dSession);
- surroundView3dSession->startStream(handler);
- mIs3dStreamStarted = true;
- }
- },
- [&]() {
if (surroundView3dSession) {
const size_t numViews =
mFuzzedDataProvider.ConsumeIntegralInRange<size_t>(1, kMaxViews);
@@ -195,7 +204,7 @@
}
},
[&]() {
- if (surroundView3dSession) {
+ if (surroundView3dSession && mIs3dStreamStarted) {
Sv3dConfig config;
config.width = mFuzzedDataProvider.ConsumeIntegralInRange<uint32_t>(
kMinConfigDimension, kMaxConfigDimension);
@@ -306,8 +315,11 @@
}
},
[&]() {
- mSurroundViewService->stop3dSession(
+ SvResult result = mSurroundViewService->stop3dSession(
mFuzzedDataProvider.ConsumeBool() ? surroundView3dSession : nullptr);
+ if (result == SvResult::OK) {
+ mIs3dStreamStarted = false;
+ }
},
});
surroundView3dFunc();
@@ -315,6 +327,10 @@
if (surroundView3dSession && mIs3dStreamStarted) {
surroundView3dSession->stopStream();
}
+
+ if (surroundView3dSession) {
+ mSurroundViewService->stop3dSession(surroundView3dSession);
+ }
}
void SurroundViewFuzzer::process() {
diff --git a/automotive/vehicle/2.0/default/tests/fuzzer/VehicleManager_fuzzer.cpp b/automotive/vehicle/2.0/default/tests/fuzzer/VehicleManager_fuzzer.cpp
index 796c08f..8a085e5 100644
--- a/automotive/vehicle/2.0/default/tests/fuzzer/VehicleManager_fuzzer.cpp
+++ b/automotive/vehicle/2.0/default/tests/fuzzer/VehicleManager_fuzzer.cpp
@@ -161,10 +161,13 @@
hidl_string debugOption = mFuzzedDataProvider->PickValueInArray(
{"--help", "--list", "--get", "--set", "", "invalid"});
hidl_handle fd = {};
- fd.setTo(native_handle_create(/*numFds=*/1, /*numInts=*/0), /*shouldOwn=*/true);
+
+ native_handle_t* rawHandle = native_handle_create(/*numFds=*/1, /*numInts=*/0);
+ fd.setTo(native_handle_clone(rawHandle), /*shouldOwn=*/true);
mManager->debug(fd, {});
mManager->debug(fd, {debugOption});
+ native_handle_delete(rawHandle);
}
void VehicleHalManagerFuzzer::invokePropConfigs() {
diff --git a/automotive/vehicle/OWNERS b/automotive/vehicle/OWNERS
index 429ec39..d6969e5 100644
--- a/automotive/vehicle/OWNERS
+++ b/automotive/vehicle/OWNERS
@@ -1,3 +1,2 @@
ericjeong@google.com
-keunyoung@google.com
shanyu@google.com
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
index f130fa4..e8da43a 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
@@ -99,12 +99,17 @@
const std::shared_ptr<VehiclePropValuePool> mValuePool;
const std::shared_ptr<VehiclePropertyStore> mServerSidePropStore;
+ const std::string mDefaultConfigDir;
+ const std::string mOverrideConfigDir;
+
ValueResultType getValue(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value) const;
VhalResult<void> setValue(
const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
+ bool UseOverrideConfigDir();
+
private:
// Expose private methods to unit test.
friend class FakeVehicleHardwareTestHelper;
@@ -156,8 +161,6 @@
aidl::android::hardware::automotive::vehicle::SetValueRequest>
mPendingSetValueRequests;
- const std::string mDefaultConfigDir;
- const std::string mOverrideConfigDir;
const bool mForceOverride;
bool mAddExtraTestVendorConfigs;
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
index 73defe2..13c48c6 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
@@ -241,6 +241,8 @@
std::string overrideConfigDir, bool forceOverride)
: mValuePool(std::make_unique<VehiclePropValuePool>()),
mServerSidePropStore(new VehiclePropertyStore(mValuePool)),
+ mDefaultConfigDir(defaultConfigDir),
+ mOverrideConfigDir(overrideConfigDir),
mFakeObd2Frame(new obd2frame::FakeObd2Frame(mServerSidePropStore)),
mFakeUserHal(new FakeUserHal(mValuePool)),
mRecurrentTimer(new RecurrentTimer()),
@@ -248,8 +250,6 @@
[this](const VehiclePropValue& value) { eventFromVehicleBus(value); })),
mPendingGetValueRequests(this),
mPendingSetValueRequests(this),
- mDefaultConfigDir(defaultConfigDir),
- mOverrideConfigDir(overrideConfigDir),
mForceOverride(forceOverride) {
init();
}
@@ -260,11 +260,15 @@
mGeneratorHub.reset();
}
+bool FakeVehicleHardware::UseOverrideConfigDir() {
+ return mForceOverride ||
+ android::base::GetBoolProperty(OVERRIDE_PROPERTY, /*default_value=*/false);
+}
+
std::unordered_map<int32_t, ConfigDeclaration> FakeVehicleHardware::loadConfigDeclarations() {
std::unordered_map<int32_t, ConfigDeclaration> configsByPropId;
loadPropConfigsFromDir(mDefaultConfigDir, &configsByPropId);
- if (mForceOverride ||
- android::base::GetBoolProperty(OVERRIDE_PROPERTY, /*default_value=*/false)) {
+ if (UseOverrideConfigDir()) {
loadPropConfigsFromDir(mOverrideConfigDir, &configsByPropId);
}
return configsByPropId;
diff --git a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h
index e740da7..ddd620e 100644
--- a/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h
@@ -82,6 +82,10 @@
bool waitForConnected(std::chrono::milliseconds waitTime);
+ protected:
+ std::shared_mutex mCallbackMutex;
+ std::unique_ptr<const PropertyChangeCallback> mOnPropChange;
+
private:
void ValuePollingLoop();
@@ -90,8 +94,6 @@
std::unique_ptr<proto::VehicleServer::Stub> mGrpcStub;
std::thread mValuePollingThread;
- std::shared_mutex mCallbackMutex;
- std::unique_ptr<const PropertyChangeCallback> mOnPropChange;
std::unique_ptr<const PropertySetErrorCallback> mOnSetErr;
std::mutex mShutdownMutex;
diff --git a/automotive/vehicle/proto/Android.bp b/automotive/vehicle/proto/Android.bp
index 683f128..e7dabcf 100644
--- a/automotive/vehicle/proto/Android.bp
+++ b/automotive/vehicle/proto/Android.bp
@@ -27,6 +27,7 @@
visibility: [
"//hardware/interfaces/automotive/vehicle:__subpackages__",
"//device/generic/car/emulator:__subpackages__",
+ "//system/software_defined_vehicle/core_services:__subpackages__",
],
vendor: true,
host_supported: true,
diff --git a/biometrics/common/util/include/util/Util.h b/biometrics/common/util/include/util/Util.h
index da19dc6..efd66bc 100644
--- a/biometrics/common/util/include/util/Util.h
+++ b/biometrics/common/util/include/util/Util.h
@@ -23,6 +23,9 @@
#include <thread>
#include <vector>
+#include <android-base/parseint.h>
+using ::android::base::ParseInt;
+
namespace aidl::android::hardware::biometrics {
#define SLEEP_MS(x) \
@@ -64,6 +67,87 @@
std::sregex_token_iterator());
return parts;
}
+
+ // Returns a vector of integers for the string separated by comma,
+ // Empty vector is returned if there is any parsing error
+ static std::vector<int32_t> parseIntSequence(const std::string& str,
+ const std::string& sep = ",") {
+ std::vector<std::string> seqs = Util::split(str, sep);
+ std::vector<int32_t> res;
+
+ for (const auto& seq : seqs) {
+ int32_t val;
+ if (ParseInt(seq, &val)) {
+ res.push_back(val);
+ } else {
+ LOG(WARNING) << "Invalid int sequence:" + str + " seq:" + seq;
+ res.clear();
+ break;
+ }
+ }
+
+ return res;
+ }
+
+ // Parses a single enrollment stage string in the format of
+ // enroll_stage_spec: <duration>[-acquiredInfos]
+ // duration: integerInMs
+ // acquiredInfos: [info1,info2,...]
+ //
+ // Returns false if there is parsing error
+ //
+ static bool parseEnrollmentCaptureSingle(const std::string& str,
+ std::vector<std::vector<int32_t>>& res) {
+ std::vector<int32_t> defaultAcquiredInfo = {1};
+ bool aborted = true;
+
+ do {
+ std::smatch sms;
+ // Parses strings like "1000-[5,1]" or "500"
+ std::regex ex("((\\d+)(-\\[([\\d|,]+)\\])?)");
+ if (!regex_match(str.cbegin(), str.cend(), sms, ex)) break;
+ int32_t duration;
+ if (!ParseInt(sms.str(2), &duration)) break;
+ res.push_back({duration});
+ if (!sms.str(4).empty()) {
+ auto acqv = parseIntSequence(sms.str(4));
+ if (acqv.empty()) break;
+ res.push_back(acqv);
+ } else
+ res.push_back(defaultAcquiredInfo);
+ aborted = false;
+ } while (0);
+
+ return !aborted;
+ }
+
+ // Parses enrollment string consisting of one or more stages in the formst of
+ // <enroll_stage_spec>[,enroll_stage_spec,...]
+ // Empty vector is returned in case of parsing error
+ static std::vector<std::vector<int32_t>> parseEnrollmentCapture(const std::string& str) {
+ std::vector<std::vector<int32_t>> res;
+
+ std::string s(str);
+ s.erase(std::remove_if(s.begin(), s.end(), ::isspace), s.end());
+ bool aborted = false;
+ std::smatch sms;
+ // Parses strings like "1000-[5,1],500,800-[6,5,1]"
+ // -------------- ----- ---------------
+ // into parts: A B C
+ while (regex_search(s, sms, std::regex("^(,)?(\\d+(-\\[[\\d|,]+\\])?)"))) {
+ if (!parseEnrollmentCaptureSingle(sms.str(2), res)) {
+ aborted = true;
+ break;
+ }
+ s = sms.suffix();
+ }
+ if (aborted || s.length() != 0) {
+ res.clear();
+ LOG(ERROR) << "Failed to parse enrollment captures:" + str;
+ }
+
+ return res;
+ }
};
} // namespace aidl::android::hardware::biometrics
diff --git a/biometrics/face/aidl/default/FakeFaceEngine.cpp b/biometrics/face/aidl/default/FakeFaceEngine.cpp
index 0f088f4..578231d 100644
--- a/biometrics/face/aidl/default/FakeFaceEngine.cpp
+++ b/biometrics/face/aidl/default/FakeFaceEngine.cpp
@@ -136,56 +136,127 @@
const std::future<void>& cancel) {
BEGIN_OP(FaceHalProperties::operation_authenticate_latency().value_or(0));
- // Signal to the framework that we have begun authenticating.
- AuthenticationFrame frame;
- frame.data.acquiredInfo = AcquiredInfo::START;
- frame.data.vendorCode = 0;
- cb->onAuthenticationFrame(frame);
-
- // Also signal that we have opened the camera.
- frame = {};
- frame.data.acquiredInfo = AcquiredInfo::FIRST_FRAME_RECEIVED;
- frame.data.vendorCode = 0;
- cb->onAuthenticationFrame(frame);
-
- auto now = Util::getSystemNanoTime();
- int64_t duration = FaceHalProperties::operation_authenticate_duration().value_or(0);
- if (duration > 0) {
- do {
- SLEEP_MS(5);
- } while (!Util::hasElapsed(now, duration));
- }
-
- if (FaceHalProperties::operation_authenticate_fails().value_or(false)) {
- LOG(ERROR) << "Fail: operation_authenticate_fails";
- cb->onError(Error::VENDOR, 0 /* vendorError */);
- return;
- }
-
- if (FaceHalProperties::lockout().value_or(false)) {
- LOG(ERROR) << "Fail: lockout";
- cb->onLockoutPermanent();
- cb->onError(Error::HW_UNAVAILABLE, 0 /* vendorError */);
- return;
- }
-
- if (shouldCancel(cancel)) {
- LOG(ERROR) << "Fail: cancel";
- cb->onError(Error::CANCELED, 0 /* vendorCode */);
- return;
- }
-
auto id = FaceHalProperties::enrollment_hit().value_or(0);
auto enrolls = FaceHalProperties::enrollments();
auto isEnrolled = std::find(enrolls.begin(), enrolls.end(), id) != enrolls.end();
- if (id < 0 || !isEnrolled) {
- LOG(ERROR) << (isEnrolled ? "invalid enrollment hit" : "Fail: not enrolled");
- cb->onAuthenticationFailed();
+
+ auto vec2str = [](std::vector<AcquiredInfo> va) {
+ std::stringstream ss;
+ bool isFirst = true;
+ for (auto ac : va) {
+ if (!isFirst) ss << ",";
+ ss << std::to_string((int8_t)ac);
+ isFirst = false;
+ }
+ return ss.str();
+ };
+
+ // default behavior mimic face sensor in U
+ int64_t defaultAuthDuration = 500;
+ std::string defaultAcquiredInfo =
+ vec2str({AcquiredInfo::START, AcquiredInfo::FIRST_FRAME_RECEIVED});
+ if (!isEnrolled) {
+ std::vector<AcquiredInfo> v;
+ for (int i = 0; i < 56; i++) v.push_back(AcquiredInfo::NOT_DETECTED);
+ defaultAcquiredInfo += "," + vec2str(v);
+ defaultAuthDuration = 2100;
+ } else {
+ defaultAcquiredInfo += "," + vec2str({AcquiredInfo::TOO_BRIGHT, AcquiredInfo::TOO_BRIGHT,
+ AcquiredInfo::TOO_BRIGHT, AcquiredInfo::TOO_BRIGHT,
+ AcquiredInfo::GOOD, AcquiredInfo::GOOD});
+ }
+
+ int64_t now = Util::getSystemNanoTime();
+ int64_t duration =
+ FaceHalProperties::operation_authenticate_duration().value_or(defaultAuthDuration);
+ auto acquired =
+ FaceHalProperties::operation_authenticate_acquired().value_or(defaultAcquiredInfo);
+ auto acquiredInfos = Util::parseIntSequence(acquired);
+ int N = acquiredInfos.size();
+
+ if (N == 0) {
+ LOG(ERROR) << "Fail to parse authentiate acquired info: " + acquired;
cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
return;
}
- cb->onAuthenticationSucceeded(id, {} /* hat */);
+ int i = 0;
+ do {
+ if (FaceHalProperties::lockout().value_or(false)) {
+ LOG(ERROR) << "Fail: lockout";
+ cb->onLockoutPermanent();
+ cb->onError(Error::HW_UNAVAILABLE, 0 /* vendorError */);
+ return;
+ }
+
+ if (FaceHalProperties::operation_authenticate_fails().value_or(false)) {
+ LOG(ERROR) << "Fail: operation_authenticate_fails";
+ cb->onAuthenticationFailed();
+ return;
+ }
+
+ auto err = FaceHalProperties::operation_authenticate_error().value_or(0);
+ if (err != 0) {
+ LOG(ERROR) << "Fail: operation_authenticate_error";
+ auto ec = convertError(err);
+ cb->onError(ec.first, ec.second);
+ return; /* simply terminating current operation for any user inserted error,
+ revisit if tests need*/
+ }
+
+ if (shouldCancel(cancel)) {
+ LOG(ERROR) << "Fail: cancel";
+ cb->onError(Error::CANCELED, 0 /* vendorCode */);
+ return;
+ }
+
+ if (i < N) {
+ auto ac = convertAcquiredInfo(acquiredInfos[i]);
+ AuthenticationFrame frame;
+ frame.data.acquiredInfo = ac.first;
+ frame.data.vendorCode = ac.second;
+ cb->onAuthenticationFrame(frame);
+ LOG(INFO) << "AcquiredInfo:" << i << ": (" << (int)ac.first << "," << (int)ac.second
+ << ")";
+ i++;
+ }
+
+ SLEEP_MS(duration / N);
+ } while (!Util::hasElapsed(now, duration));
+
+ if (id > 0 && isEnrolled) {
+ cb->onAuthenticationSucceeded(id, {} /* hat */);
+ return;
+ } else {
+ LOG(ERROR) << "Fail: face not enrolled";
+ cb->onAuthenticationFailed();
+ cb->onError(Error::TIMEOUT, 0 /* vendorError*/);
+ return;
+ }
+}
+
+std::pair<AcquiredInfo, int32_t> FakeFaceEngine::convertAcquiredInfo(int32_t code) {
+ std::pair<AcquiredInfo, int32_t> res;
+ if (code > FACE_ACQUIRED_VENDOR_BASE) {
+ res.first = AcquiredInfo::VENDOR;
+ res.second = code - FACE_ACQUIRED_VENDOR_BASE;
+ } else {
+ res.first = (AcquiredInfo)code;
+ res.second = 0;
+ }
+ return res;
+}
+
+std::pair<Error, int32_t> FakeFaceEngine::convertError(int32_t code) {
+ std::pair<Error, int32_t> res;
+ if (code > FACE_ERROR_VENDOR_BASE) {
+ res.first = Error::VENDOR;
+ res.second = code - FACE_ERROR_VENDOR_BASE;
+ } else {
+ res.first = (Error)code;
+ res.second = 0;
+ }
+ return res;
}
void FakeFaceEngine::detectInteractionImpl(ISessionCallback* cb, const std::future<void>& cancel) {
@@ -315,4 +386,4 @@
cb->onLockoutCleared();
}
-} // namespace aidl::android::hardware::biometrics::face
\ No newline at end of file
+} // namespace aidl::android::hardware::biometrics::face
diff --git a/biometrics/face/aidl/default/FakeFaceEngine.h b/biometrics/face/aidl/default/FakeFaceEngine.h
index eb99441..06dd396 100644
--- a/biometrics/face/aidl/default/FakeFaceEngine.h
+++ b/biometrics/face/aidl/default/FakeFaceEngine.h
@@ -62,6 +62,12 @@
void resetLockoutImpl(ISessionCallback* cb, const keymaster::HardwareAuthToken& /*hat*/);
std::mt19937 mRandom;
+
+ private:
+ static constexpr int32_t FACE_ACQUIRED_VENDOR_BASE = 1000;
+ static constexpr int32_t FACE_ERROR_VENDOR_BASE = 1000;
+ std::pair<AcquiredInfo, int32_t> convertAcquiredInfo(int32_t code);
+ std::pair<Error, int32_t> convertError(int32_t code);
};
} // namespace aidl::android::hardware::biometrics::face
diff --git a/biometrics/face/aidl/default/README.md b/biometrics/face/aidl/default/README.md
index 77bfe57..516a7aa 100644
--- a/biometrics/face/aidl/default/README.md
+++ b/biometrics/face/aidl/default/README.md
@@ -18,6 +18,7 @@
Face VHAL enabling is gated by the following two AND conditions:
1. The Face VHAL feature flag (as part of Trunk-development strategy) must be tured until the flags life-cycle ends.
2. The Face VHAL must be enabled via sysprop
+See adb commands below
##Getting Stared
@@ -47,8 +48,7 @@
$ adb shell setprop vendor.face.virtual.operation_authenticate_duration 800
$ adb shell setprop vendor.face.virtual.enrollment_hit 1
```
-Note: At the initial phase of the Face VHAL development, Face-on-camera simulation is not supported, hence
-the authentication immediately occurrs as soon as the authentication request arriving at VHAL.
+Refer to face.sysprop for full supported features of authentication, such as error and acquiredInfo insertion
## Enrollment via Setup
diff --git a/biometrics/face/aidl/default/face.sysprop b/biometrics/face/aidl/default/face.sysprop
index 6b0f37f..be32015 100644
--- a/biometrics/face/aidl/default/face.sysprop
+++ b/biometrics/face/aidl/default/face.sysprop
@@ -157,3 +157,22 @@
access: ReadWrite
api_name: "operation_authenticate_duration"
}
+
+# insert error for authenticate operations
+prop {
+ prop_name: "vendor.face.virtual.operation_authenticate_error"
+ type: Integer
+ scope: Internal
+ access: ReadWrite
+ api_name: "operation_authenticate_error"
+}
+
+# acquired info during authentication in format of sequence
+prop {
+ prop_name: "vendor.face.virtual.operation_authenticate_acquired"
+ type: String
+ scope: Internal
+ access: ReadWrite
+ api_name: "operation_authenticate_acquired"
+}
+
diff --git a/biometrics/face/aidl/default/tests/FakeFaceEngineTest.cpp b/biometrics/face/aidl/default/tests/FakeFaceEngineTest.cpp
index c8ad6b7..6897dc4 100644
--- a/biometrics/face/aidl/default/tests/FakeFaceEngineTest.cpp
+++ b/biometrics/face/aidl/default/tests/FakeFaceEngineTest.cpp
@@ -245,7 +245,7 @@
FaceHalProperties::enrollments({3});
FaceHalProperties::enrollment_hit(100);
mEngine.authenticateImpl(mCallback.get(), 0 /* operationId*/, mCancel.get_future());
- ASSERT_EQ(Error::UNABLE_TO_PROCESS, mCallback->mError);
+ ASSERT_EQ(Error::TIMEOUT, mCallback->mError);
ASSERT_TRUE(mCallback->mAuthenticateFailed);
}
@@ -380,4 +380,4 @@
ASSERT_FALSE(mCallback->mAuthenticateFailed);
}
-} // namespace aidl::android::hardware::biometrics::face
\ No newline at end of file
+} // namespace aidl::android::hardware::biometrics::face
diff --git a/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp b/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
index 54076c8..574570e 100644
--- a/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
+++ b/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
@@ -142,7 +142,7 @@
return true;
}
auto enrollmentId = std::stoi(parts[0]);
- auto progress = parseEnrollmentCapture(parts[1]);
+ auto progress = Util::parseEnrollmentCapture(parts[1]);
for (size_t i = 0; i < progress.size(); i += 2) {
auto left = (progress.size() - i) / 2 - 1;
auto duration = progress[i][0];
@@ -193,7 +193,7 @@
int64_t now = Util::getSystemNanoTime();
int64_t duration = FingerprintHalProperties::operation_authenticate_duration().value_or(10);
auto acquired = FingerprintHalProperties::operation_authenticate_acquired().value_or("1");
- auto acquiredInfos = parseIntSequence(acquired);
+ auto acquiredInfos = Util::parseIntSequence(acquired);
int N = acquiredInfos.size();
if (N == 0) {
@@ -271,7 +271,7 @@
FingerprintHalProperties::operation_detect_interaction_duration().value_or(10);
auto acquired = FingerprintHalProperties::operation_detect_interaction_acquired().value_or("1");
- auto acquiredInfos = parseIntSequence(acquired);
+ auto acquiredInfos = Util::parseIntSequence(acquired);
int N = acquiredInfos.size();
int64_t now = Util::getSystemNanoTime();
@@ -450,76 +450,6 @@
return SensorLocation();
}
-std::vector<int32_t> FakeFingerprintEngine::parseIntSequence(const std::string& str,
- const std::string& sep) {
- std::vector<std::string> seqs = Util::split(str, sep);
- std::vector<int32_t> res;
-
- for (const auto& seq : seqs) {
- int32_t val;
- if (ParseInt(seq, &val)) {
- res.push_back(val);
- } else {
- LOG(WARNING) << "Invalid int sequence:" + str;
- res.clear();
- break;
- }
- }
-
- return res;
-}
-
-bool FakeFingerprintEngine::parseEnrollmentCaptureSingle(const std::string& str,
- std::vector<std::vector<int32_t>>& res) {
- std::vector<int32_t> defaultAcquiredInfo = {(int32_t)AcquiredInfo::GOOD};
- bool aborted = true;
-
- do {
- std::smatch sms;
- // Parses strings like "1000-[5,1]" or "500"
- std::regex ex("((\\d+)(-\\[([\\d|,]+)\\])?)");
- if (!regex_match(str.cbegin(), str.cend(), sms, ex)) break;
- int32_t duration;
- if (!ParseInt(sms.str(2), &duration)) break;
- res.push_back({duration});
- if (!sms.str(4).empty()) {
- auto acqv = parseIntSequence(sms.str(4));
- if (acqv.empty()) break;
- res.push_back(acqv);
- } else
- res.push_back(defaultAcquiredInfo);
- aborted = false;
- } while (0);
-
- return !aborted;
-}
-
-std::vector<std::vector<int32_t>> FakeFingerprintEngine::parseEnrollmentCapture(
- const std::string& str) {
- std::vector<std::vector<int32_t>> res;
-
- std::string s(str);
- s.erase(std::remove_if(s.begin(), s.end(), ::isspace), s.end());
- bool aborted = false;
- std::smatch sms;
- // Parses strings like "1000-[5,1],500,800-[6,5,1]"
- // ---------- --- -----------
- // into parts: A B C
- while (regex_search(s, sms, std::regex("^(,)?(\\d+(-\\[[\\d|,]+\\])?)"))) {
- if (!parseEnrollmentCaptureSingle(sms.str(2), res)) {
- aborted = true;
- break;
- }
- s = sms.suffix();
- }
- if (aborted || s.length() != 0) {
- res.clear();
- LOG(ERROR) << "Failed to parse enrollment captures:" + str;
- }
-
- return res;
-}
-
std::pair<AcquiredInfo, int32_t> FakeFingerprintEngine::convertAcquiredInfo(int32_t code) {
std::pair<AcquiredInfo, int32_t> res;
if (code > FINGERPRINT_ACQUIRED_VENDOR_BASE) {
diff --git a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
index 2450115..15d8360 100644
--- a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
+++ b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
@@ -68,10 +68,6 @@
virtual void fingerDownAction();
- std::vector<int32_t> parseIntSequence(const std::string& str, const std::string& sep = ",");
-
- std::vector<std::vector<int32_t>> parseEnrollmentCapture(const std::string& str);
-
int32_t getLatency(const std::vector<std::optional<std::int32_t>>& latencyVec);
std::mt19937 mRandom;
@@ -110,8 +106,6 @@
static constexpr int32_t FINGERPRINT_ERROR_VENDOR_BASE = 1000;
std::pair<AcquiredInfo, int32_t> convertAcquiredInfo(int32_t code);
std::pair<Error, int32_t> convertError(int32_t code);
- bool parseEnrollmentCaptureSingle(const std::string& str,
- std::vector<std::vector<int32_t>>& res);
int32_t getRandomInRange(int32_t bound1, int32_t bound2);
bool checkSensorLockout(ISessionCallback*);
void clearLockout(ISessionCallback* cb);
diff --git a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
index fe405f4..45b5be8 100644
--- a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
+++ b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
@@ -421,29 +421,29 @@
TEST_F(FakeFingerprintEngineTest, parseIntSequence) {
std::vector<int32_t> seqV;
- seqV = mEngine.parseIntSequence("");
+ seqV = Util::parseIntSequence("");
ASSERT_EQ(0, seqV.size());
- seqV = mEngine.parseIntSequence("2");
+ seqV = Util::parseIntSequence("2");
ASSERT_EQ(1, seqV.size());
ASSERT_EQ(2, seqV[0]);
- seqV = mEngine.parseIntSequence("2,3,4");
+ seqV = Util::parseIntSequence("2,3,4");
std::vector<int32_t> expV{2, 3, 4};
ASSERT_EQ(expV, seqV);
- seqV = mEngine.parseIntSequence("2,3,a");
+ seqV = Util::parseIntSequence("2,3,a");
ASSERT_EQ(0, seqV.size());
- seqV = mEngine.parseIntSequence("2, 3, 4");
+ seqV = Util::parseIntSequence("2, 3, 4");
ASSERT_EQ(expV, seqV);
- seqV = mEngine.parseIntSequence("123,456");
+ seqV = Util::parseIntSequence("123,456");
ASSERT_EQ(2, seqV.size());
std::vector<int32_t> expV1{123, 456};
ASSERT_EQ(expV1, seqV);
- seqV = mEngine.parseIntSequence("12f3,456");
+ seqV = Util::parseIntSequence("12f3,456");
ASSERT_EQ(0, seqV.size());
}
TEST_F(FakeFingerprintEngineTest, parseEnrollmentCaptureOk) {
std::vector<std::vector<int32_t>> ecV;
- ecV = mEngine.parseEnrollmentCapture("100,200,300");
+ ecV = Util::parseEnrollmentCapture("100,200,300");
ASSERT_EQ(6, ecV.size());
std::vector<std::vector<int32_t>> expE{{100}, {200}, {300}};
std::vector<int32_t> defC{1};
@@ -451,26 +451,26 @@
ASSERT_EQ(expE[i / 2], ecV[i]);
ASSERT_EQ(defC, ecV[i + 1]);
}
- ecV = mEngine.parseEnrollmentCapture("100");
+ ecV = Util::parseEnrollmentCapture("100");
ASSERT_EQ(2, ecV.size());
ASSERT_EQ(expE[0], ecV[0]);
ASSERT_EQ(defC, ecV[1]);
- ecV = mEngine.parseEnrollmentCapture("100-[5,6,7]");
+ ecV = Util::parseEnrollmentCapture("100-[5,6,7]");
std::vector<int32_t> expC{5, 6, 7};
ASSERT_EQ(2, ecV.size());
for (int i = 0; i < ecV.size(); i += 2) {
ASSERT_EQ(expE[i / 2], ecV[i]);
ASSERT_EQ(expC, ecV[i + 1]);
}
- ecV = mEngine.parseEnrollmentCapture("100-[5,6,7], 200, 300-[9,10]");
+ ecV = Util::parseEnrollmentCapture("100-[5,6,7], 200, 300-[9,10]");
std::vector<std::vector<int32_t>> expC1{{5, 6, 7}, {1}, {9, 10}};
ASSERT_EQ(6, ecV.size());
for (int i = 0; i < ecV.size(); i += 2) {
ASSERT_EQ(expE[i / 2], ecV[i]);
ASSERT_EQ(expC1[i / 2], ecV[i + 1]);
}
- ecV = mEngine.parseEnrollmentCapture("100-[5,6,7], 200-[2,1], 300-[9]");
+ ecV = Util::parseEnrollmentCapture("100-[5,6,7], 200-[2,1], 300-[9]");
std::vector<std::vector<int32_t>> expC2{{5, 6, 7}, {2, 1}, {9}};
ASSERT_EQ(ecV.size(), 6);
for (int i = 0; i < ecV.size(); i += 2) {
@@ -484,7 +484,7 @@
"100,2x0,300", "200-[f]", "a,b"};
std::vector<std::vector<int32_t>> ecV;
for (const auto& s : badStr) {
- ecV = mEngine.parseEnrollmentCapture(s);
+ ecV = Util::parseEnrollmentCapture(s);
ASSERT_EQ(ecV.size(), 0);
}
}
@@ -508,7 +508,7 @@
TEST_F(FakeFingerprintEngineTest, lockoutTimer) {
mEngine.startLockoutTimer(200, mCallback.get());
ASSERT_TRUE(mEngine.getLockoutTimerStarted());
- std::this_thread::sleep_for(std::chrono::milliseconds(210));
+ std::this_thread::sleep_for(std::chrono::milliseconds(230));
ASSERT_FALSE(mEngine.getLockoutTimerStarted());
ASSERT_TRUE(mCallback->mLockoutCleared);
}
diff --git a/boot/1.1/default/Android.bp b/boot/1.1/default/Android.bp
index e7a8d6e..0b0a5b7 100644
--- a/boot/1.1/default/Android.bp
+++ b/boot/1.1/default/Android.bp
@@ -20,7 +20,6 @@
srcs: ["BootControl.cpp"],
shared_libs: [
- "libbase",
"liblog",
"libhidlbase",
"libhardware",
diff --git a/boot/1.1/default/boot_control/Android.bp b/boot/1.1/default/boot_control/Android.bp
index d0dcb59..6aa30c2 100644
--- a/boot/1.1/default/boot_control/Android.bp
+++ b/boot/1.1/default/boot_control/Android.bp
@@ -35,13 +35,14 @@
],
shared_libs: [
+ "android.hardware.boot@1.1",
+ "libbase",
"liblog",
],
static_libs: [
"libbootloader_message",
"libfstab",
],
-
}
cc_library_static {
@@ -51,13 +52,7 @@
recovery_available: true,
vendor_available: true,
- srcs: [
- "libboot_control.cpp",
- ],
- static_libs: [
- "android.hardware.boot@1.1",
- "libbase",
- ],
+ srcs: ["libboot_control.cpp"],
}
cc_library_shared {
@@ -72,8 +67,6 @@
"libboot_control",
],
shared_libs: [
- "android.hardware.boot@1.1",
- "libbase",
"libhardware",
],
}
diff --git a/boot/1.2/default/Android.bp b/boot/1.2/default/Android.bp
index f1e9c34..4e1c35e 100644
--- a/boot/1.2/default/Android.bp
+++ b/boot/1.2/default/Android.bp
@@ -20,7 +20,6 @@
srcs: ["BootControl.cpp"],
shared_libs: [
- "libbase",
"liblog",
"libhidlbase",
"libhardware",
diff --git a/boot/aidl/default/Android.bp b/boot/aidl/default/Android.bp
index c1d3c57..dcb40db 100644
--- a/boot/aidl/default/Android.bp
+++ b/boot/aidl/default/Android.bp
@@ -27,77 +27,29 @@
name: "android.hardware.boot-service_common",
relative_install_path: "hw",
defaults: ["libboot_control_defaults"],
- srcs: [
- "main.cpp",
- "BootControl.cpp",
+ vintf_fragments: ["android.hardware.boot-service.default.xml"],
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "android.hardware.boot@1.1",
+ "android.hardware.boot-V1-ndk",
],
+ static_libs: [
+ "libboot_control",
+ ],
+ srcs: ["main.cpp", "BootControl.cpp"],
}
cc_binary {
name: "android.hardware.boot-service.default",
defaults: ["android.hardware.boot-service_common"],
+ init_rc: ["android.hardware.boot-service.default.rc"],
vendor: true,
-
- stl: "c++_static",
- shared_libs: [
- "libbinder_ndk",
- "liblog",
- ],
- static_libs: [
- "android.hardware.boot@1.1",
- "android.hardware.boot-V1-ndk",
- "libbase",
- "libboot_control",
- ],
-
- installable: false, // installed in APEX
}
cc_binary {
name: "android.hardware.boot-service.default_recovery",
defaults: ["android.hardware.boot-service_common"],
init_rc: ["android.hardware.boot-service.default_recovery.rc"],
- vintf_fragments: ["android.hardware.boot-service.default.xml"],
recovery: true,
-
- shared_libs: [
- "libbase",
- "libbinder_ndk",
- "android.hardware.boot@1.1",
- "android.hardware.boot-V1-ndk",
- ],
- static_libs: [
- "libboot_control",
- ],
-}
-
-prebuilt_etc {
- name: "android.hardware.boot-service.default.rc",
- src: "android.hardware.boot-service.default.rc",
- installable: false,
-}
-
-prebuilt_etc {
- name: "android.hardware.boot-service.default.xml",
- src: "android.hardware.boot-service.default.xml",
- sub_dir: "vintf",
- installable: false,
-}
-
-apex {
- name: "com.android.hardware.boot",
- vendor: true,
- manifest: "apex_manifest.json",
- file_contexts: "apex_file_contexts",
- key: "com.android.hardware.key",
- certificate: ":com.android.hardware.certificate",
- updatable: false,
-
- binaries: [
- "android.hardware.boot-service.default",
- ],
- prebuilts: [
- "android.hardware.boot-service.default.rc",
- "android.hardware.boot-service.default.xml",
- ],
}
diff --git a/boot/aidl/default/android.hardware.boot-service.default.rc b/boot/aidl/default/android.hardware.boot-service.default.rc
index 5090e2c..589f803 100644
--- a/boot/aidl/default/android.hardware.boot-service.default.rc
+++ b/boot/aidl/default/android.hardware.boot-service.default.rc
@@ -1,4 +1,4 @@
-service vendor.boot-default /apex/com.android.hardware.boot/bin/hw/android.hardware.boot-service.default
+service vendor.boot-default /vendor/bin/hw/android.hardware.boot-service.default
class early_hal
user root
group root
diff --git a/boot/aidl/default/apex_file_contexts b/boot/aidl/default/apex_file_contexts
deleted file mode 100644
index bf03585..0000000
--- a/boot/aidl/default/apex_file_contexts
+++ /dev/null
@@ -1,3 +0,0 @@
-(/.*)? u:object_r:vendor_file:s0
-/etc(/.*)? u:object_r:vendor_configs_file:s0
-/bin/hw/android\.hardware\.boot-service\.default u:object_r:hal_bootctl_default_exec:s0
diff --git a/boot/aidl/default/apex_manifest.json b/boot/aidl/default/apex_manifest.json
deleted file mode 100644
index 92661c9..0000000
--- a/boot/aidl/default/apex_manifest.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "name": "com.android.hardware.boot",
- "version": 1,
- "vendorBootstrap": true
-}
\ No newline at end of file
diff --git a/camera/metadata/aidl/Android.bp b/camera/metadata/aidl/Android.bp
index 5872a86..2b2be55 100644
--- a/camera/metadata/aidl/Android.bp
+++ b/camera/metadata/aidl/Android.bp
@@ -11,7 +11,7 @@
name: "android.hardware.camera.metadata",
vendor_available: true,
srcs: ["android/hardware/camera/metadata/*.aidl"],
- frozen: true,
+ frozen: false,
stability: "vintf",
backend: {
cpp: {
diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataTag.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataTag.aidl
index 71d4e41..0290aef 100644
--- a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataTag.aidl
+++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataTag.aidl
@@ -108,6 +108,11 @@
ANDROID_FLASH_COLOR_TEMPERATURE,
ANDROID_FLASH_MAX_ENERGY,
ANDROID_FLASH_STATE,
+ ANDROID_FLASH_STRENGTH_LEVEL,
+ ANDROID_FLASH_SINGLE_STRENGTH_MAX_LEVEL,
+ ANDROID_FLASH_SINGLE_STRENGTH_DEFAULT_LEVEL,
+ ANDROID_FLASH_TORCH_STRENGTH_MAX_LEVEL,
+ ANDROID_FLASH_TORCH_STRENGTH_DEFAULT_LEVEL,
ANDROID_FLASH_INFO_AVAILABLE = android.hardware.camera.metadata.CameraMetadataSectionStart.ANDROID_FLASH_INFO_START /* 327680 */,
ANDROID_FLASH_INFO_CHARGE_DURATION,
ANDROID_FLASH_INFO_STRENGTH_MAXIMUM_LEVEL,
diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl
index 56aa690..dd679f3 100644
--- a/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl
+++ b/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl
@@ -560,6 +560,36 @@
*/
ANDROID_FLASH_STATE,
/**
+ * android.flash.strengthLevel [dynamic, int32, public]
+ *
+ * <p>Flash strength level to be used when manual flash control is active.</p>
+ */
+ ANDROID_FLASH_STRENGTH_LEVEL,
+ /**
+ * android.flash.singleStrengthMaxLevel [static, int32, public]
+ *
+ * <p>Maximum flash brightness level for manual flash control in SINGLE mode.</p>
+ */
+ ANDROID_FLASH_SINGLE_STRENGTH_MAX_LEVEL,
+ /**
+ * android.flash.singleStrengthDefaultLevel [static, int32, public]
+ *
+ * <p>Default flash brightness level for manual flash control in SINGLE mode.</p>
+ */
+ ANDROID_FLASH_SINGLE_STRENGTH_DEFAULT_LEVEL,
+ /**
+ * android.flash.torchStrengthMaxLevel [static, int32, public]
+ *
+ * <p>Maximum flash brightness level for manual flash control in TORCH mode</p>
+ */
+ ANDROID_FLASH_TORCH_STRENGTH_MAX_LEVEL,
+ /**
+ * android.flash.torchStrengthDefaultLevel [static, int32, public]
+ *
+ * <p>Default flash brightness level for manual flash control in TORCH mode</p>
+ */
+ ANDROID_FLASH_TORCH_STRENGTH_DEFAULT_LEVEL,
+ /**
* android.flash.info.available [static, enum, public]
*
* <p>Whether this camera device has a
diff --git a/common/fmq/aidl/Android.bp b/common/fmq/aidl/Android.bp
index 3b022fc..6c37213 100644
--- a/common/fmq/aidl/Android.bp
+++ b/common/fmq/aidl/Android.bp
@@ -43,8 +43,9 @@
min_sdk_version: "29",
},
rust: {
- // FMQ is not supported in the rust backend
- enabled: false,
+ // FMQ is not supported in the rust backend, but we need this AIDL interface for
+ // HardwareBuffer.
+ enabled: true,
},
},
frozen: true,
diff --git a/drm/aidl/vts/Android.bp b/drm/aidl/vts/Android.bp
index 190f60d..5139036 100644
--- a/drm/aidl/vts/Android.bp
+++ b/drm/aidl/vts/Android.bp
@@ -59,13 +59,13 @@
data: [":libvtswidevine-arm-prebuilts"],
},
arm64: {
- data: [":libvtswidevine-arm64-prebuilts"],
+ data: [":libvtswidevine-arm64-prebuilts", ":libvtswidevine-arm-prebuilts"],
},
x86: {
data: [":libvtswidevine-x86-prebuilts"],
},
x86_64: {
- data: [":libvtswidevine-x86_64-prebuilts"],
+ data: [":libvtswidevine-x86_64-prebuilts", ":libvtswidevine-x86-prebuilts"],
},
},
test_suites: [
diff --git a/health/1.0/default/convert.cpp b/health/1.0/default/convert.cpp
index 31b4679..e12e197 100644
--- a/health/1.0/default/convert.cpp
+++ b/health/1.0/default/convert.cpp
@@ -117,7 +117,7 @@
info.batteryCycleCount = p->batteryCycleCount;
info.batteryFullCharge = p->batteryFullCharge;
info.batteryChargeCounter = p->batteryChargeCounter;
- info.batteryTechnology = p->batteryTechnology;
+ info.batteryTechnology = p->batteryTechnology.c_str();
}
void convertFromHealthInfo(const HealthInfo& info,
diff --git a/media/bufferpool/aidl/Android.bp b/media/bufferpool/aidl/Android.bp
index 8caf525..8e013e0 100644
--- a/media/bufferpool/aidl/Android.bp
+++ b/media/bufferpool/aidl/Android.bp
@@ -46,6 +46,9 @@
],
min_sdk_version: "29",
},
+ rust: {
+ enabled: true,
+ },
},
versions_with_info: [
{
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IGraphicBufferAllocator.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IGraphicBufferAllocator.aidl
index da3d5ff..3e460dd 100644
--- a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IGraphicBufferAllocator.aidl
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IGraphicBufferAllocator.aidl
@@ -36,7 +36,7 @@
interface IGraphicBufferAllocator {
android.hardware.media.c2.IGraphicBufferAllocator.Allocation allocate(in android.hardware.media.c2.IGraphicBufferAllocator.Description desc);
boolean deallocate(in long id);
- android.hardware.media.c2.IGraphicBufferAllocator.WaitableFds getWaitableFds();
+ ParcelFileDescriptor getWaitableFd();
parcelable Allocation {
android.hardware.HardwareBuffer buffer;
ParcelFileDescriptor fence;
@@ -47,8 +47,4 @@
int format;
long usage;
}
- parcelable WaitableFds {
- ParcelFileDescriptor allocEvent;
- ParcelFileDescriptor statusEvent;
- }
}
diff --git a/media/c2/aidl/android/hardware/media/c2/IGraphicBufferAllocator.aidl b/media/c2/aidl/android/hardware/media/c2/IGraphicBufferAllocator.aidl
index 1c97214..49c4ea4 100644
--- a/media/c2/aidl/android/hardware/media/c2/IGraphicBufferAllocator.aidl
+++ b/media/c2/aidl/android/hardware/media/c2/IGraphicBufferAllocator.aidl
@@ -75,31 +75,22 @@
boolean deallocate(in long id);
/**
- * Fds for waitable object events.
- *
- * Fds are created by eventfd() with semaphore mode.
- * For allocEvent, An integer counter regarding dequeuable buffer count is maintained
- * by client using read()/write() to the fd. The fd can be checked whether it is
- * readable via poll(). When in readable status, the specified counter is positive
- * so allocate/dequeue can happen.
- *
- * For statusEvent, the client can notify further allocation is not feasible.
- * e.g.) life-cycle of the underlying allocator is ended.
- *
- * C2Fence object should be implemented based on this Fds. Thus, C2Fence can return
- * either by allocation being ready or allocation being infeasible by the client status
- * change.
- */
- parcelable WaitableFds {
- ParcelFileDescriptor allocEvent;
- ParcelFileDescriptor statusEvent;
- }
-
- /**
- * Gets waiable file descriptors.
+ * Gets a waitable file descriptor.
*
* Use this method once and cache it in order not to create unnecessary duplicated fds.
- * The returned array will have two fds.
+ *
+ * Two file descriptors are created by pipe2(), and the reading end will be returned
+ * and shared by this method. Whenever a dequeuable buffer is ready a byte will be
+ * written to the writing end. Whenever a buffer is allocated(or dequeued) a byte will
+ * be read from the reading end.
+ *
+ * The returned file descriptor(the reading end) can be polled whether the read is ready
+ * via ::poll(). If no more allocate() can be fulfilled(by status change or etc.), the
+ * writing end will be closed. In the case, POLLHUP event can be retrieved via ::poll().
+ *
+ * C2Fence object should be implemented based on this Fd. Thus, C2Fence can return
+ * either by allocation being ready or allocation being infeasible by the client status
+ * change.
*
* If many waitable objects based on the same fd are competing, all watiable objects will be
* notified. After being notified, they should invoke allocate(). At least one of them can
@@ -110,5 +101,5 @@
* @return an fd array which will be wrapped to C2Fence and will be waited for
* until allocating is unblocked.
*/
- WaitableFds getWaitableFds();
+ ParcelFileDescriptor getWaitableFd();
}
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 5f8ec0e..3a8a1e8 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -841,7 +841,7 @@
int vendor_api_level = property_get_int32("ro.vendor.api_level", 0);
if (SecLevel() == SecurityLevel::STRONGBOX) {
// This is known to be broken on older vendor implementations.
- if (vendor_api_level < __ANDROID_API_T__) {
+ if (vendor_api_level <= __ANDROID_API_U__) {
compare_output = false;
} else {
additional_information = " (b/194134359) ";
diff --git a/soundtrigger/aidl/cli/java/android/hardware/soundtrigger3/cli/SthalCli.java b/soundtrigger/aidl/cli/java/android/hardware/soundtrigger3/cli/SthalCli.java
index 127f062..41e2533 100644
--- a/soundtrigger/aidl/cli/java/android/hardware/soundtrigger3/cli/SthalCli.java
+++ b/soundtrigger/aidl/cli/java/android/hardware/soundtrigger3/cli/SthalCli.java
@@ -289,6 +289,8 @@
Properties properties = new Properties();
properties.implementor = "Android";
properties.description = "Mock STHAL";
+ properties.uuid = "a5af2d2a-4cc4-4b69-a22f-c9d5b6d492c3";
+ properties.supportedModelArch = "Mock arch";
properties.maxSoundModels = 2;
properties.maxKeyPhrases = 1;
properties.recognitionModes =
diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp
index bb99ae4..46cba93 100644
--- a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp
+++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test.cpp
@@ -48,6 +48,13 @@
virtual void SetUp() override {
wifi_instance_name_ = std::get<0>(GetParam());
hostapd_instance_name_ = std::get<1>(GetParam());
+
+ // Disable Wi-Fi framework to avoid interference
+ isWifiEnabled_ = isWifiFrameworkEnabled();
+ isScanAlwaysEnabled_ = isWifiScanAlwaysAvailable();
+ toggleWifiFramework(false);
+ toggleWifiScanAlwaysAvailable(false);
+
stopSupplicantIfNeeded(wifi_instance_name_);
startHostapdAndWaitForHidlService(wifi_instance_name_,
hostapd_instance_name_);
@@ -58,14 +65,21 @@
virtual void TearDown() override {
HIDL_INVOKE_VOID_WITHOUT_ARGUMENTS(hostapd_, terminate);
stopHostapd(wifi_instance_name_);
+
+ // Restore Wi-Fi framework state
+ toggleWifiFramework(isWifiEnabled_);
+ toggleWifiScanAlwaysAvailable(isScanAlwaysEnabled_);
}
protected:
- std::string getPrimaryWlanIfaceName() {
+ bool isWifiEnabled_ = false;
+ bool isScanAlwaysEnabled_ = false;
+
+ std::string getPrimaryWlanIfaceName() {
std::array<char, PROPERTY_VALUE_MAX> buffer;
property_get("wifi.interface", buffer.data(), "wlan0");
return buffer.data();
- }
+ }
IHostapd::IfaceParams getIfaceParamsWithAcs() {
IHostapd::IfaceParams iface_params;
diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
index 56f285d..4c452fb 100644
--- a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
+++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
@@ -98,3 +98,24 @@
::android::hardware::wifi::hostapd::V1_1::IHostapd::castFrom(hostapd);
return hostapd_1_1.get() != nullptr;
}
+
+void toggleWifiFramework(bool enable) {
+ std::string cmd = "/system/bin/cmd wifi set-wifi-enabled ";
+ cmd += enable ? "enabled" : "disabled";
+ testing::checkSubstringInCommandOutput(cmd.c_str(), "X");
+}
+
+void toggleWifiScanAlwaysAvailable(bool enable) {
+ std::string cmd = "/system/bin/cmd wifi set-scan-always-available ";
+ cmd += enable ? "enabled" : "disabled";
+ testing::checkSubstringInCommandOutput(cmd.c_str(), "X");
+}
+
+bool isWifiFrameworkEnabled() {
+ return testing::checkSubstringInCommandOutput("/system/bin/cmd wifi status", "Wifi is enabled");
+}
+
+bool isWifiScanAlwaysAvailable() {
+ return testing::checkSubstringInCommandOutput("/system/bin/cmd wifi status",
+ "Wifi scanning is always available");
+}
diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h
index 893de1e..aa34c9a 100644
--- a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h
+++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.h
@@ -17,14 +17,17 @@
#ifndef HOSTAPD_HIDL_TEST_UTILS_H
#define HOSTAPD_HIDL_TEST_UTILS_H
+#include <VtsCoreUtil.h>
#include <android/hardware/wifi/hostapd/1.0/IHostapd.h>
#include <android/hardware/wifi/hostapd/1.1/IHostapd.h>
// Used to stop the android wifi framework before every test.
-void stopWifiFramework(const std::string& instance_name);
-void startWifiFramework(const std::string& instance_name);
void stopSupplicantIfNeeded(const std::string& instance_name);
void stopHostapd(const std::string& instance_name);
+void toggleWifiFramework(bool enable);
+void toggleWifiScanAlwaysAvailable(bool enable);
+bool isWifiFrameworkEnabled();
+bool isWifiScanAlwaysAvailable();
// Used to configure the chip, driver and start wpa_hostapd before every
// test.
void startHostapdAndWaitForHidlService(