Combine test parameters into TestConfig structure
am: 0d4ba3f33a
Change-Id: I273f1de1e8ccd379abb8137476104c1cb8a0f514
diff --git a/audio/6.0/IDevice.hal b/audio/6.0/IDevice.hal
index e885fe2..122c550 100644
--- a/audio/6.0/IDevice.hal
+++ b/audio/6.0/IDevice.hal
@@ -280,4 +280,19 @@
*/
setConnectedState(DeviceAddress address, bool connected)
generates (Result retval);
+
+ /**
+ * Called by the framework to deinitialize the device and free up
+ * all currently allocated resources. It is recommended to close
+ * the device on the client side as soon as it is becomes unused.
+ *
+ * Note that all streams must be closed by the client before
+ * attempting to close the device they belong to.
+ *
+ * @return retval OK in case the success.
+ * INVALID_STATE if the device was already closed
+ * or there are streams currently opened.
+ */
+ @exit
+ close() generates (Result retval);
};
diff --git a/audio/6.0/IStream.hal b/audio/6.0/IStream.hal
index 451e116..d7d3c84 100644
--- a/audio/6.0/IStream.hal
+++ b/audio/6.0/IStream.hal
@@ -277,7 +277,7 @@
* @return retval OK in case the success.
* NOT_SUPPORTED on non mmap mode streams
* NOT_INITIALIZED in case of memory allocation error
- * INVALID_ARGUMENTS if the requested buffer size is too large
+ * INVALID_ARGUMENTS if the requested buffer size is invalid
* INVALID_STATE if called out of sequence
* @return info a MmapBufferInfo struct containing information on the MMMAP buffer created.
*/
@@ -300,13 +300,17 @@
/**
* Called by the framework to deinitialize the stream and free up
- * all the currently allocated resources. It is recommended to close
+ * all currently allocated resources. It is recommended to close
* the stream on the client side as soon as it is becomes unused.
*
+ * The client must ensure that this function is not called while
+ * audio data is being transferred through the stream's message queues.
+ *
* @return retval OK in case the success.
* NOT_SUPPORTED if called on IStream instead of input or
* output stream interface.
* INVALID_STATE if the stream was already closed.
*/
+ @exit
close() generates (Result retval);
};
diff --git a/audio/core/all-versions/default/Device.cpp b/audio/core/all-versions/default/Device.cpp
index 1a9df21..21dab00 100644
--- a/audio/core/all-versions/default/Device.cpp
+++ b/audio/core/all-versions/default/Device.cpp
@@ -39,11 +39,10 @@
using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
-Device::Device(audio_hw_device_t* device) : mDevice(device) {}
+Device::Device(audio_hw_device_t* device) : mIsClosed(false), mDevice(device) {}
Device::~Device() {
- int status = audio_hw_device_close(mDevice);
- ALOGW_IF(status, "Error closing audio hw device %p: %s", mDevice, strerror(-status));
+ (void)doClose();
mDevice = nullptr;
}
@@ -54,10 +53,14 @@
void Device::closeInputStream(audio_stream_in_t* stream) {
mDevice->close_input_stream(mDevice, stream);
+ LOG_ALWAYS_FATAL_IF(mOpenedStreamsCount == 0, "mOpenedStreamsCount is already 0");
+ --mOpenedStreamsCount;
}
void Device::closeOutputStream(audio_stream_out_t* stream) {
mDevice->close_output_stream(mDevice, stream);
+ LOG_ALWAYS_FATAL_IF(mOpenedStreamsCount == 0, "mOpenedStreamsCount is already 0");
+ --mOpenedStreamsCount;
}
char* Device::halGetParameters(const char* keys) {
@@ -159,6 +162,7 @@
sp<IStreamOut> streamOut;
if (status == OK) {
streamOut = new StreamOut(this, halStream);
+ ++mOpenedStreamsCount;
}
HidlUtils::audioConfigFromHal(halConfig, suggestedConfig);
return {analyzeStatus("open_output_stream", status, {EINVAL} /*ignore*/), streamOut};
@@ -185,6 +189,7 @@
sp<IStreamIn> streamIn;
if (status == OK) {
streamIn = new StreamIn(this, halStream);
+ ++mOpenedStreamsCount;
}
HidlUtils::audioConfigFromHal(halConfig, suggestedConfig);
return {analyzeStatus("open_input_stream", status, {EINVAL} /*ignore*/), streamIn};
@@ -383,6 +388,18 @@
}
#endif
+Result Device::doClose() {
+ if (mIsClosed || mOpenedStreamsCount != 0) return Result::INVALID_STATE;
+ mIsClosed = true;
+ return analyzeStatus("close", audio_hw_device_close(mDevice));
+}
+
+#if MAJOR_VERSION >= 6
+Return<Result> Device::close() {
+ return doClose();
+}
+#endif
+
} // namespace implementation
} // namespace CPP_VERSION
} // namespace audio
diff --git a/audio/core/all-versions/default/PrimaryDevice.cpp b/audio/core/all-versions/default/PrimaryDevice.cpp
index 99590b0..3cf0932 100644
--- a/audio/core/all-versions/default/PrimaryDevice.cpp
+++ b/audio/core/all-versions/default/PrimaryDevice.cpp
@@ -31,7 +31,11 @@
PrimaryDevice::PrimaryDevice(audio_hw_device_t* device) : mDevice(new Device(device)) {}
-PrimaryDevice::~PrimaryDevice() {}
+PrimaryDevice::~PrimaryDevice() {
+ // Do not call mDevice->close here. If there are any unclosed streams,
+ // they only hold IDevice instance, not IPrimaryDevice, thus IPrimaryDevice
+ // "part" of a device can be destroyed before the streams.
+}
// Methods from ::android::hardware::audio::CPP_VERSION::IDevice follow.
Return<Result> PrimaryDevice::initCheck() {
@@ -160,6 +164,11 @@
return mDevice->setConnectedState(address, connected);
}
#endif
+#if MAJOR_VERSION >= 6
+Return<Result> PrimaryDevice::close() {
+ return mDevice->close();
+}
+#endif
// Methods from ::android::hardware::audio::CPP_VERSION::IPrimaryDevice follow.
Return<Result> PrimaryDevice::setVoiceVolume(float volume) {
diff --git a/audio/core/all-versions/default/StreamIn.cpp b/audio/core/all-versions/default/StreamIn.cpp
index d316f83..f1152ca 100644
--- a/audio/core/all-versions/default/StreamIn.cpp
+++ b/audio/core/all-versions/default/StreamIn.cpp
@@ -139,8 +139,7 @@
} // namespace
StreamIn::StreamIn(const sp<Device>& device, audio_stream_in_t* stream)
- : mIsClosed(false),
- mDevice(device),
+ : mDevice(device),
mStream(stream),
mStreamCommon(new Stream(&stream->common)),
mStreamMmap(new StreamMmap<audio_stream_in_t>(stream)),
@@ -159,7 +158,9 @@
status_t status = EventFlag::deleteEventFlag(&mEfGroup);
ALOGE_IF(status, "read MQ event flag deletion error: %s", strerror(-status));
}
+#if MAJOR_VERSION <= 5
mDevice->closeInputStream(mStream);
+#endif
mStream = nullptr;
}
@@ -303,14 +304,16 @@
}
Return<Result> StreamIn::close() {
- if (mIsClosed) return Result::INVALID_STATE;
- mIsClosed = true;
- if (mReadThread.get()) {
- mStopReadThread.store(true, std::memory_order_release);
+ if (mStopReadThread.load(std::memory_order_relaxed)) { // only this thread writes
+ return Result::INVALID_STATE;
}
+ mStopReadThread.store(true, std::memory_order_release);
if (mEfGroup) {
mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL));
}
+#if MAJOR_VERSION >= 6
+ mDevice->closeInputStream(mStream);
+#endif
return Result::OK;
}
diff --git a/audio/core/all-versions/default/StreamOut.cpp b/audio/core/all-versions/default/StreamOut.cpp
index 82cc408..396d354 100644
--- a/audio/core/all-versions/default/StreamOut.cpp
+++ b/audio/core/all-versions/default/StreamOut.cpp
@@ -138,8 +138,7 @@
} // namespace
StreamOut::StreamOut(const sp<Device>& device, audio_stream_out_t* stream)
- : mIsClosed(false),
- mDevice(device),
+ : mDevice(device),
mStream(stream),
mStreamCommon(new Stream(&stream->common)),
mStreamMmap(new StreamMmap<audio_stream_out_t>(stream)),
@@ -148,7 +147,7 @@
StreamOut::~StreamOut() {
ATRACE_CALL();
- close();
+ (void)close();
if (mWriteThread.get()) {
ATRACE_NAME("mWriteThread->join");
status_t status = mWriteThread->join();
@@ -159,10 +158,12 @@
ALOGE_IF(status, "write MQ event flag deletion error: %s", strerror(-status));
}
mCallback.clear();
+#if MAJOR_VERSION <= 5
mDevice->closeOutputStream(mStream);
// Closing the output stream in the HAL waits for the callback to finish,
// and joins the callback thread. Thus is it guaranteed that the callback
// thread will not be accessing our object anymore.
+#endif
mStream = nullptr;
}
@@ -291,14 +292,16 @@
#endif
Return<Result> StreamOut::close() {
- if (mIsClosed) return Result::INVALID_STATE;
- mIsClosed = true;
- if (mWriteThread.get()) {
- mStopWriteThread.store(true, std::memory_order_release);
+ if (mStopWriteThread.load(std::memory_order_relaxed)) { // only this thread writes
+ return Result::INVALID_STATE;
}
+ mStopWriteThread.store(true, std::memory_order_release);
if (mEfGroup) {
mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY));
}
+#if MAJOR_VERSION >= 6
+ mDevice->closeOutputStream(mStream);
+#endif
return Result::OK;
}
diff --git a/audio/core/all-versions/default/include/core/default/Device.h b/audio/core/all-versions/default/include/core/default/Device.h
index e64f00f..11ab607 100644
--- a/audio/core/all-versions/default/include/core/default/Device.h
+++ b/audio/core/all-versions/default/include/core/default/Device.h
@@ -114,6 +114,9 @@
Return<void> getMicrophones(getMicrophones_cb _hidl_cb) override;
Return<Result> setConnectedState(const DeviceAddress& address, bool connected) override;
#endif
+#if MAJOR_VERSION >= 6
+ Return<Result> close() override;
+#endif
Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
@@ -124,11 +127,15 @@
void closeOutputStream(audio_stream_out_t* stream);
audio_hw_device_t* device() const { return mDevice; }
- private:
+ private:
+ bool mIsClosed;
audio_hw_device_t* mDevice;
+ int mOpenedStreamsCount = 0;
virtual ~Device();
+ Result doClose();
+
// Methods from ParametersUtil.
char* halGetParameters(const char* keys) override;
int halSetParameters(const char* keysAndValues) override;
diff --git a/audio/core/all-versions/default/include/core/default/PrimaryDevice.h b/audio/core/all-versions/default/include/core/default/PrimaryDevice.h
index 9d69cb0..f5f3848 100644
--- a/audio/core/all-versions/default/include/core/default/PrimaryDevice.h
+++ b/audio/core/all-versions/default/include/core/default/PrimaryDevice.h
@@ -96,6 +96,9 @@
Return<void> getMicrophones(getMicrophones_cb _hidl_cb) override;
Return<Result> setConnectedState(const DeviceAddress& address, bool connected) override;
#endif
+#if MAJOR_VERSION >= 6
+ Return<Result> close() override;
+#endif
Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
diff --git a/audio/core/all-versions/default/include/core/default/StreamIn.h b/audio/core/all-versions/default/include/core/default/StreamIn.h
index 6209b8f..24f9944 100644
--- a/audio/core/all-versions/default/include/core/default/StreamIn.h
+++ b/audio/core/all-versions/default/include/core/default/StreamIn.h
@@ -120,7 +120,6 @@
uint64_t* time);
private:
- bool mIsClosed;
const sp<Device> mDevice;
audio_stream_in_t* mStream;
const sp<Stream> mStreamCommon;
diff --git a/audio/core/all-versions/default/include/core/default/StreamOut.h b/audio/core/all-versions/default/include/core/default/StreamOut.h
index b098005..6334785 100644
--- a/audio/core/all-versions/default/include/core/default/StreamOut.h
+++ b/audio/core/all-versions/default/include/core/default/StreamOut.h
@@ -126,7 +126,6 @@
TimeSpec* timeStamp);
private:
- bool mIsClosed;
const sp<Device> mDevice;
audio_stream_out_t* mStream;
const sp<Stream> mStreamCommon;
diff --git a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
index e267a5e..709b7cd 100644
--- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
@@ -22,18 +22,16 @@
GTEST_SKIP() << "No primary device on this factory"; // returns
}
- struct WaitExecutor {
- ~WaitExecutor() { DeviceManager::waitForInstanceDestruction(); }
- } waitExecutor; // Make sure we wait for the device destruction on exiting from the test.
- Result result;
- sp<IDevice> baseDevice;
- ASSERT_OK(getDevicesFactory()->openDevice("primary", returnIn(result, baseDevice)));
- ASSERT_OK(result);
- ASSERT_TRUE(baseDevice != nullptr);
-
- Return<sp<IPrimaryDevice>> primaryDevice = IPrimaryDevice::castFrom(baseDevice);
- ASSERT_TRUE(primaryDevice.isOk());
- ASSERT_TRUE(sp<IPrimaryDevice>(primaryDevice) != nullptr);
+ { // Scope for device SPs
+ sp<IDevice> baseDevice =
+ DeviceManager::getInstance().get(getFactoryName(), DeviceManager::kPrimaryDevice);
+ ASSERT_TRUE(baseDevice != nullptr);
+ Return<sp<IPrimaryDevice>> primaryDevice = IPrimaryDevice::castFrom(baseDevice);
+ EXPECT_TRUE(primaryDevice.isOk());
+ EXPECT_TRUE(sp<IPrimaryDevice>(primaryDevice) != nullptr);
+ }
+ EXPECT_TRUE(
+ DeviceManager::getInstance().reset(getFactoryName(), DeviceManager::kPrimaryDevice));
}
//////////////////////////////////////////////////////////////////////////////
@@ -54,7 +52,6 @@
doc::test(
"Make sure getMicrophones always succeeds"
"and getActiveMicrophones always succeeds when recording from these microphones.");
- AudioIoHandle ioHandle = (AudioIoHandle)AudioHandleConsts::AUDIO_IO_HANDLE_NONE;
AudioConfig config{};
config.channelMask = mkEnumBitfield(AudioChannelMask::IN_MONO);
config.sampleRateHz = 8000;
@@ -67,18 +64,14 @@
continue;
}
sp<IStreamIn> stream;
+ StreamHelper<IStreamIn> helper(stream);
AudioConfig suggestedConfig{};
- ASSERT_OK(getDevice()->openInputStream(ioHandle, microphone.deviceAddress, config,
- flags, initMetadata,
- returnIn(res, stream, suggestedConfig)));
- if (res != Result::OK) {
- ASSERT_TRUE(stream == nullptr);
- AudioConfig suggestedConfigRetry{};
- ASSERT_OK(getDevice()->openInputStream(
- ioHandle, microphone.deviceAddress, suggestedConfig, flags, initMetadata,
- returnIn(res, stream, suggestedConfigRetry)));
- }
- ASSERT_OK(res);
+ ASSERT_NO_FATAL_FAILURE(helper.open(
+ [&](AudioIoHandle handle, AudioConfig config, auto cb) {
+ return getDevice()->openInputStream(handle, microphone.deviceAddress,
+ config, flags, initMetadata, cb);
+ },
+ config, &res, &suggestedConfig));
hidl_vec<MicrophoneInfo> activeMicrophones;
Result readRes;
typedef MessageQueue<IStreamIn::ReadParameters, kSynchronizedReadWrite> CommandMQ;
@@ -112,11 +105,8 @@
ASSERT_OK(res);
ASSERT_NE(0U, activeMicrophones.size());
}
- stream->close();
- // Workaround for b/139329877. Ensures the stream gets closed on the audio hal side.
- stream.clear();
- IPCThreadState::self()->flushCommands();
- usleep(1000);
+ helper.close(true /*clear*/, &res);
+ ASSERT_OK(res);
if (efGroup) {
EventFlag::deleteEventFlag(&efGroup);
}
diff --git a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
index 30f8a7a..22e60be 100644
--- a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
@@ -100,7 +100,8 @@
special = true;
}
if ((flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
- !(flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
+ !(flags &
+ (AUDIO_OUTPUT_FLAG_HW_AV_SYNC | AUDIO_OUTPUT_FLAG_MMAP_NOIRQ))) {
result.emplace_back(device, config,
AudioOutputFlag(AUDIO_OUTPUT_FLAG_DIRECT));
special = true;
@@ -144,3 +145,49 @@
}();
return parameters;
}
+
+TEST_P(AudioHidlDeviceTest, CloseDeviceWithOpenedOutputStreams) {
+ doc::test("Verify that a device can't be closed if there are streams opened");
+ DeviceAddress address{.device = AudioDevice::OUT_DEFAULT};
+ AudioConfig config{};
+ auto flags = hidl_bitfield<AudioOutputFlag>(AudioOutputFlag::NONE);
+ SourceMetadata initMetadata = {{{AudioUsage::MEDIA, AudioContentType::MUSIC, 1 /* gain */}}};
+ sp<IStreamOut> stream;
+ StreamHelper<IStreamOut> helper(stream);
+ AudioConfig suggestedConfig{};
+ ASSERT_NO_FATAL_FAILURE(helper.open(
+ [&](AudioIoHandle handle, AudioConfig config, auto cb) {
+ return getDevice()->openOutputStream(handle, address, config, flags, initMetadata,
+ cb);
+ },
+ config, &res, &suggestedConfig));
+ ASSERT_RESULT(Result::INVALID_STATE, getDevice()->close());
+ ASSERT_NO_FATAL_FAILURE(helper.close(true /*clear*/, &res));
+ ASSERT_OK(getDevice()->close());
+ ASSERT_TRUE(resetDevice());
+}
+
+TEST_P(AudioHidlDeviceTest, CloseDeviceWithOpenedInputStreams) {
+ doc::test("Verify that a device can't be closed if there are streams opened");
+ auto module = getCachedPolicyConfig().getModuleFromName(getDeviceName());
+ if (module->getInputProfiles().empty()) {
+ GTEST_SKIP() << "Device doesn't have input profiles";
+ }
+ DeviceAddress address{.device = AudioDevice::IN_DEFAULT};
+ AudioConfig config{};
+ auto flags = hidl_bitfield<AudioInputFlag>(AudioInputFlag::NONE);
+ SinkMetadata initMetadata = {{{.source = AudioSource::MIC, .gain = 1}}};
+ sp<IStreamIn> stream;
+ StreamHelper<IStreamIn> helper(stream);
+ AudioConfig suggestedConfig{};
+ ASSERT_NO_FATAL_FAILURE(helper.open(
+ [&](AudioIoHandle handle, AudioConfig config, auto cb) {
+ return getDevice()->openInputStream(handle, address, config, flags, initMetadata,
+ cb);
+ },
+ config, &res, &suggestedConfig));
+ ASSERT_RESULT(Result::INVALID_STATE, getDevice()->close());
+ ASSERT_NO_FATAL_FAILURE(helper.close(true /*clear*/, &res));
+ ASSERT_OK(getDevice()->close());
+ ASSERT_TRUE(resetDevice());
+}
diff --git a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
index e76e24e..d0d39e8 100644
--- a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
+++ b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
@@ -718,12 +718,6 @@
::testing::Values(AudioInputFlag::NONE)),
&DeviceConfigParameterToString);
INSTANTIATE_TEST_CASE_P(
- SupportedInputBufferSize, RequiredInputBufferSizeTest,
- ::testing::Combine(::testing::ValuesIn(getDeviceParameters()),
- ::testing::ValuesIn(ConfigHelper::getSupportedCaptureAudioConfig()),
- ::testing::Values(AudioInputFlag::NONE)),
- &DeviceConfigParameterToString);
-INSTANTIATE_TEST_CASE_P(
RecommendedCaptureAudioConfigSupport, OptionalInputBufferSizeTest,
::testing::Combine(
::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
@@ -815,60 +809,84 @@
////////////////////////// open{Output,Input}Stream //////////////////////////
//////////////////////////////////////////////////////////////////////////////
+// This class is also used by some device tests.
template <class Stream>
-class OpenStreamTest : public AudioHidlTestWithDeviceConfigParameter {
- protected:
+class StreamHelper {
+ public:
+ // StreamHelper doesn't own the stream, this is for simpler stream lifetime management.
+ explicit StreamHelper(sp<Stream>& stream) : mStream(stream) {}
template <class Open>
- void testOpen(Open openStream, const AudioConfig& config) {
+ void open(Open openStream, const AudioConfig& config, Result* res,
+ AudioConfig* suggestedConfigPtr) {
// FIXME: Open a stream without an IOHandle
// This is not required to be accepted by hal implementations
AudioIoHandle ioHandle = (AudioIoHandle)AudioHandleConsts::AUDIO_IO_HANDLE_NONE;
AudioConfig suggestedConfig{};
- ASSERT_OK(openStream(ioHandle, config, returnIn(res, stream, suggestedConfig)));
-
- // TODO: only allow failure for RecommendedPlaybackAudioConfig
- switch (res) {
+ bool retryWithSuggestedConfig = true;
+ if (suggestedConfigPtr == nullptr) {
+ suggestedConfigPtr = &suggestedConfig;
+ retryWithSuggestedConfig = false;
+ }
+ ASSERT_OK(openStream(ioHandle, config, returnIn(*res, mStream, *suggestedConfigPtr)));
+ switch (*res) {
case Result::OK:
- ASSERT_TRUE(stream != nullptr);
- audioConfig = config;
+ ASSERT_TRUE(mStream != nullptr);
+ *suggestedConfigPtr = config;
break;
case Result::INVALID_ARGUMENTS:
- ASSERT_TRUE(stream == nullptr);
- AudioConfig suggestedConfigRetry;
- // Could not open stream with config, try again with the
- // suggested one
- ASSERT_OK(openStream(ioHandle, suggestedConfig,
- returnIn(res, stream, suggestedConfigRetry)));
- // This time it must succeed
- ASSERT_OK(res);
- ASSERT_TRUE(stream != nullptr);
- audioConfig = suggestedConfig;
+ ASSERT_TRUE(mStream == nullptr);
+ if (retryWithSuggestedConfig) {
+ AudioConfig suggestedConfigRetry;
+ ASSERT_OK(openStream(ioHandle, *suggestedConfigPtr,
+ returnIn(*res, mStream, suggestedConfigRetry)));
+ ASSERT_OK(*res);
+ ASSERT_TRUE(mStream != nullptr);
+ }
break;
default:
- FAIL() << "Invalid return status: " << ::testing::PrintToString(res);
+ FAIL() << "Invalid return status: " << ::testing::PrintToString(*res);
}
+ }
+ void close(bool clear, Result* res) {
+ auto ret = mStream->close();
+ EXPECT_TRUE(ret.isOk());
+ *res = ret;
+ if (clear) {
+ mStream.clear();
+#if MAJOR_VERSION <= 5
+ // FIXME: there is no way to know when the remote IStream is being destroyed
+ // Binder does not support testing if an object is alive, thus
+ // wait for 100ms to let the binder destruction propagates and
+ // the remote device has the time to be destroyed.
+ // flushCommand makes sure all local command are sent, thus should reduce
+ // the latency between local and remote destruction.
+ IPCThreadState::self()->flushCommands();
+ usleep(100 * 1000);
+#endif
+ }
+ }
+
+ private:
+ sp<Stream>& mStream;
+};
+
+template <class Stream>
+class OpenStreamTest : public AudioHidlTestWithDeviceConfigParameter {
+ protected:
+ OpenStreamTest() : AudioHidlTestWithDeviceConfigParameter(), helper(stream) {}
+ template <class Open>
+ void testOpen(Open openStream, const AudioConfig& config) {
+ // TODO: only allow failure for RecommendedPlaybackAudioConfig
+ ASSERT_NO_FATAL_FAILURE(helper.open(openStream, config, &res, &audioConfig));
open = true;
}
- Return<Result> closeStream() {
+ Result closeStream(bool clear = true) {
open = false;
- auto res = stream->close();
- stream.clear();
- waitForStreamDestruction();
+ helper.close(clear, &res);
return res;
}
- static void waitForStreamDestruction() {
- // FIXME: there is no way to know when the remote IStream is being destroyed
- // Binder does not support testing if an object is alive, thus
- // wait for 100ms to let the binder destruction propagates and
- // the remote device has the time to be destroyed.
- // flushCommand makes sure all local command are sent, thus should reduce
- // the latency between local and remote destruction.
- IPCThreadState::self()->flushCommands();
- usleep(100 * 1000);
- }
-
private:
void TearDown() override {
if (open) {
@@ -881,6 +899,7 @@
AudioConfig audioConfig;
DeviceAddress address = {};
sp<Stream> stream;
+ StreamHelper<Stream> helper;
bool open = false;
};
@@ -929,12 +948,6 @@
::testing::Values(AudioOutputFlag::NONE)),
&DeviceConfigParameterToString);
INSTANTIATE_TEST_CASE_P(
- SupportedOutputStreamConfig, OutputStreamTest,
- ::testing::Combine(::testing::ValuesIn(getDeviceParameters()),
- ::testing::ValuesIn(ConfigHelper::getSupportedPlaybackAudioConfig()),
- ::testing::Values(AudioOutputFlag::NONE)),
- &DeviceConfigParameterToString);
-INSTANTIATE_TEST_CASE_P(
RecommendedOutputStreamConfigSupport, OutputStreamTest,
::testing::Combine(
::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
@@ -944,7 +957,7 @@
#elif MAJOR_VERSION >= 6
// For V6 and above test according to the audio policy manager configuration.
// This is more correct as CDD is written from the apps perspective.
-// Audio system provides necessary format conversions for the missing configurations.
+// Audio system provides necessary format conversions for missing configurations.
INSTANTIATE_TEST_CASE_P(DeclaredOutputStreamConfigSupport, OutputStreamTest,
::testing::ValuesIn(getOutputDeviceConfigParameters()),
&DeviceConfigParameterToString);
@@ -990,12 +1003,6 @@
::testing::Values(AudioInputFlag::NONE)),
&DeviceConfigParameterToString);
INSTANTIATE_TEST_CASE_P(
- SupportedInputStreamConfig, InputStreamTest,
- ::testing::Combine(::testing::ValuesIn(getDeviceParameters()),
- ::testing::ValuesIn(ConfigHelper::getSupportedCaptureAudioConfig()),
- ::testing::Values(AudioInputFlag::NONE)),
- &DeviceConfigParameterToString);
-INSTANTIATE_TEST_CASE_P(
RecommendedInputStreamConfigSupport, InputStreamTest,
::testing::Combine(
::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
@@ -1005,7 +1012,7 @@
#elif MAJOR_VERSION >= 6
// For V6 and above test according to the audio policy manager configuration.
// This is more correct as CDD is written from the apps perspective.
-// Audio system provides necessary format conversions for the missing configurations.
+// Audio system provides necessary format conversions for missing configurations.
INSTANTIATE_TEST_CASE_P(DeclaredInputStreamConfigSupport, InputStreamTest,
::testing::ValuesIn(getInputDeviceConfigParameters()),
&DeviceConfigParameterToString);
@@ -1194,26 +1201,21 @@
TEST_IO_STREAM(close, "Make sure a stream can be closed", ASSERT_OK(closeStream()))
// clang-format off
TEST_IO_STREAM(closeTwice, "Make sure a stream can not be closed twice",
- auto streamCopy = stream;
- ASSERT_OK(closeStream());
- ASSERT_RESULT(Result::INVALID_STATE, streamCopy->close());
- streamCopy.clear();
- waitForStreamDestruction())
+ ASSERT_OK(closeStream(false /*clear*/));
+ ASSERT_EQ(Result::INVALID_STATE, closeStream()))
// clang-format on
-static void testCreateTooBigMmapBuffer(IStream* stream) {
- MmapBufferInfo info;
- Result res;
- // Assume that int max is a value too big to be allocated
- // This is true currently with a 32bit media server, but might not when it
- // will run in 64 bit
- auto minSizeFrames = std::numeric_limits<int32_t>::max();
- ASSERT_OK(stream->createMmapBuffer(minSizeFrames, returnIn(res, info)));
- ASSERT_RESULT(invalidArgsOrNotSupported, res);
+static void testMmapBufferOfInvalidSize(IStream* stream) {
+ for (int32_t value : {-1, 0, std::numeric_limits<int32_t>::max()}) {
+ MmapBufferInfo info;
+ Result res;
+ EXPECT_OK(stream->createMmapBuffer(value, returnIn(res, info)));
+ EXPECT_RESULT(invalidArgsOrNotSupported, res) << "value=" << value;
+ }
}
-TEST_IO_STREAM(CreateTooBigMmapBuffer, "Create mmap buffer too big should fail",
- testCreateTooBigMmapBuffer(stream.get()))
+TEST_IO_STREAM(CreateTooBigMmapBuffer, "Create mmap buffer of invalid size must fail",
+ testMmapBufferOfInvalidSize(stream.get()))
static void testGetMmapPositionOfNonMmapedStream(IStream* stream) {
Result res;
diff --git a/audio/core/all-versions/vts/functional/ConfigHelper.h b/audio/core/all-versions/vts/functional/ConfigHelper.h
index 48aae8c..a2f4116 100644
--- a/audio/core/all-versions/vts/functional/ConfigHelper.h
+++ b/audio/core/all-versions/vts/functional/ConfigHelper.h
@@ -57,12 +57,6 @@
{24000, 48000}, {AudioFormat::PCM_16_BIT});
}
- static const vector<AudioConfig> getSupportedPlaybackAudioConfig() {
- // TODO: retrieve audio config supported by the platform
- // as declared in the policy configuration
- return {};
- }
-
static const vector<AudioConfig> getRequiredSupportCaptureAudioConfig() {
if (!primaryHasMic()) return {};
return combineAudioConfig({AudioChannelMask::IN_MONO}, {8000, 11025, 16000, 44100},
@@ -73,11 +67,6 @@
return combineAudioConfig({AudioChannelMask::IN_STEREO}, {22050, 48000},
{AudioFormat::PCM_16_BIT});
}
- static const vector<AudioConfig> getSupportedCaptureAudioConfig() {
- // TODO: retrieve audio config supported by the platform
- // as declared in the policy configuration
- return {};
- }
static vector<AudioConfig> combineAudioConfig(vector<audio_channel_mask_t> channelMasks,
vector<uint32_t> sampleRates,
diff --git a/audio/core/all-versions/vts/functional/DeviceManager.h b/audio/core/all-versions/vts/functional/DeviceManager.h
index b6e2db0..d849f85 100644
--- a/audio/core/all-versions/vts/functional/DeviceManager.h
+++ b/audio/core/all-versions/vts/functional/DeviceManager.h
@@ -22,25 +22,33 @@
template <class Derived, class Key, class Interface>
class InterfaceManager {
public:
+ sp<Interface> getExisting(const Key& name) {
+ auto existing = instances.find(name);
+ return existing != instances.end() ? existing->second : sp<Interface>();
+ }
+
sp<Interface> get(const Key& name) {
auto existing = instances.find(name);
if (existing != instances.end()) return existing->second;
auto [inserted, _] = instances.emplace(name, Derived::createInterfaceInstance(name));
if (inserted->second) {
- environment->registerTearDown([name]() { (void)Derived::getInstance().reset(name); });
+ environment->registerTearDown(
+ [name]() { (void)Derived::getInstance().reset(name, false); });
}
return inserted->second;
}
// The test must check that reset was successful. Reset failure means that the test code
// is holding a strong reference to the device.
- bool reset(const Key& name) __attribute__((warn_unused_result)) {
+ bool reset(const Key& name, bool waitForDestruction) __attribute__((warn_unused_result)) {
auto iter = instances.find(name);
if (iter == instances.end()) return true;
::android::wp<Interface> weak = iter->second;
instances.erase(iter);
if (weak.promote() != nullptr) return false;
- waitForInstanceDestruction();
+ if (waitForDestruction) {
+ waitForInstanceDestruction();
+ }
return true;
}
@@ -100,7 +108,15 @@
}
bool reset(const std::string& factoryName, const std::string& name)
__attribute__((warn_unused_result)) {
- return InterfaceManager::reset(std::make_tuple(factoryName, name));
+#if MAJOR_VERSION <= 5
+ return InterfaceManager::reset(std::make_tuple(factoryName, name), true);
+#elif MAJOR_VERSION >= 6
+ {
+ sp<IDevice> device = getExisting(std::make_tuple(factoryName, name));
+ if (device != nullptr) device->close();
+ }
+ return InterfaceManager::reset(std::make_tuple(factoryName, name), false);
+#endif
}
bool resetPrimary(const std::string& factoryName) __attribute__((warn_unused_result)) {
return reset(factoryName, kPrimaryDevice);
diff --git a/audio/effect/6.0/IEffect.hal b/audio/effect/6.0/IEffect.hal
index b35afee..f4c50a2 100644
--- a/audio/effect/6.0/IEffect.hal
+++ b/audio/effect/6.0/IEffect.hal
@@ -407,9 +407,12 @@
/**
* Called by the framework to deinitialize the effect and free up
- * all the currently allocated resources. It is recommended to close
+ * all currently allocated resources. It is recommended to close
* the effect on the client side as soon as it is becomes unused.
*
+ * The client must ensure that this function is not called while
+ * audio data is being transferred through the effect's message queues.
+ *
* @return retval OK in case the success.
* INVALID_STATE if the effect was already closed.
*/
diff --git a/audio/effect/all-versions/default/Effect.cpp b/audio/effect/all-versions/default/Effect.cpp
index 3c0d878..0afa779 100644
--- a/audio/effect/all-versions/default/Effect.cpp
+++ b/audio/effect/all-versions/default/Effect.cpp
@@ -138,11 +138,11 @@
const char* Effect::sContextCallFunction = sContextCallToCommand;
Effect::Effect(effect_handle_t handle)
- : mIsClosed(false), mHandle(handle), mEfGroup(nullptr), mStopProcessThread(false) {}
+ : mHandle(handle), mEfGroup(nullptr), mStopProcessThread(false) {}
Effect::~Effect() {
ATRACE_CALL();
- close();
+ (void)close();
if (mProcessThread.get()) {
ATRACE_NAME("mProcessThread->join");
status_t status = mProcessThread->join();
@@ -154,8 +154,10 @@
}
mInBuffer.clear();
mOutBuffer.clear();
+#if MAJOR_VERSION <= 5
int status = EffectRelease(mHandle);
ALOGW_IF(status, "Error releasing effect %p: %s", mHandle, strerror(-status));
+#endif
EffectMap::getInstance().remove(mHandle);
mHandle = 0;
}
@@ -699,15 +701,20 @@
}
Return<Result> Effect::close() {
- if (mIsClosed) return Result::INVALID_STATE;
- mIsClosed = true;
- if (mProcessThread.get()) {
- mStopProcessThread.store(true, std::memory_order_release);
+ if (mStopProcessThread.load(std::memory_order_relaxed)) { // only this thread modifies
+ return Result::INVALID_STATE;
}
+ mStopProcessThread.store(true, std::memory_order_release);
if (mEfGroup) {
mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_QUIT));
}
+#if MAJOR_VERSION <= 5
return Result::OK;
+#elif MAJOR_VERSION >= 6
+ // No need to join the processing thread, it is part of the API contract that the client
+ // must finish processing before closing the effect.
+ return analyzeStatus("EffectRelease", "", sContextCallFunction, EffectRelease(mHandle));
+#endif
}
Return<void> Effect::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& /* options */) {
diff --git a/audio/effect/all-versions/default/Effect.h b/audio/effect/all-versions/default/Effect.h
index 3d99a0e..181e542 100644
--- a/audio/effect/all-versions/default/Effect.h
+++ b/audio/effect/all-versions/default/Effect.h
@@ -170,7 +170,6 @@
static const char* sContextCallToCommand;
static const char* sContextCallFunction;
- bool mIsClosed;
effect_handle_t mHandle;
sp<AudioBufferWrapper> mInBuffer;
sp<AudioBufferWrapper> mOutBuffer;
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h
index d689e62..8ee3c54 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h
@@ -153,7 +153,7 @@
std::unique_ptr<VehiclePropValue> createAvailabilityRequest();
// Creates a VehiclePropValue containing a message of type
-// VmsMessageType.AVAILABILITY_REQUEST.
+// VmsMessageType.SUBSCRIPTIONS_REQUEST.
std::unique_ptr<VehiclePropValue> createSubscriptionsRequest();
// Creates a VehiclePropValue containing a message of type VmsMessageType.DATA.
@@ -202,21 +202,21 @@
// Returns true if the new sequence number is greater than the last seen
// sequence number.
-bool isSequenceNumberNewer(const VehiclePropValue& subscription_change,
+bool isSequenceNumberNewer(const VehiclePropValue& subscriptions_state,
const int last_seen_sequence_number);
// Returns sequence number of the message.
-int32_t getSequenceNumberForSubscriptionsState(const VehiclePropValue& subscription_change);
+int32_t getSequenceNumberForSubscriptionsState(const VehiclePropValue& subscriptions_state);
-// Takes a subscription change message and returns the layers that have active
+// Takes a subscriptions state message and returns the layers that have active
// subscriptions of the layers that are offered by your HAL client/publisher.
//
-// A publisher can use this function when receiving a subscription change message
-// to determine which layers to publish data on.
+// A publisher can use this function when receiving a subscriptions response or subscriptions
+// change message to determine which layers to publish data on.
// The caller of this function can optionally decide to not consume these layers
// if the subscription change has the sequence number less than the last seen
// sequence number.
-std::vector<VmsLayer> getSubscribedLayers(const VehiclePropValue& subscription_change,
+std::vector<VmsLayer> getSubscribedLayers(const VehiclePropValue& subscriptions_state,
const VmsOffers& offers);
// Takes an availability change message and returns true if the parsed message implies that
diff --git a/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp b/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp
index d346206..9eba905 100644
--- a/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp
@@ -194,32 +194,35 @@
return -1;
}
-bool isSequenceNumberNewer(const VehiclePropValue& subscription_change,
+bool isSequenceNumberNewer(const VehiclePropValue& subscriptions_state,
const int last_seen_sequence_number) {
- return (isValidVmsMessage(subscription_change) &&
- parseMessageType(subscription_change) == VmsMessageType::SUBSCRIPTIONS_CHANGE &&
- subscription_change.value.int32Values.size() > kSubscriptionStateSequenceNumberIndex &&
- subscription_change.value.int32Values[kSubscriptionStateSequenceNumberIndex] >
+ return (isValidVmsMessage(subscriptions_state) &&
+ (parseMessageType(subscriptions_state) == VmsMessageType::SUBSCRIPTIONS_CHANGE ||
+ parseMessageType(subscriptions_state) == VmsMessageType::SUBSCRIPTIONS_RESPONSE) &&
+ subscriptions_state.value.int32Values.size() > kSubscriptionStateSequenceNumberIndex &&
+ subscriptions_state.value.int32Values[kSubscriptionStateSequenceNumberIndex] >
last_seen_sequence_number);
}
-int32_t getSequenceNumberForSubscriptionsState(const VehiclePropValue& subscription_change) {
- if (isValidVmsMessage(subscription_change) &&
- parseMessageType(subscription_change) == VmsMessageType::SUBSCRIPTIONS_CHANGE &&
- subscription_change.value.int32Values.size() > kSubscriptionStateSequenceNumberIndex) {
- return subscription_change.value.int32Values[kSubscriptionStateSequenceNumberIndex];
+int32_t getSequenceNumberForSubscriptionsState(const VehiclePropValue& subscriptions_state) {
+ if (isValidVmsMessage(subscriptions_state) &&
+ (parseMessageType(subscriptions_state) == VmsMessageType::SUBSCRIPTIONS_CHANGE ||
+ parseMessageType(subscriptions_state) == VmsMessageType::SUBSCRIPTIONS_RESPONSE) &&
+ subscriptions_state.value.int32Values.size() > kSubscriptionStateSequenceNumberIndex) {
+ return subscriptions_state.value.int32Values[kSubscriptionStateSequenceNumberIndex];
}
return -1;
}
-std::vector<VmsLayer> getSubscribedLayers(const VehiclePropValue& subscription_change,
+std::vector<VmsLayer> getSubscribedLayers(const VehiclePropValue& subscriptions_state,
const VmsOffers& offers) {
- if (isValidVmsMessage(subscription_change) &&
- parseMessageType(subscription_change) == VmsMessageType::SUBSCRIPTIONS_CHANGE &&
- subscription_change.value.int32Values.size() > kSubscriptionStateSequenceNumberIndex) {
- const int32_t num_of_layers = subscription_change.value.int32Values[toInt(
+ if (isValidVmsMessage(subscriptions_state) &&
+ (parseMessageType(subscriptions_state) == VmsMessageType::SUBSCRIPTIONS_CHANGE ||
+ parseMessageType(subscriptions_state) == VmsMessageType::SUBSCRIPTIONS_RESPONSE) &&
+ subscriptions_state.value.int32Values.size() > kSubscriptionStateSequenceNumberIndex) {
+ const int32_t num_of_layers = subscriptions_state.value.int32Values[toInt(
VmsSubscriptionsStateIntegerValuesIndex::NUMBER_OF_LAYERS)];
- const int32_t num_of_associated_layers = subscription_change.value.int32Values[toInt(
+ const int32_t num_of_associated_layers = subscriptions_state.value.int32Values[toInt(
VmsSubscriptionsStateIntegerValuesIndex ::NUMBER_OF_ASSOCIATED_LAYERS)];
std::unordered_set<VmsLayer, VmsLayer::VmsLayerHashFunction> offered_layers;
@@ -231,9 +234,9 @@
int current_index = toInt(VmsSubscriptionsStateIntegerValuesIndex::SUBSCRIPTIONS_START);
// Add all subscribed layers which are offered by the current publisher.
for (int i = 0; i < num_of_layers; i++) {
- VmsLayer layer = VmsLayer(subscription_change.value.int32Values[current_index],
- subscription_change.value.int32Values[current_index + 1],
- subscription_change.value.int32Values[current_index + 2]);
+ VmsLayer layer = VmsLayer(subscriptions_state.value.int32Values[current_index],
+ subscriptions_state.value.int32Values[current_index + 1],
+ subscriptions_state.value.int32Values[current_index + 2]);
if (offered_layers.find(layer) != offered_layers.end()) {
subscribed_layers.push_back(layer);
}
@@ -243,15 +246,15 @@
// For this, we need to check if the associated layer has a publisher ID which is
// same as that of the current publisher.
for (int i = 0; i < num_of_associated_layers; i++) {
- VmsLayer layer = VmsLayer(subscription_change.value.int32Values[current_index],
- subscription_change.value.int32Values[current_index + 1],
- subscription_change.value.int32Values[current_index + 2]);
+ VmsLayer layer = VmsLayer(subscriptions_state.value.int32Values[current_index],
+ subscriptions_state.value.int32Values[current_index + 1],
+ subscriptions_state.value.int32Values[current_index + 2]);
current_index += kLayerSize;
if (offered_layers.find(layer) != offered_layers.end()) {
- int32_t num_of_publisher_ids = subscription_change.value.int32Values[current_index];
+ int32_t num_of_publisher_ids = subscriptions_state.value.int32Values[current_index];
current_index++;
for (int j = 0; j < num_of_publisher_ids; j++) {
- if (subscription_change.value.int32Values[current_index] ==
+ if (subscriptions_state.value.int32Values[current_index] ==
offers.publisher_id) {
subscribed_layers.push_back(layer);
}
diff --git a/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp b/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp
index 7189212..8b547f1 100644
--- a/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp
+++ b/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp
@@ -214,57 +214,82 @@
EXPECT_EQ(parsePublisherIdResponse(*message), -1);
}
-TEST(VmsUtilsTest, validSequenceNumberForSubscriptionsState) {
+TEST(VmsUtilsTest, validSequenceNumberForSubscriptionsChange) {
auto message = createBaseVmsMessage(2);
message->value.int32Values =
hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE), 1234};
EXPECT_EQ(getSequenceNumberForSubscriptionsState(*message), 1234);
}
+TEST(VmsUtilsTest, validSequenceNumberForSubscriptionsResponse) {
+ auto message = createBaseVmsMessage(2);
+ message->value.int32Values =
+ hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_RESPONSE), 1234};
+ EXPECT_EQ(getSequenceNumberForSubscriptionsState(*message), 1234);
+}
+
TEST(VmsUtilsTest, invalidSubscriptionsState) {
auto message = createBaseVmsMessage(1);
EXPECT_EQ(getSequenceNumberForSubscriptionsState(*message), -1);
}
-TEST(VmsUtilsTest, newSequenceNumberForExistingSmallerNumber) {
+TEST(VmsUtilsTest, newSequenceNumberForExistingSmallerNumberForChange) {
auto message = createBaseVmsMessage(2);
message->value.int32Values =
hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE), 1234};
EXPECT_TRUE(isSequenceNumberNewer(*message, 1233));
}
-TEST(VmsUtilsTest, newSequenceNumberForExistingGreaterNumber) {
+TEST(VmsUtilsTest, newSequenceNumberForExistingSmallerNumberForResponse) {
+ auto message = createBaseVmsMessage(2);
+ message->value.int32Values =
+ hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_RESPONSE), 1234};
+ EXPECT_TRUE(isSequenceNumberNewer(*message, 1233));
+}
+
+TEST(VmsUtilsTest, newSequenceNumberForExistingGreaterNumberForChange) {
auto message = createBaseVmsMessage(2);
message->value.int32Values =
hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE), 1234};
EXPECT_FALSE(isSequenceNumberNewer(*message, 1235));
}
-TEST(VmsUtilsTest, newSequenceNumberForSameNumber) {
+TEST(VmsUtilsTest, newSequenceNumberForExistingGreaterNumberForResponse) {
+ auto message = createBaseVmsMessage(2);
+ message->value.int32Values =
+ hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_RESPONSE), 1234};
+ EXPECT_FALSE(isSequenceNumberNewer(*message, 1235));
+}
+
+TEST(VmsUtilsTest, newSequenceNumberForSameNumberForChange) {
auto message = createBaseVmsMessage(2);
message->value.int32Values =
hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE), 1234};
EXPECT_FALSE(isSequenceNumberNewer(*message, 1234));
}
-TEST(VmsUtilsTest, subscribedLayers) {
+TEST(VmsUtilsTest, newSequenceNumberForSameNumberForResponse) {
+ auto message = createBaseVmsMessage(2);
+ message->value.int32Values =
+ hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_RESPONSE), 1234};
+ EXPECT_FALSE(isSequenceNumberNewer(*message, 1234));
+}
+
+void testSubscribedLayers(VmsMessageType type) {
VmsOffers offers = {123,
{VmsLayerOffering(VmsLayer(1, 0, 1), {VmsLayer(4, 1, 1)}),
VmsLayerOffering(VmsLayer(2, 0, 1))}};
auto message = createBaseVmsMessage(2);
- message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE),
+ message->value.int32Values = hidl_vec<int32_t>{toInt(type),
1234, // sequence number
2, // number of layers
1, // number of associated layers
1, // layer 1
- 0,
- 1,
+ 0, 1,
4, // layer 2
- 1,
- 1,
+ 1, 1,
2, // associated layer
- 0,
- 1,
+ 0, 1,
2, // number of publisher IDs
111, // publisher IDs
123};
@@ -275,10 +300,18 @@
EXPECT_EQ(result.at(1), VmsLayer(2, 0, 1));
}
-TEST(VmsUtilsTest, subscribedLayersWithDifferentSubtype) {
+TEST(VmsUtilsTest, subscribedLayersForChange) {
+ testSubscribedLayers(VmsMessageType::SUBSCRIPTIONS_CHANGE);
+}
+
+TEST(VmsUtilsTest, subscribedLayersForResponse) {
+ testSubscribedLayers(VmsMessageType::SUBSCRIPTIONS_RESPONSE);
+}
+
+void testSubscribedLayersWithDifferentSubtype(VmsMessageType type) {
VmsOffers offers = {123, {VmsLayerOffering(VmsLayer(1, 0, 1))}};
auto message = createBaseVmsMessage(2);
- message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE),
+ message->value.int32Values = hidl_vec<int32_t>{toInt(type),
1234, // sequence number
1, // number of layers
0, // number of associated layers
@@ -289,36 +322,58 @@
EXPECT_TRUE(getSubscribedLayers(*message, offers).empty());
}
-TEST(VmsUtilsTest, subscribedLayersWithDifferentVersion) {
+TEST(VmsUtilsTest, subscribedLayersWithDifferentSubtypeForChange) {
+ testSubscribedLayersWithDifferentSubtype(VmsMessageType::SUBSCRIPTIONS_CHANGE);
+}
+
+TEST(VmsUtilsTest, subscribedLayersWithDifferentSubtypeForResponse) {
+ testSubscribedLayersWithDifferentSubtype(VmsMessageType::SUBSCRIPTIONS_RESPONSE);
+}
+
+void subscribedLayersWithDifferentVersion(VmsMessageType type) {
VmsOffers offers = {123, {VmsLayerOffering(VmsLayer(1, 0, 1))}};
auto message = createBaseVmsMessage(2);
- message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE),
- 1234, // sequence number
- 1, // number of layers
- 0, // number of associated layers
- 1, // layer 1
- 0,
- 2}; // different version
+ message->value.int32Values = hidl_vec<int32_t>{toInt(type),
+ 1234, // sequence number
+ 1, // number of layers
+ 0, // number of associated layers
+ 1, // layer 1
+ 0, 2}; // different version
EXPECT_TRUE(isValidVmsMessage(*message));
EXPECT_TRUE(getSubscribedLayers(*message, offers).empty());
}
-TEST(VmsUtilsTest, subscribedLayersWithDifferentPublisherId) {
+TEST(VmsUtilsTest, subscribedLayersWithDifferentVersionForChange) {
+ subscribedLayersWithDifferentVersion(VmsMessageType::SUBSCRIPTIONS_CHANGE);
+}
+
+TEST(VmsUtilsTest, subscribedLayersWithDifferentVersionForResponse) {
+ subscribedLayersWithDifferentVersion(VmsMessageType::SUBSCRIPTIONS_RESPONSE);
+}
+
+void subscribedLayersWithDifferentPublisherId(VmsMessageType type) {
VmsOffers offers = {123, {VmsLayerOffering(VmsLayer(1, 0, 1))}};
auto message = createBaseVmsMessage(2);
- message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE),
+ message->value.int32Values = hidl_vec<int32_t>{toInt(type),
1234, // sequence number
0, // number of layers
1, // number of associated layers
1, // associated layer 1
- 0,
- 1,
+ 0, 1,
1, // number of publisher IDs
234}; // publisher ID 1
EXPECT_TRUE(isValidVmsMessage(*message));
EXPECT_TRUE(getSubscribedLayers(*message, offers).empty());
}
+TEST(VmsUtilsTest, subscribedLayersWithDifferentPublisherIdForChange) {
+ subscribedLayersWithDifferentPublisherId(VmsMessageType::SUBSCRIPTIONS_CHANGE);
+}
+
+TEST(VmsUtilsTest, subscribedLayersWithDifferentPublisherIdForResponse) {
+ subscribedLayersWithDifferentPublisherId(VmsMessageType::SUBSCRIPTIONS_RESPONSE);
+}
+
TEST(VmsUtilsTest, serviceNewlyStarted) {
auto message = createBaseVmsMessage(2);
message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::AVAILABILITY_CHANGE), 0};
diff --git a/biometrics/face/1.0/vts/functional/Android.bp b/biometrics/face/1.0/vts/functional/Android.bp
index fa68c4e..f2598a7 100644
--- a/biometrics/face/1.0/vts/functional/Android.bp
+++ b/biometrics/face/1.0/vts/functional/Android.bp
@@ -19,6 +19,6 @@
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalBiometricsFaceV1_0TargetTest.cpp"],
static_libs: ["android.hardware.biometrics.face@1.0"],
- test_suites: ["general-tests"],
+ test_suites: ["general-tests", "vts-core"],
}
diff --git a/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp b/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
index a4e95ed..7ac44a4 100644
--- a/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
+++ b/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
@@ -20,9 +20,10 @@
#include <android/hardware/biometrics/face/1.0/IBiometricsFaceClientCallback.h>
#include <VtsHalHidlTargetCallbackBase.h>
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
#include <android-base/logging.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
#include <chrono>
#include <cstdint>
@@ -124,27 +125,11 @@
}
};
-// Test environment for the BiometricsFace HAL.
-class FaceHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
- public:
- // Get the test environment singleton.
- static FaceHidlEnvironment* Instance() {
- static FaceHidlEnvironment* instance = new FaceHidlEnvironment;
- return instance;
- }
-
- void registerTestServices() override { registerTestService<IBiometricsFace>(); }
-
- private:
- FaceHidlEnvironment() = default;
-};
-
// Test class for the BiometricsFace HAL.
-class FaceHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class FaceHidlTest : public ::testing::TestWithParam<std::string> {
public:
void SetUp() override {
- mService = ::testing::VtsHalHidlTargetTestBase::getService<IBiometricsFace>(
- FaceHidlEnvironment::Instance()->getServiceName<IBiometricsFace>());
+ mService = IBiometricsFace::getService(GetParam());
ASSERT_NE(mService, nullptr);
mCallback = new FaceCallback();
mCallback->SetWaitTimeoutDefault(kTimeout);
@@ -167,7 +152,7 @@
// generateChallenge should always return a unique, cryptographically secure,
// non-zero number.
-TEST_F(FaceHidlTest, GenerateChallengeTest) {
+TEST_P(FaceHidlTest, GenerateChallengeTest) {
std::map<uint64_t, int> m;
for (int i = 0; i < kGenerateChallengeIterations; ++i) {
Return<void> ret =
@@ -182,7 +167,7 @@
}
// enroll with an invalid (all zeroes) HAT should fail.
-TEST_F(FaceHidlTest, EnrollZeroHatTest) {
+TEST_P(FaceHidlTest, EnrollZeroHatTest) {
// Filling HAT with zeros
hidl_vec<uint8_t> token(69);
for (size_t i = 0; i < 69; i++) {
@@ -200,7 +185,7 @@
}
// enroll with an invalid HAT should fail.
-TEST_F(FaceHidlTest, EnrollGarbageHatTest) {
+TEST_P(FaceHidlTest, EnrollGarbageHatTest) {
// Filling HAT with pseudorandom invalid data.
// Using default seed to make the test reproducible.
std::mt19937 gen(std::mt19937::default_seed);
@@ -221,7 +206,7 @@
}
// setFeature with an invalid (all zeros) HAT should fail.
-TEST_F(FaceHidlTest, SetFeatureZeroHatTest) {
+TEST_P(FaceHidlTest, SetFeatureZeroHatTest) {
hidl_vec<uint8_t> token(69);
for (size_t i = 0; i < 69; i++) {
token[i] = 0;
@@ -232,7 +217,7 @@
}
// setFeature with an invalid HAT should fail.
-TEST_F(FaceHidlTest, SetFeatureGarbageHatTest) {
+TEST_P(FaceHidlTest, SetFeatureGarbageHatTest) {
// Filling HAT with pseudorandom invalid data.
// Using default seed to make the test reproducible.
std::mt19937 gen(std::mt19937::default_seed);
@@ -254,16 +239,16 @@
ASSERT_TRUE(res.isOk());
}
-TEST_F(FaceHidlTest, GetFeatureRequireAttentionTest) {
+TEST_P(FaceHidlTest, GetFeatureRequireAttentionTest) {
assertGetFeatureFails(mService, 0 /* faceId */, Feature::REQUIRE_ATTENTION);
}
-TEST_F(FaceHidlTest, GetFeatureRequireDiversityTest) {
+TEST_P(FaceHidlTest, GetFeatureRequireDiversityTest) {
assertGetFeatureFails(mService, 0 /* faceId */, Feature::REQUIRE_DIVERSITY);
}
// revokeChallenge should always return within the timeout
-TEST_F(FaceHidlTest, RevokeChallengeTest) {
+TEST_P(FaceHidlTest, RevokeChallengeTest) {
auto start = std::chrono::system_clock::now();
Return<Status> ret = mService->revokeChallenge();
auto elapsed = std::chrono::system_clock::now() - start;
@@ -272,14 +257,14 @@
}
// The call to getAuthenticatorId should succeed.
-TEST_F(FaceHidlTest, GetAuthenticatorIdTest) {
+TEST_P(FaceHidlTest, GetAuthenticatorIdTest) {
Return<void> ret = mService->getAuthenticatorId(
[](const OptionalUint64& res) { ASSERT_EQ(Status::OK, res.status); });
ASSERT_TRUE(ret.isOk());
}
// The call to enumerate should succeed.
-TEST_F(FaceHidlTest, EnumerateTest) {
+TEST_P(FaceHidlTest, EnumerateTest) {
Return<Status> ret = mService->enumerate();
ASSERT_EQ(Status::OK, static_cast<Status>(ret));
auto res = mCallback->WaitForCallback(kCallbackNameOnEnumerate);
@@ -288,21 +273,21 @@
}
// The call to remove should succeed for any faceId
-TEST_F(FaceHidlTest, RemoveFaceTest) {
+TEST_P(FaceHidlTest, RemoveFaceTest) {
// Remove a face
Return<Status> ret = mService->remove(kFaceId);
ASSERT_EQ(Status::OK, static_cast<Status>(ret));
}
// Remove should accept 0 to delete all faces
-TEST_F(FaceHidlTest, RemoveAllFacesTest) {
+TEST_P(FaceHidlTest, RemoveAllFacesTest) {
// Remove all faces
Return<Status> ret = mService->remove(0);
ASSERT_EQ(Status::OK, static_cast<Status>(ret));
}
// Active user should successfully set to a writable location.
-TEST_F(FaceHidlTest, SetActiveUserTest) {
+TEST_P(FaceHidlTest, SetActiveUserTest) {
// Create an active user
Return<Status> ret = mService->setActiveUser(2, kFacedataDir);
ASSERT_EQ(Status::OK, static_cast<Status>(ret));
@@ -313,7 +298,7 @@
}
// Active user should fail to set to an unwritable location.
-TEST_F(FaceHidlTest, SetActiveUserUnwritableTest) {
+TEST_P(FaceHidlTest, SetActiveUserUnwritableTest) {
// Create an active user to an unwritable location (device root dir)
Return<Status> ret = mService->setActiveUser(3, "/");
ASSERT_NE(Status::OK, static_cast<Status>(ret));
@@ -324,7 +309,7 @@
}
// Active user should fail to set to a null location.
-TEST_F(FaceHidlTest, SetActiveUserNullTest) {
+TEST_P(FaceHidlTest, SetActiveUserNullTest) {
// Create an active user to a null location.
Return<Status> ret = mService->setActiveUser(4, nullptr);
ASSERT_NE(Status::OK, static_cast<Status>(ret));
@@ -336,7 +321,7 @@
// Cancel should always return CANCELED from any starting state including
// the IDLE state.
-TEST_F(FaceHidlTest, CancelTest) {
+TEST_P(FaceHidlTest, CancelTest) {
Return<Status> ret = mService->cancel();
// check that we were able to make an IPC request successfully
ASSERT_EQ(Status::OK, static_cast<Status>(ret));
@@ -347,7 +332,7 @@
EXPECT_EQ(FaceError::CANCELED, res.args->error);
}
-TEST_F(FaceHidlTest, OnLockoutChangedTest) {
+TEST_P(FaceHidlTest, OnLockoutChangedTest) {
// Update active user and ensure onLockoutChanged was called.
Return<Status> ret = mService->setActiveUser(kUserId + 1, kFacedataDir);
ASSERT_EQ(Status::OK, static_cast<Status>(ret));
@@ -359,11 +344,7 @@
} // anonymous namespace
-int main(int argc, char** argv) {
- ::testing::AddGlobalTestEnvironment(FaceHidlEnvironment::Instance());
- ::testing::InitGoogleTest(&argc, argv);
- FaceHidlEnvironment::Instance()->init(&argc, argv);
- int status = RUN_ALL_TESTS();
- LOG(INFO) << "Test result = " << status;
- return status;
-}
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, FaceHidlTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(IBiometricsFace::descriptor)),
+ android::hardware::PrintInstanceNameToString);
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index a500ca0..f0b5966 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -256,7 +256,7 @@
<hal format="hidl" optional="false">
<name>android.hardware.keymaster</name>
<version>3.0</version>
- <version>4.0</version>
+ <version>4.0-1</version>
<interface>
<name>IKeymasterDevice</name>
<instance>default</instance>
@@ -264,7 +264,7 @@
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.keymaster</name>
- <version>4.0</version>
+ <version>4.0-1</version>
<interface>
<name>IKeymasterDevice</name>
<instance>strongbox</instance>
diff --git a/current.txt b/current.txt
index e55527f..c1991c3 100644
--- a/current.txt
+++ b/current.txt
@@ -591,6 +591,9 @@
ce8dbe76eb9ee94b46ef98f725be992e760a5751073d4f4912484026541371f3 android.hardware.health@2.1::IHealth
26f04510a0b57aba5167c5c0a7c2f077c2acbb98b81902a072517829fd9fd67f android.hardware.health@2.1::IHealthInfoCallback
db47f4ceceb1f06c656f39caa70c557b0f8471ef59fd58611bea667ffca20101 android.hardware.health@2.1::types
+c228aaa27f66c48e147159a4f4996c5273191fece1b08de31bd171c61334855e android.hardware.keymaster@4.1::IKeymasterDevice
+adb0efdf1462e9b2e742c0dcadd598666aac551f178be06e755bfcdf5797abd0 android.hardware.keymaster@4.1::IOperation
+7a04ea5595ed418ca3e91c28b8bd7353dd988be9be7b0c8c9e64fb4b77bd4523 android.hardware.keymaster@4.1::types
9e59fffceed0dd72a9799e04505db5f777bbbea1af0695ba4107ef6d967c6fda android.hardware.neuralnetworks@1.3::IDevice
4a6c3b3556da951b4def21ba579a227c022980fe4465df6cdfbe20628fa75f5a android.hardware.neuralnetworks@1.3::IPreparedModel
94e803236398bed1febb11cc21051bc42ec003700139b099d6c479e02a7ca3c3 android.hardware.neuralnetworks@1.3::IPreparedModelCallback
diff --git a/drm/1.0/default/CryptoPlugin.cpp b/drm/1.0/default/CryptoPlugin.cpp
index 666653b..8ddc380 100644
--- a/drm/1.0/default/CryptoPlugin.cpp
+++ b/drm/1.0/default/CryptoPlugin.cpp
@@ -101,11 +101,20 @@
std::unique_ptr<android::CryptoPlugin::SubSample[]> legacySubSamples =
std::make_unique<android::CryptoPlugin::SubSample[]>(subSamples.size());
+ size_t destSize = 0;
for (size_t i = 0; i < subSamples.size(); i++) {
- legacySubSamples[i].mNumBytesOfClearData
- = subSamples[i].numBytesOfClearData;
- legacySubSamples[i].mNumBytesOfEncryptedData
- = subSamples[i].numBytesOfEncryptedData;
+ uint32_t numBytesOfClearData = subSamples[i].numBytesOfClearData;
+ legacySubSamples[i].mNumBytesOfClearData = numBytesOfClearData;
+ uint32_t numBytesOfEncryptedData = subSamples[i].numBytesOfEncryptedData;
+ legacySubSamples[i].mNumBytesOfEncryptedData = numBytesOfEncryptedData;
+ if (__builtin_add_overflow(destSize, numBytesOfClearData, &destSize)) {
+ _hidl_cb(Status::BAD_VALUE, 0, "subsample clear size overflow");
+ return Void();
+ }
+ if (__builtin_add_overflow(destSize, numBytesOfEncryptedData, &destSize)) {
+ _hidl_cb(Status::BAD_VALUE, 0, "subsample encrypted size overflow");
+ return Void();
+ }
}
AString detailMessage;
@@ -137,11 +146,24 @@
_hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
return Void();
}
+
+ if (destSize > destBuffer.size) {
+ _hidl_cb(Status::BAD_VALUE, 0, "subsample sum too large");
+ return Void();
+ }
+
destPtr = static_cast<void *>(base + destination.nonsecureMemory.offset);
} else if (destination.type == BufferType::NATIVE_HANDLE) {
+ if (!secure) {
+ _hidl_cb(Status::BAD_VALUE, 0, "native handle destination must be secure");
+ return Void();
+ }
native_handle_t *handle = const_cast<native_handle_t *>(
destination.secureMemory.getNativeHandle());
destPtr = static_cast<void *>(handle);
+ } else {
+ _hidl_cb(Status::BAD_VALUE, 0, "invalid destination type");
+ return Void();
}
ssize_t result = mLegacyPlugin->decrypt(secure, keyId.data(), iv.data(),
legacyMode, legacyPattern, srcPtr, legacySubSamples.get(),
diff --git a/gatekeeper/1.0/vts/functional/Android.bp b/gatekeeper/1.0/vts/functional/Android.bp
index f55e5d2..a115285 100644
--- a/gatekeeper/1.0/vts/functional/Android.bp
+++ b/gatekeeper/1.0/vts/functional/Android.bp
@@ -19,5 +19,5 @@
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["VtsHalGatekeeperV1_0TargetTest.cpp"],
static_libs: ["android.hardware.gatekeeper@1.0"],
- test_suites: ["general-tests"],
+ test_suites: ["general-tests", "vts-core"],
}
diff --git a/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp b/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp
index 715e9fc..afc737c 100644
--- a/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp
+++ b/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp
@@ -24,7 +24,10 @@
#include <inttypes.h>
#include <unistd.h>
+#include <gtest/gtest.h>
#include <hardware/hw_auth_token.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
#include <android/log.h>
#include <android/hardware/gatekeeper/1.0/IGatekeeper.h>
@@ -32,9 +35,6 @@
#include <log/log.h>
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
-
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::gatekeeper::V1_0::IGatekeeper;
@@ -78,22 +78,8 @@
return auth_token;
}
-// Test environment for Gatekeeper HIDL HAL.
-class GatekeeperHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
- public:
- // get the test environment singleton
- static GatekeeperHidlEnvironment* Instance() {
- static GatekeeperHidlEnvironment* instance = new GatekeeperHidlEnvironment;
- return instance;
- }
-
- virtual void registerTestServices() override { registerTestService<IGatekeeper>(); }
- private:
- GatekeeperHidlEnvironment() {}
-};
-
// The main test class for Gatekeeper HIDL HAL.
-class GatekeeperHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class GatekeeperHidlTest : public ::testing::TestWithParam<std::string> {
protected:
void setUid(uint32_t uid) { uid_ = uid; }
@@ -204,8 +190,7 @@
GatekeeperHidlTest() : uid_(0) {}
virtual void SetUp() override {
GatekeeperResponse rsp;
- gatekeeper_ = ::testing::VtsHalHidlTargetTestBase::getService<IGatekeeper>(
- GatekeeperHidlEnvironment::Instance()->getServiceName<IGatekeeper>());
+ gatekeeper_ = IGatekeeper::getService(GetParam());
ASSERT_NE(nullptr, gatekeeper_.get());
doDeleteAllUsers(rsp);
}
@@ -219,7 +204,7 @@
/**
* Ensure we can enroll new password
*/
-TEST_F(GatekeeperHidlTest, EnrollSuccess) {
+TEST_P(GatekeeperHidlTest, EnrollSuccess) {
hidl_vec<uint8_t> password;
GatekeeperResponse rsp;
ALOGI("Testing Enroll (expected success)");
@@ -231,7 +216,7 @@
/**
* Ensure we can not enroll empty password
*/
-TEST_F(GatekeeperHidlTest, EnrollNoPassword) {
+TEST_P(GatekeeperHidlTest, EnrollNoPassword) {
hidl_vec<uint8_t> password;
GatekeeperResponse rsp;
ALOGI("Testing Enroll (expected failure)");
@@ -242,7 +227,7 @@
/**
* Ensure we can successfully verify previously enrolled password
*/
-TEST_F(GatekeeperHidlTest, VerifySuccess) {
+TEST_P(GatekeeperHidlTest, VerifySuccess) {
GatekeeperResponse enrollRsp;
GatekeeperResponse verifyRsp;
hidl_vec<uint8_t> password;
@@ -258,7 +243,7 @@
* Ensure we can securely update password (keep the same
* secure user_id) if we prove we know old password
*/
-TEST_F(GatekeeperHidlTest, TrustedReenroll) {
+TEST_P(GatekeeperHidlTest, TrustedReenroll) {
GatekeeperResponse enrollRsp;
GatekeeperRequest reenrollReq;
GatekeeperResponse reenrollRsp;
@@ -297,7 +282,7 @@
* Ensure we can update password (and get new
* secure user_id) if we don't know old password
*/
-TEST_F(GatekeeperHidlTest, UntrustedReenroll) {
+TEST_P(GatekeeperHidlTest, UntrustedReenroll) {
GatekeeperResponse enrollRsp;
GatekeeperResponse reenrollRsp;
GatekeeperResponse verifyRsp;
@@ -327,7 +312,7 @@
/**
* Ensure we dont get successful verify with invalid data
*/
-TEST_F(GatekeeperHidlTest, VerifyNoData) {
+TEST_P(GatekeeperHidlTest, VerifyNoData) {
hidl_vec<uint8_t> password;
hidl_vec<uint8_t> passwordHandle;
GatekeeperResponse verifyRsp;
@@ -341,7 +326,7 @@
/**
* Ensure we can not verify password after we enrolled it and then deleted user
*/
-TEST_F(GatekeeperHidlTest, DeleteUserTest) {
+TEST_P(GatekeeperHidlTest, DeleteUserTest) {
hidl_vec<uint8_t> password;
GatekeeperResponse enrollRsp;
GatekeeperResponse verifyRsp;
@@ -368,7 +353,7 @@
/**
* Ensure we can not delete a user that does not exist
*/
-TEST_F(GatekeeperHidlTest, DeleteInvalidUserTest) {
+TEST_P(GatekeeperHidlTest, DeleteInvalidUserTest) {
hidl_vec<uint8_t> password;
GatekeeperResponse enrollRsp;
GatekeeperResponse verifyRsp;
@@ -400,7 +385,7 @@
* Ensure we can not verify passwords after we enrolled them and then deleted
* all users
*/
-TEST_F(GatekeeperHidlTest, DeleteAllUsersTest) {
+TEST_P(GatekeeperHidlTest, DeleteAllUsersTest) {
struct UserData {
uint32_t userId;
hidl_vec<uint8_t> password;
@@ -448,11 +433,7 @@
ALOGI("Testing deleteAllUsers done: rsp=%" PRIi32, delAllRsp.code);
}
-int main(int argc, char **argv) {
- ::testing::AddGlobalTestEnvironment(GatekeeperHidlEnvironment::Instance());
- ::testing::InitGoogleTest(&argc, argv);
- GatekeeperHidlEnvironment::Instance()->init(&argc, argv);
- int status = RUN_ALL_TESTS();
- ALOGI("Test result = %d", status);
- return status;
-}
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, GatekeeperHidlTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(IGatekeeper::descriptor)),
+ android::hardware::PrintInstanceNameToString);
diff --git a/health/2.0/default/healthd_common_adapter.cpp b/health/2.0/default/healthd_common_adapter.cpp
index 8fc689d..0b5d869 100644
--- a/health/2.0/default/healthd_common_adapter.cpp
+++ b/health/2.0/default/healthd_common_adapter.cpp
@@ -49,11 +49,14 @@
static std::unique_ptr<HealthLoopAdapter> health_loop;
int healthd_register_event(int fd, void (*handler)(uint32_t), EventWakeup wakeup) {
+ if (!health_loop) return -1;
+
auto wrapped_handler = [handler](auto*, uint32_t epevents) { handler(epevents); };
return health_loop->RegisterEvent(fd, wrapped_handler, wakeup);
}
void healthd_battery_update_internal(bool charger_online) {
+ if (!health_loop) return;
health_loop->AdjustWakealarmPeriods(charger_online);
}
diff --git a/keymaster/4.1/Android.bp b/keymaster/4.1/Android.bp
new file mode 100644
index 0000000..eaa7e41
--- /dev/null
+++ b/keymaster/4.1/Android.bp
@@ -0,0 +1,19 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.keymaster@4.1",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "types.hal",
+ "IKeymasterDevice.hal",
+ "IOperation.hal",
+ ],
+ interfaces: [
+ "android.hardware.keymaster@4.0",
+ "android.hidl.base@1.0",
+ ],
+ gen_java: false,
+}
diff --git a/keymaster/4.1/IKeymasterDevice.hal b/keymaster/4.1/IKeymasterDevice.hal
new file mode 100644
index 0000000..64d2c9f
--- /dev/null
+++ b/keymaster/4.1/IKeymasterDevice.hal
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+package android.hardware.keymaster@4.1;
+
+import @4.0::ErrorCode;
+import @4.0::HardwareAuthToken;
+import @4.0::IKeymasterDevice;
+import @4.0::KeyParameter;
+import @4.0::KeyPurpose;
+import @4.0::OperationHandle;
+import IOperation;
+
+/**
+ * @4.1::IKeymasterDevice is a minor extension to @4.0::IKeymasterDevice. It adds support for
+ *
+ * - Partial hardware enforcment of UNLOCKED_DEVICE_REQUIRED keys;
+ * - Device-unique attestaion;
+ * - Early boot only keys;
+ * - Better cleanup of operations when clients die without completing or aborting them.
+ */
+interface IKeymasterDevice extends @4.0::IKeymasterDevice {
+ /**
+ * Called by client to notify the IKeymasterDevice that the device is now locked, and keys with
+ * the UNLOCKED_DEVICE_REQUIRED tag should no longer be usable. When this function is called,
+ * the IKeymasterDevice should note the current timestamp, and attempts to use
+ * UNLOCKED_DEVICE_REQUIRED keys must be rejected with Error::DEVICE_LOCKED until an
+ * authentication token with a later timestamp is presented. If the `passwordOnly' argument is
+ * set to true the sufficiently-recent authentication token must indicate that the user
+ * authenticated with a password, not a biometric.
+ *
+ * @param passwordOnly specifies whether the device must be unlocked with a password, rather
+ * than a biometric, before UNLOCKED_DEVICE_REQUIRED keys can be used.
+ */
+ deviceLocked(bool passwordOnly) generates (ErrorCode error);
+
+ /**
+ * Called by client to notify the IKeymasterDevice that the device has left the early boot
+ * state, and that keys with the EARLY_BOOT_ONLY tag may no longer be used. All attempts to use
+ * an EARLY_BOOT_ONLY key after this method is called must fail with Error::INVALID_KEY_BLOB.
+ */
+ earlyBootEnded() generates (ErrorCode error);
+
+ /**
+ * Begins a cryptographic operation. beginOp() is a variation on begin(). beginOp() has
+ * identical functionality to begin, but instead of an OperationHandle it returns an IOperation
+ * object. An IKeymasterDevice HAL service must call linkToDeath() on the Operation before
+ * returning it, and the provided hidl_death_recipient, if called, must abort() the operation.
+ * This is to ensure that in the event a client crashes while an operation is in progress, the
+ * operation slot is freed and available for use by other clients.
+ *
+ * @4.1::IKeymasterDevices must implement both beginOp() and begin().
+ */
+ beginOp(KeyPurpose purpose, vec<uint8_t> keyBlob, vec<KeyParameter> inParams,
+ HardwareAuthToken authToken)
+ generates (ErrorCode error, vec<KeyParameter> outParam, IOperation operation);
+};
diff --git a/keymaster/4.1/IOperation.hal b/keymaster/4.1/IOperation.hal
new file mode 100644
index 0000000..7103e9e
--- /dev/null
+++ b/keymaster/4.1/IOperation.hal
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+package android.hardware.keymaster@4.1;
+
+import @4.0::ErrorCode;
+import @4.0::OperationHandle;
+
+/**
+ * IOperation represents an in-progress IKeymasterDevice operation. It is returned by
+ * IKeymasterDevice.beginOp().
+ */
+interface IOperation {
+ /**
+ * Returns the operation handle to be used as an authentication challenge.
+ */
+ getOperationChallenge() generates (ErrorCode error, OperationHandle operation);
+};
diff --git a/keymaster/4.1/default/Android.bp b/keymaster/4.1/default/Android.bp
new file mode 100644
index 0000000..b06878b
--- /dev/null
+++ b/keymaster/4.1/default/Android.bp
@@ -0,0 +1,38 @@
+//
+// Copyright (C) 2019 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.
+//
+
+cc_binary {
+ name: "android.hardware.keymaster@4.1-service",
+ defaults: ["hidl_defaults"],
+ relative_install_path: "hw",
+ vendor: true,
+ init_rc: ["android.hardware.keymaster@4.1-service.rc"],
+ srcs: ["service.cpp"],
+
+ shared_libs: [
+ "android.hardware.keymaster@4.0",
+ "android.hardware.keymaster@4.1",
+ "libbase",
+ "libcutils",
+ "libhardware",
+ "libhidlbase",
+ "libkeymaster4",
+ "libkeymaster41",
+ "liblog",
+ "libutils",
+ ],
+
+}
diff --git a/keymaster/4.1/default/OWNERS b/keymaster/4.1/default/OWNERS
new file mode 100644
index 0000000..335660d
--- /dev/null
+++ b/keymaster/4.1/default/OWNERS
@@ -0,0 +1,2 @@
+jdanis@google.com
+swillden@google.com
diff --git a/keymaster/4.1/default/android.hardware.keymaster@4.1-service.rc b/keymaster/4.1/default/android.hardware.keymaster@4.1-service.rc
new file mode 100644
index 0000000..740b3c2
--- /dev/null
+++ b/keymaster/4.1/default/android.hardware.keymaster@4.1-service.rc
@@ -0,0 +1,6 @@
+service vendor.keymaster-4-1 /vendor/bin/hw/android.hardware.keymaster@4.1-service
+ interface android.hardware.keymaster@4.0::IKeymasterDevice default
+ interface android.hardware.keymaster@4.1::IKeymasterDevice default
+ class early_hal
+ user system
+ group system drmrpc
diff --git a/keymaster/4.1/default/service.cpp b/keymaster/4.1/default/service.cpp
new file mode 100644
index 0000000..d79a291
--- /dev/null
+++ b/keymaster/4.1/default/service.cpp
@@ -0,0 +1,35 @@
+/*
+** Copyright 2019, 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 <android-base/logging.h>
+#include <android/hardware/keymaster/4.1/IKeymasterDevice.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include <AndroidKeymaster41Device.h>
+
+using android::hardware::keymaster::V4_0::SecurityLevel;
+
+int main() {
+ ::android::hardware::configureRpcThreadpool(1, true /* willJoinThreadpool */);
+ auto keymaster = ::keymaster::V4_1::CreateKeymasterDevice(SecurityLevel::SOFTWARE);
+ auto status = keymaster->registerAsService();
+ if (status != android::OK) {
+ LOG(FATAL) << "Could not register service for Keymaster 4.1 (" << status << ")";
+ }
+
+ android::hardware::joinRpcThreadpool();
+ return -1; // Should never get here.
+}
diff --git a/keymaster/4.1/support/Android.bp b/keymaster/4.1/support/Android.bp
new file mode 100644
index 0000000..34b6108
--- /dev/null
+++ b/keymaster/4.1/support/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2019 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.
+//
+
+cc_library {
+ name: "libkeymaster4_1support",
+ vendor_available: true,
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ ],
+ export_include_dirs: ["include"],
+ shared_libs: [
+ "android.hardware.keymaster@3.0",
+ "android.hardware.keymaster@4.0",
+ "android.hardware.keymaster@4.1",
+ "libkeymaster4support",
+ ]
+}
diff --git a/keymaster/4.1/support/include/keymasterV4_1/authorization_set.h b/keymaster/4.1/support/include/keymasterV4_1/authorization_set.h
new file mode 100644
index 0000000..afc0eaf
--- /dev/null
+++ b/keymaster/4.1/support/include/keymasterV4_1/authorization_set.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#ifndef HARDWARE_INTERFACES_KEYMASTER_V4_1_SUPPORT_INCLUDE_AUTHORIZATION_SET_H_
+#define HARDWARE_INTERFACES_KEYMASTER_V4_1_SUPPORT_INCLUDE_AUTHORIZATION_SET_H_
+
+#include <keymasterV4_0/authorization_set.h>
+
+#include <keymasterV4_1/keymaster_tags.h>
+
+namespace android::hardware::keymaster::V4_1 {
+
+using V4_0::AuthorizationSet;
+using V4_0::AuthorizationSetBuilder;
+using V4_0::KeyParameter;
+
+} // namespace android::hardware::keymaster::V4_1
+
+#endif // HARDWARE_INTERFACES_KEYMASTER_V4_1_SUPPORT_INCLUDE_AUTHORIZATION_SET_H_
diff --git a/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h b/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h
new file mode 100644
index 0000000..6ffe8e1
--- /dev/null
+++ b/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#ifndef HARDWARE_INTERFACES_KEYMASTER_V4_1_SUPPORT_INCLUDE_KEYMASTER_TAGS_H_
+#define HARDWARE_INTERFACES_KEYMASTER_V4_1_SUPPORT_INCLUDE_KEYMASTER_TAGS_H_
+
+#include <android/hardware/keymaster/4.1/types.h>
+
+#include <keymasterV4_0/keymaster_tags.h>
+
+namespace android::hardware::keymaster::V4_1 {
+
+using V4_0::BlockMode;
+using V4_0::Digest;
+using V4_0::EcCurve;
+using V4_0::ErrorCode;
+using V4_0::HardwareAuthToken;
+using V4_0::KeyParameter;
+using V4_0::PaddingMode;
+using V4_0::TagType;
+using V4_0::VerificationToken;
+
+using V4_0::TypedTag;
+
+using V4_0::TAG_ACTIVE_DATETIME;
+using V4_0::TAG_ALGORITHM;
+using V4_0::TAG_ALLOW_WHILE_ON_BODY;
+using V4_0::TAG_APPLICATION_DATA;
+using V4_0::TAG_APPLICATION_ID;
+using V4_0::TAG_ASSOCIATED_DATA;
+using V4_0::TAG_ATTESTATION_APPLICATION_ID;
+using V4_0::TAG_ATTESTATION_CHALLENGE;
+using V4_0::TAG_AUTH_TIMEOUT;
+using V4_0::TAG_BLOB_USAGE_REQUIREMENTS;
+using V4_0::TAG_BLOCK_MODE;
+using V4_0::TAG_BOOT_PATCHLEVEL;
+using V4_0::TAG_BOOTLOADER_ONLY;
+using V4_0::TAG_CALLER_NONCE;
+using V4_0::TAG_CONFIRMATION_TOKEN;
+using V4_0::TAG_CREATION_DATETIME;
+using V4_0::TAG_DIGEST;
+using V4_0::TAG_EC_CURVE;
+using V4_0::TAG_HARDWARE_TYPE;
+using V4_0::TAG_INCLUDE_UNIQUE_ID;
+using V4_0::TAG_INVALID;
+using V4_0::TAG_KEY_SIZE;
+using V4_0::TAG_MAC_LENGTH;
+using V4_0::TAG_MAX_USES_PER_BOOT;
+using V4_0::TAG_MIN_MAC_LENGTH;
+using V4_0::TAG_MIN_SECONDS_BETWEEN_OPS;
+using V4_0::TAG_NO_AUTH_REQUIRED;
+using V4_0::TAG_NONCE;
+using V4_0::TAG_ORIGIN;
+using V4_0::TAG_ORIGINATION_EXPIRE_DATETIME;
+using V4_0::TAG_OS_PATCHLEVEL;
+using V4_0::TAG_OS_VERSION;
+using V4_0::TAG_PADDING;
+using V4_0::TAG_PURPOSE;
+using V4_0::TAG_RESET_SINCE_ID_ROTATION;
+using V4_0::TAG_ROLLBACK_RESISTANCE;
+using V4_0::TAG_ROOT_OF_TRUST;
+using V4_0::TAG_RSA_PUBLIC_EXPONENT;
+using V4_0::TAG_TRUSTED_CONFIRMATION_REQUIRED;
+using V4_0::TAG_TRUSTED_USER_PRESENCE_REQUIRED;
+using V4_0::TAG_UNIQUE_ID;
+using V4_0::TAG_UNLOCKED_DEVICE_REQUIRED;
+using V4_0::TAG_USAGE_EXPIRE_DATETIME;
+using V4_0::TAG_USER_AUTH_TYPE;
+using V4_0::TAG_USER_ID;
+using V4_0::TAG_USER_SECURE_ID;
+using V4_0::TAG_VENDOR_PATCHLEVEL;
+
+#define DECLARE_KM_4_1_TYPED_TAG(name) \
+ typedef typename V4_0::Tag2TypedTag<(static_cast<V4_0::Tag>(V4_1::Tag::name))>::type \
+ TAG_##name##_t; \
+ static TAG_##name##_t TAG_##name;
+
+DECLARE_KM_4_1_TYPED_TAG(EARLY_BOOT_ONLY);
+DECLARE_KM_4_1_TYPED_TAG(DEVICE_UNIQUE_ATTESTATION);
+
+} // namespace android::hardware::keymaster::V4_1
+
+#endif // HARDWARE_INTERFACES_KEYMASTER_V4_1_SUPPORT_INCLUDE_KEYMASTER_TAGS_H_
diff --git a/keymaster/4.1/types.hal b/keymaster/4.1/types.hal
new file mode 100644
index 0000000..bdf1731
--- /dev/null
+++ b/keymaster/4.1/types.hal
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+package android.hardware.keymaster@4.1;
+
+import @4.0::ErrorCode;
+import @4.0::Tag;
+import @4.0::TagType;
+
+enum Tag : @4.0::Tag {
+ /**
+ * Keys tagged with EARLY_BOOT_ONLY may only be used, or created, during early boot, until
+ * IKeymasterDevice::earlyBootEnded() is called.
+ */
+ EARLY_BOOT_ONLY = TagType:BOOL | 305,
+ /**
+ * DEVICE_UNIQUE_ATTESTATION is an argument to IKeymasterDevice::attestKey(). It indicates that
+ * attestation using a device-unique key is requested, rather than a batch key. Only
+ * SecurityLevel::STRONGBOX IKeymasterDevices may support device-unique attestations.
+ * SecurityLevel::TRUSTED_ENVIRONMENT IKeymasterDevices must return ErrorCode::INVALID_ARGUMENT
+ * if they receive DEVICE_UNIQUE_ATTESTATION. SecurityLevel::STRONGBOX IKeymasterDevices need
+ * not support DEVICE_UNIQUE_ATTESTATION, and return ErrorCode::CANNOT_ATTEST_IDS if they do not
+ * support it.
+ *
+ * IKeymasterDevice implementations that support device-unique attestation MUST add the
+ * DEVICE_UNIQUE_ATTESTATION tag to device-unique attestations.
+ */
+ DEVICE_UNIQUE_ATTESTATION = TagType:BOOL | 720,
+};
diff --git a/keymaster/4.1/vts/OWNERS b/keymaster/4.1/vts/OWNERS
new file mode 100644
index 0000000..335660d
--- /dev/null
+++ b/keymaster/4.1/vts/OWNERS
@@ -0,0 +1,2 @@
+jdanis@google.com
+swillden@google.com
diff --git a/keymaster/4.1/vts/functional/Android.bp b/keymaster/4.1/vts/functional/Android.bp
new file mode 100644
index 0000000..f5a0c9c
--- /dev/null
+++ b/keymaster/4.1/vts/functional/Android.bp
@@ -0,0 +1,30 @@
+//
+// Copyright (C) 2019 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.
+//
+
+cc_test {
+ name: "VtsHalKeymasterV4_1TargetTest",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: [
+ "EarlyBootKeyTest.cpp",
+ ],
+ static_libs: [
+ "android.hardware.keymaster@4.0",
+ "android.hardware.keymaster@4.1",
+ "libkeymaster4support",
+ "libkeymaster4_1support",
+ ],
+ test_suites: ["vts-core"],
+}
diff --git a/keymaster/4.1/vts/functional/EarlyBootKeyTest.cpp b/keymaster/4.1/vts/functional/EarlyBootKeyTest.cpp
new file mode 100644
index 0000000..4a19010
--- /dev/null
+++ b/keymaster/4.1/vts/functional/EarlyBootKeyTest.cpp
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+namespace android::hardware::keymaster::V4_1::test {
+
+// TODO(swillden): Put tests here.
+
+} // namespace android::hardware::keymaster::V4_1::test
diff --git a/media/omx/1.0/vts/functional/README.md b/media/omx/1.0/vts/functional/README.md
index acffc42..274b30d 100644
--- a/media/omx/1.0/vts/functional/README.md
+++ b/media/omx/1.0/vts/functional/README.md
@@ -18,17 +18,17 @@
usage:
-VtsHalMediaOmxV1\_0TargetAudioDecTest -I default -C <comp name> -R audio_decoder.<comp class> -P /sdcard/media/
+VtsHalMediaOmxV1\_0TargetAudioDecTest -I default -C <comp name> -R audio_decoder.<comp class> -P /data/local/tmp/media/
-VtsHalMediaOmxV1\_0TargetAudioEncTest -I default -C <comp name> -R audio_encoder.<comp class> -P /sdcard/media/
+VtsHalMediaOmxV1\_0TargetAudioEncTest -I default -C <comp name> -R audio_encoder.<comp class> -P /data/local/tmp/media/
#### video :
This folder includes test fixtures associated with testing video encoder and decoder components such as simple encoding of a raw clip or decoding of an elementary stream, end of stream test, timestamp deviations test, flush test and so on. These tests are aimed towards testing the plugin that connects the component to the omx core.
usage:
-VtsHalMediaOmxV1\_0TargetVideoDecTest -I default -C <comp name> -R video_decoder.<comp class> -P /sdcard/media/
+VtsHalMediaOmxV1\_0TargetVideoDecTest -I default -C <comp name> -R video_decoder.<comp class> -P /data/local/tmp/media/
-VtsHalMediaOmxV1\_0TargetVideoEncTest -I default -C <comp name> -R video_encoder.<comp class> -P /sdcard/media/
+VtsHalMediaOmxV1\_0TargetVideoEncTest -I default -C <comp name> -R video_encoder.<comp class> -P /data/local/tmp/media/
-While tesing audio/video encoder, decoder components, test fixtures require input files. These input are files are present in the folder 'res'. Before running the tests all the files in 'res' have to be placed in '/media/sdcard/' or a path of your choice and this path needs to be provided as an argument to the test application
\ No newline at end of file
+While tesing audio/video encoder, decoder components, test fixtures require input files. These input are files are present in the folder 'res'. Before running the tests all the files in 'res' have to be placed in '/data/local/tmp/media' or a path of your choice and this path needs to be provided as an argument to the test application
diff --git a/media/omx/1.0/vts/functional/common/Android.bp b/media/omx/1.0/vts/functional/common/Android.bp
index cdc52fb..5a79e55 100644
--- a/media/omx/1.0/vts/functional/common/Android.bp
+++ b/media/omx/1.0/vts/functional/common/Android.bp
@@ -29,6 +29,21 @@
"android.hidl.memory@1.0",
"android.hardware.media.omx@1.0",
"android.hardware.graphics.allocator@2.0",
+ "android.hardware.graphics.allocator@3.0",
+ "android.hardware.graphics.common@1.0",
+ "android.hardware.graphics.common@1.1",
+ "android.hardware.graphics.common@1.2",
+ "android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
+ ],
+ export_static_lib_headers: [
+ "android.hardware.graphics.allocator@2.0",
+ "android.hardware.graphics.allocator@3.0",
+ "android.hardware.graphics.common@1.0",
+ "android.hardware.graphics.common@1.1",
+ "android.hardware.graphics.common@1.2",
+ "android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
],
}
@@ -40,7 +55,12 @@
static_libs: [
"VtsHalMediaOmxV1_0CommonUtil",
"android.hardware.graphics.allocator@2.0",
+ "android.hardware.graphics.allocator@3.0",
+ "android.hardware.graphics.common@1.0",
+ "android.hardware.graphics.common@1.1",
+ "android.hardware.graphics.common@1.2",
"android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@3.0",
"android.hardware.graphics.bufferqueue@1.0",
"android.hardware.graphics.common@1.0",
"android.hardware.media.omx@1.0",
diff --git a/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp b/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
index f299e36..8d4c022 100644
--- a/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
+++ b/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
@@ -22,8 +22,11 @@
#include <android-base/logging.h>
#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <android/hardware/graphics/allocator/3.0/IAllocator.h>
#include <android/hardware/graphics/mapper/2.0/IMapper.h>
#include <android/hardware/graphics/mapper/2.0/types.h>
+#include <android/hardware/graphics/mapper/3.0/IMapper.h>
+#include <android/hardware/graphics/mapper/3.0/types.h>
#include <android/hardware/media/omx/1.0/IOmx.h>
#include <android/hardware/media/omx/1.0/IOmxNode.h>
#include <android/hardware/media/omx/1.0/IOmxObserver.h>
@@ -31,7 +34,9 @@
#include <android/hidl/allocator/1.0/IAllocator.h>
#include <android/hidl/memory/1.0/IMapper.h>
#include <android/hidl/memory/1.0/IMemory.h>
-#include <cutils/atomic.h>
+
+#include <atomic>
+#include <variant>
using ::android::hardware::graphics::common::V1_0::BufferUsage;
using ::android::hardware::graphics::common::V1_0::PixelFormat;
@@ -195,67 +200,104 @@
BufferInfo* buffer, uint32_t nFrameWidth,
uint32_t nFrameHeight, int32_t* nStride,
int format) {
- android::hardware::media::omx::V1_0::Status status;
- sp<android::hardware::graphics::allocator::V2_0::IAllocator> allocator =
- android::hardware::graphics::allocator::V2_0::IAllocator::getService();
- ASSERT_NE(nullptr, allocator.get());
+ struct AllocatorV2 : public GrallocV2 {
+ sp<IAllocator> mAllocator;
+ sp<IMapper> mMapper;
+ AllocatorV2(sp<IAllocator>&& allocator, sp<IMapper>&& mapper)
+ : mAllocator{std::move(allocator)}, mMapper{std::move(mapper)} {}
+ AllocatorV2() = default;
+ };
+ struct AllocatorV3 : public GrallocV3 {
+ sp<IAllocator> mAllocator;
+ sp<IMapper> mMapper;
+ AllocatorV3(sp<IAllocator>&& allocator, sp<IMapper>&& mapper)
+ : mAllocator{std::move(allocator)}, mMapper{std::move(mapper)} {}
+ AllocatorV3() = default;
+ };
+ std::variant<AllocatorV2, AllocatorV3> grallocVar;
- sp<android::hardware::graphics::mapper::V2_0::IMapper> mapper =
- android::hardware::graphics::mapper::V2_0::IMapper::getService();
- ASSERT_NE(mapper.get(), nullptr);
+ sp<android::hardware::graphics::mapper::V2_0::IMapper> mapper2{};
+ sp<android::hardware::graphics::mapper::V3_0::IMapper> mapper3{};
+ sp<android::hardware::graphics::allocator::V2_0::IAllocator> allocator2{};
+ sp<android::hardware::graphics::allocator::V3_0::IAllocator> allocator3 =
+ android::hardware::graphics::allocator::V3_0::IAllocator::getService();
+ if (allocator3) {
+ mapper3 =
+ android::hardware::graphics::mapper::V3_0::IMapper::getService();
+ ASSERT_NE(nullptr, mapper3.get());
+ grallocVar.emplace<AllocatorV3>(std::move(allocator3), std::move(mapper3));
+ } else {
+ allocator2 =
+ android::hardware::graphics::allocator::V2_0::IAllocator::getService();
+ ASSERT_NE(nullptr, allocator2.get());
+ mapper2 =
+ android::hardware::graphics::mapper::V2_0::IMapper::getService();
+ ASSERT_NE(nullptr, allocator2.get());
+ grallocVar.emplace<AllocatorV2>(std::move(allocator2), std::move(mapper2));
+ }
- android::hardware::graphics::mapper::V2_0::IMapper::BufferDescriptorInfo
- descriptorInfo;
- uint32_t usage;
-
- descriptorInfo.width = nFrameWidth;
- descriptorInfo.height = nFrameHeight;
- descriptorInfo.layerCount = 1;
- descriptorInfo.format = static_cast<PixelFormat>(format);
- descriptorInfo.usage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN);
- omxNode->getGraphicBufferUsage(
+ android::hardware::media::omx::V1_0::Status status{};
+ uint64_t usage{};
+ ASSERT_TRUE(omxNode->getGraphicBufferUsage(
portIndex,
[&status, &usage](android::hardware::media::omx::V1_0::Status _s,
uint32_t _n1) {
status = _s;
usage = _n1;
- });
- if (status == android::hardware::media::omx::V1_0::Status::OK) {
- descriptorInfo.usage |= usage;
- }
+ }).isOk());
+ ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
- ::android::hardware::hidl_vec<uint32_t> descriptor;
- android::hardware::graphics::mapper::V2_0::Error error;
- mapper->createDescriptor(
- descriptorInfo, [&error, &descriptor](
- android::hardware::graphics::mapper::V2_0::Error _s,
- ::android::hardware::hidl_vec<uint32_t> _n1) {
- error = _s;
- descriptor = _n1;
- });
- ASSERT_EQ(error, android::hardware::graphics::mapper::V2_0::Error::NONE);
+ static std::atomic_int32_t bufferIdCounter{0};
- static volatile int32_t nextId = 0;
- uint64_t id = static_cast<uint64_t>(getpid()) << 32;
- allocator->allocate(
- descriptor, 1,
- [&](android::hardware::graphics::mapper::V2_0::Error _s, uint32_t _n1,
- const ::android::hardware::hidl_vec<
- ::android::hardware::hidl_handle>& _n2) {
- ASSERT_EQ(android::hardware::graphics::mapper::V2_0::Error::NONE,
- _s);
- *nStride = _n1;
- buffer->omxBuffer.nativeHandle = _n2[0];
- buffer->omxBuffer.attr.anwBuffer.width = nFrameWidth;
- buffer->omxBuffer.attr.anwBuffer.height = nFrameHeight;
- buffer->omxBuffer.attr.anwBuffer.stride = _n1;
- buffer->omxBuffer.attr.anwBuffer.format = descriptorInfo.format;
- buffer->omxBuffer.attr.anwBuffer.usage = descriptorInfo.usage;
- buffer->omxBuffer.attr.anwBuffer.layerCount =
- descriptorInfo.layerCount;
- buffer->omxBuffer.attr.anwBuffer.id =
- id | static_cast<uint32_t>(android_atomic_inc(&nextId));
- });
+ std::visit([buffer, nFrameWidth, nFrameHeight, format, usage, nStride](auto&& gralloc) {
+ using Gralloc = std::remove_reference_t<decltype(gralloc)>;
+ using Descriptor = typename Gralloc::Descriptor;
+ using DescriptorInfo = typename Gralloc::DescriptorInfo;
+ using Error = typename Gralloc::Error;
+ using Format = typename Gralloc::Format;
+ using Usage = typename Gralloc::Usage;
+
+ Error error{};
+ Descriptor descriptor{};
+
+ DescriptorInfo descriptorInfo{};
+ descriptorInfo.width = nFrameWidth;
+ descriptorInfo.height = nFrameHeight;
+ descriptorInfo.layerCount = 1;
+ descriptorInfo.format = static_cast<Format>(format);
+ descriptorInfo.usage = usage | Usage(BufferUsage::CPU_READ_OFTEN);
+
+ gralloc.mMapper->createDescriptor(descriptorInfo,
+ [&error, &descriptor](
+ Error _s,
+ const Descriptor& _n1) {
+ error = _s;
+ descriptor = _n1;
+ });
+ ASSERT_EQ(error, Error::NONE);
+
+ gralloc.mAllocator->allocate(
+ descriptor, 1,
+ [&](Error _s, uint32_t _n1,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::hidl_handle>& _n2) {
+ ASSERT_EQ(Error::NONE, _s);
+ *nStride = _n1;
+ buffer->omxBuffer.nativeHandle = _n2[0];
+ buffer->omxBuffer.attr.anwBuffer.width = nFrameWidth;
+ buffer->omxBuffer.attr.anwBuffer.height = nFrameHeight;
+ buffer->omxBuffer.attr.anwBuffer.stride = _n1;
+ buffer->omxBuffer.attr.anwBuffer.format =
+ static_cast<PixelFormat>(descriptorInfo.format);
+ buffer->omxBuffer.attr.anwBuffer.usage =
+ static_cast<uint32_t>(descriptorInfo.usage);
+ buffer->omxBuffer.attr.anwBuffer.layerCount =
+ descriptorInfo.layerCount;
+ buffer->omxBuffer.attr.anwBuffer.id =
+ (static_cast<uint64_t>(getpid()) << 32) |
+ bufferIdCounter.fetch_add(1, std::memory_order_relaxed);
+ });
+ }, grallocVar);
}
// allocate buffers needed on a component port
diff --git a/media/omx/1.0/vts/functional/common/media_hidl_test_common.h b/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
index 1575ba2..ac077a3 100644
--- a/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
+++ b/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
@@ -22,6 +22,16 @@
#endif
#include <getopt.h>
+
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <android/hardware/graphics/allocator/3.0/IAllocator.h>
+#include <android/hardware/graphics/common/1.0/types.h>
+#include <android/hardware/graphics/common/1.1/types.h>
+#include <android/hardware/graphics/common/1.2/types.h>
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <android/hardware/graphics/mapper/2.0/types.h>
+#include <android/hardware/graphics/mapper/3.0/IMapper.h>
+#include <android/hardware/graphics/mapper/3.0/types.h>
#include <media/stagefright/foundation/ALooper.h>
#include <utils/Condition.h>
#include <utils/List.h>
@@ -288,6 +298,36 @@
/*
* common functions declarations
*/
+struct GrallocV2 {
+ using Format = android::hardware::graphics::common::V1_0::PixelFormat;
+ using Usage = android::hardware::hidl_bitfield<
+ android::hardware::graphics::common::V1_0::BufferUsage>;
+
+ using IAllocator = android::hardware::graphics::allocator::V2_0::IAllocator;
+
+ using IMapper = android::hardware::graphics::mapper::V2_0::IMapper;
+ using Error = android::hardware::graphics::mapper::V2_0::Error;
+ using Descriptor = android::hardware::graphics::mapper::V2_0::BufferDescriptor;
+ using YCbCrLayout = android::hardware::graphics::mapper::V2_0::YCbCrLayout;
+ using DescriptorInfo = IMapper::BufferDescriptorInfo;
+ using Rect = IMapper::Rect;
+};
+
+struct GrallocV3 {
+ using Format = android::hardware::graphics::common::V1_2::PixelFormat;
+ using Usage = android::hardware::hidl_bitfield<
+ android::hardware::graphics::common::V1_2::BufferUsage>;
+
+ using IAllocator = android::hardware::graphics::allocator::V3_0::IAllocator;
+
+ using IMapper = android::hardware::graphics::mapper::V3_0::IMapper;
+ using Error = android::hardware::graphics::mapper::V3_0::Error;
+ using Descriptor = android::hardware::graphics::mapper::V3_0::BufferDescriptor;
+ using YCbCrLayout = android::hardware::graphics::mapper::V3_0::YCbCrLayout;
+ using DescriptorInfo = IMapper::BufferDescriptorInfo;
+ using Rect = IMapper::Rect;
+};
+
Return<android::hardware::media::omx::V1_0::Status> setRole(
sp<IOmxNode> omxNode, const char* role);
@@ -368,7 +408,7 @@
public:
virtual void registerTestServices() override { registerTestService<IOmx>(); }
- ComponentTestEnvironment() : res("/sdcard/media/") {}
+ ComponentTestEnvironment() : res("/data/local/tmp/media/") {}
void setComponent(const char* _component) { component = _component; }
diff --git a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
index a740a80..2280cee 100644
--- a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
+++ b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
@@ -63,6 +63,7 @@
#include <media_video_hidl_test_common.h>
#include <system/window.h>
#include <fstream>
+#include <variant>
static ComponentTestEnvironment* gEnv = nullptr;
@@ -364,6 +365,61 @@
return Void();
};
+// Variant of mappers
+struct MapperV2 : public GrallocV2 {
+ sp<IMapper> mMapper;
+ MapperV2(sp<IMapper>&& mapper): mMapper{std::move(mapper)} {}
+ MapperV2() = default;
+ android::hardware::Return<void> lock(
+ void* buffer,
+ Usage usage,
+ const Rect& rect,
+ const android::hardware::hidl_handle& handle,
+ Error* error,
+ void** data) {
+ return mMapper->lock(buffer, usage, rect, handle,
+ [error, data](Error e, void* d) {
+ *error = e;
+ *data = d;
+ });
+ }
+};
+struct MapperV3 : public GrallocV3 {
+ sp<IMapper> mMapper;
+ MapperV3(sp<IMapper>&& mapper): mMapper{std::move(mapper)} {}
+ MapperV3() = default;
+ android::hardware::Return<void> lock(
+ void* buffer,
+ Usage usage,
+ const Rect& rect,
+ const android::hardware::hidl_handle& handle,
+ Error* error,
+ void** data) {
+ return mMapper->lock(buffer, usage, rect, handle,
+ [error, data](Error e, void* d, int32_t, int32_t) {
+ *error = e;
+ *data = d;
+ });
+ }
+};
+using MapperVar = std::variant<MapperV2, MapperV3>;
+// Initializes the MapperVar by trying services of different versions.
+bool initialize(MapperVar& mapperVar) {
+ sp<android::hardware::graphics::mapper::V3_0::IMapper> mapper3 =
+ android::hardware::graphics::mapper::V3_0::IMapper::getService();
+ if (mapper3) {
+ mapperVar.emplace<MapperV3>(std::move(mapper3));
+ return true;
+ }
+ sp<android::hardware::graphics::mapper::V2_0::IMapper> mapper2 =
+ android::hardware::graphics::mapper::V2_0::IMapper::getService();
+ if (mapper2) {
+ mapperVar.emplace<MapperV2>(std::move(mapper2));
+ return true;
+ }
+ return false;
+}
+
// request VOP refresh
void requestIDR(sp<IOmxNode> omxNode, OMX_U32 portIndex) {
android::hardware::media::omx::V1_0::Status status;
@@ -574,150 +630,166 @@
int colorFormatConversion(BufferInfo* buffer, void* buff, PixelFormat format,
std::ifstream& eleStream) {
- sp<android::hardware::graphics::mapper::V2_0::IMapper> mapper =
- android::hardware::graphics::mapper::V2_0::IMapper::getService();
- EXPECT_NE(mapper.get(), nullptr);
- if (mapper.get() == nullptr) return 1;
-
- android::hardware::hidl_handle fence;
- android::hardware::graphics::mapper::V2_0::IMapper::Rect rect;
- android::hardware::graphics::mapper::V2_0::YCbCrLayout ycbcrLayout;
- android::hardware::graphics::mapper::V2_0::Error error;
- rect.left = 0;
- rect.top = 0;
- rect.width = buffer->omxBuffer.attr.anwBuffer.width;
- rect.height = buffer->omxBuffer.attr.anwBuffer.height;
-
- if (format == PixelFormat::YV12 || format == PixelFormat::YCRCB_420_SP ||
- format == PixelFormat::YCBCR_420_888) {
- mapper->lockYCbCr(
- buff, buffer->omxBuffer.attr.anwBuffer.usage, rect, fence,
- [&](android::hardware::graphics::mapper::V2_0::Error _e,
- android::hardware::graphics::mapper::V2_0::YCbCrLayout _n1) {
- error = _e;
- ycbcrLayout = _n1;
- });
- EXPECT_EQ(error,
- android::hardware::graphics::mapper::V2_0::Error::NONE);
- if (error != android::hardware::graphics::mapper::V2_0::Error::NONE)
- return 1;
-
- int size = ((rect.width * rect.height * 3) >> 1);
- char* img = new char[size];
- if (img == nullptr) return 1;
- eleStream.read(img, size);
- if (eleStream.gcount() != size) {
- delete[] img;
- return 1;
- }
-
- char* imgTmp = img;
- char* ipBuffer = static_cast<char*>(ycbcrLayout.y);
- for (size_t y = rect.height; y > 0; --y) {
- memcpy(ipBuffer, imgTmp, rect.width);
- ipBuffer += ycbcrLayout.yStride;
- imgTmp += rect.width;
- }
-
- if (format == PixelFormat::YV12)
- EXPECT_EQ(ycbcrLayout.chromaStep, 1U);
- else if (format == PixelFormat::YCRCB_420_SP)
- EXPECT_EQ(ycbcrLayout.chromaStep, 2U);
-
- ipBuffer = static_cast<char*>(ycbcrLayout.cb);
- for (size_t y = rect.height >> 1; y > 0; --y) {
- for (int32_t x = 0; x < (rect.width >> 1); ++x) {
- ipBuffer[ycbcrLayout.chromaStep * x] = *imgTmp++;
- }
- ipBuffer += ycbcrLayout.cStride;
- }
- ipBuffer = static_cast<char*>(ycbcrLayout.cr);
- for (size_t y = rect.height >> 1; y > 0; --y) {
- for (int32_t x = 0; x < (rect.width >> 1); ++x) {
- ipBuffer[ycbcrLayout.chromaStep * x] = *imgTmp++;
- }
- ipBuffer += ycbcrLayout.cStride;
- }
-
- delete[] img;
-
- mapper->unlock(buff,
- [&](android::hardware::graphics::mapper::V2_0::Error _e,
- android::hardware::hidl_handle _n1) {
- error = _e;
- fence = _n1;
- });
- EXPECT_EQ(error,
- android::hardware::graphics::mapper::V2_0::Error::NONE);
- if (error != android::hardware::graphics::mapper::V2_0::Error::NONE)
- return 1;
- } else {
- void* data;
- mapper->lock(buff, buffer->omxBuffer.attr.anwBuffer.usage, rect, fence,
- [&](android::hardware::graphics::mapper::V2_0::Error _e,
- void* _n1) {
- error = _e;
- data = _n1;
- });
- EXPECT_EQ(error,
- android::hardware::graphics::mapper::V2_0::Error::NONE);
- if (error != android::hardware::graphics::mapper::V2_0::Error::NONE)
- return 1;
-
- if (format == PixelFormat::BGRA_8888) {
- char* ipBuffer = static_cast<char*>(data);
- for (size_t y = rect.height; y > 0; --y) {
- eleStream.read(ipBuffer, rect.width * 4);
- if (eleStream.gcount() != rect.width * 4) return 1;
- ipBuffer += buffer->omxBuffer.attr.anwBuffer.stride * 4;
- }
- } else {
- EXPECT_TRUE(false) << "un expected pixel format";
- return 1;
- }
-
- mapper->unlock(buff,
- [&](android::hardware::graphics::mapper::V2_0::Error _e,
- android::hardware::hidl_handle _n1) {
- error = _e;
- fence = _n1;
- });
- EXPECT_EQ(error,
- android::hardware::graphics::mapper::V2_0::Error::NONE);
- if (error != android::hardware::graphics::mapper::V2_0::Error::NONE)
- return 1;
+ MapperVar mapperVar;
+ if (!initialize(mapperVar)) {
+ EXPECT_TRUE(false) << "failed to obtain mapper service";
+ return 1;
}
- return 0;
+ return std::visit([buffer, buff, format, &eleStream](auto&& mapper) -> int {
+ using Gralloc = std::remove_reference_t<decltype(mapper)>;
+ using Error = typename Gralloc::Error;
+ using Rect = typename Gralloc::Rect;
+ using Usage = typename Gralloc::Usage;
+ using YCbCrLayout = typename Gralloc::YCbCrLayout;
+
+ android::hardware::hidl_handle fence;
+ Rect rect;
+ YCbCrLayout ycbcrLayout;
+ Error error;
+ rect.left = 0;
+ rect.top = 0;
+ rect.width = buffer->omxBuffer.attr.anwBuffer.width;
+ rect.height = buffer->omxBuffer.attr.anwBuffer.height;
+
+ if (format == PixelFormat::YV12 || format == PixelFormat::YCRCB_420_SP ||
+ format == PixelFormat::YCBCR_420_888) {
+ mapper.mMapper->lockYCbCr(
+ buff,
+ static_cast<Usage>(
+ buffer->omxBuffer.attr.anwBuffer.usage),
+ rect,
+ fence,
+ [&](Error _e,
+ const YCbCrLayout& _n1) {
+ error = _e;
+ ycbcrLayout = _n1;
+ });
+ EXPECT_EQ(error, Error::NONE);
+ if (error != Error::NONE)
+ return 1;
+
+ int size = ((rect.width * rect.height * 3) >> 1);
+ char* img = new char[size];
+ if (img == nullptr) return 1;
+ eleStream.read(img, size);
+ if (eleStream.gcount() != size) {
+ delete[] img;
+ return 1;
+ }
+
+ char* imgTmp = img;
+ char* ipBuffer = static_cast<char*>(ycbcrLayout.y);
+ for (size_t y = rect.height; y > 0; --y) {
+ memcpy(ipBuffer, imgTmp, rect.width);
+ ipBuffer += ycbcrLayout.yStride;
+ imgTmp += rect.width;
+ }
+
+ if (format == PixelFormat::YV12)
+ EXPECT_EQ(ycbcrLayout.chromaStep, 1U);
+ else if (format == PixelFormat::YCRCB_420_SP)
+ EXPECT_EQ(ycbcrLayout.chromaStep, 2U);
+
+ ipBuffer = static_cast<char*>(ycbcrLayout.cb);
+ for (size_t y = rect.height >> 1; y > 0; --y) {
+ for (int32_t x = 0; x < (rect.width >> 1); ++x) {
+ ipBuffer[ycbcrLayout.chromaStep * x] = *imgTmp++;
+ }
+ ipBuffer += ycbcrLayout.cStride;
+ }
+ ipBuffer = static_cast<char*>(ycbcrLayout.cr);
+ for (size_t y = rect.height >> 1; y > 0; --y) {
+ for (int32_t x = 0; x < (rect.width >> 1); ++x) {
+ ipBuffer[ycbcrLayout.chromaStep * x] = *imgTmp++;
+ }
+ ipBuffer += ycbcrLayout.cStride;
+ }
+
+ delete[] img;
+
+ mapper.mMapper->unlock(buff,
+ [&](Error _e,
+ const android::hardware::hidl_handle& _n1) {
+ error = _e;
+ fence = _n1;
+ });
+ EXPECT_EQ(error, Error::NONE);
+ if (error != Error::NONE)
+ return 1;
+ } else {
+ void* data;
+ mapper.lock(
+ buff,
+ buffer->omxBuffer.attr.anwBuffer.usage,
+ rect,
+ fence,
+ &error,
+ &data);
+ EXPECT_EQ(error, Error::NONE);
+ if (error != Error::NONE)
+ return 1;
+
+ if (format == PixelFormat::BGRA_8888) {
+ char* ipBuffer = static_cast<char*>(data);
+ for (size_t y = rect.height; y > 0; --y) {
+ eleStream.read(ipBuffer, rect.width * 4);
+ if (eleStream.gcount() != rect.width * 4) return 1;
+ ipBuffer += buffer->omxBuffer.attr.anwBuffer.stride * 4;
+ }
+ } else {
+ EXPECT_TRUE(false) << "un expected pixel format";
+ return 1;
+ }
+
+ mapper.mMapper->unlock(
+ buff,
+ [&](Error _e, const android::hardware::hidl_handle& _n1) {
+ error = _e;
+ fence = _n1;
+ });
+ EXPECT_EQ(error, Error::NONE);
+ if (error != Error::NONE)
+ return 1;
+ }
+
+ return 0;
+ }, mapperVar);
}
int fillGraphicBuffer(BufferInfo* buffer, PixelFormat format,
std::ifstream& eleStream) {
- sp<android::hardware::graphics::mapper::V2_0::IMapper> mapper =
- android::hardware::graphics::mapper::V2_0::IMapper::getService();
- EXPECT_NE(mapper.get(), nullptr);
- if (mapper.get() == nullptr) return 1;
-
- void* buff = nullptr;
- android::hardware::graphics::mapper::V2_0::Error error;
- mapper->importBuffer(
- buffer->omxBuffer.nativeHandle,
- [&](android::hardware::graphics::mapper::V2_0::Error _e, void* _n1) {
- error = _e;
- buff = _n1;
- });
- EXPECT_EQ(error, android::hardware::graphics::mapper::V2_0::Error::NONE);
- if (error != android::hardware::graphics::mapper::V2_0::Error::NONE)
+ MapperVar mapperVar;
+ if (!initialize(mapperVar)) {
+ EXPECT_TRUE(false) << "failed to obtain mapper service";
return 1;
+ }
- if (colorFormatConversion(buffer, buff, format, eleStream)) return 1;
+ return std::visit([buffer, format, &eleStream](auto&& mapper) -> int {
+ using Gralloc = std::remove_reference_t<decltype(mapper)>;
+ using Error = typename Gralloc::Error;
- error = mapper->freeBuffer(buff);
- EXPECT_EQ(error, android::hardware::graphics::mapper::V2_0::Error::NONE);
- if (error != android::hardware::graphics::mapper::V2_0::Error::NONE)
- return 1;
+ void* buff = nullptr;
+ Error error;
+ mapper.mMapper->importBuffer(
+ buffer->omxBuffer.nativeHandle,
+ [&](Error _e, void* _n1) {
+ error = _e;
+ buff = _n1;
+ });
+ EXPECT_EQ(error, Error::NONE);
+ if (error != Error::NONE)
+ return 1;
- return 0;
+ if (colorFormatConversion(buffer, buff, format, eleStream)) return 1;
+
+ error = mapper.mMapper->freeBuffer(buff);
+ EXPECT_EQ(error, Error::NONE);
+ if (error != Error::NONE)
+ return 1;
+
+ return 0;
+ }, mapperVar);
}
int dispatchGraphicBuffer(sp<IOmxNode> omxNode,
diff --git a/sensors/2.0/multihal/Android.bp b/sensors/2.0/multihal/Android.bp
index c13eaf2..811c455 100644
--- a/sensors/2.0/multihal/Android.bp
+++ b/sensors/2.0/multihal/Android.bp
@@ -43,10 +43,10 @@
srcs: [
"service.cpp",
"HalProxy.cpp",
- "ScopedWakelock.cpp",
],
init_rc: ["android.hardware.sensors@2.0-service-multihal.rc"],
vintf_fragments: ["android.hardware.sensors@2.0-multihal.xml"],
+ shared_libs: ["android.hardware.sensors@2.0-ScopedWakelock"]
}
cc_library_headers {
@@ -55,19 +55,40 @@
export_include_dirs: ["include"],
}
+cc_library_shared {
+ name: "android.hardware.sensors@2.0-ScopedWakelock",
+ defaults: [
+ "hidl_defaults",
+ "android.hardware.sensors@2.0-multihal-defaults",
+ ],
+ srcs: [
+ "ScopedWakelock.cpp",
+ ],
+ vendor_available: true,
+ export_header_lib_headers: [
+ "android.hardware.sensors@2.0-multihal.header"
+ ]
+}
+
// The below targets should only be used for testing.
cc_test_library {
name: "android.hardware.sensors@2.0-HalProxy",
- defaults: ["android.hardware.sensors@2.0-multihal-defaults"],
+ defaults: [
+ "hidl_defaults",
+ "android.hardware.sensors@2.0-multihal-defaults",
+ ],
vendor_available: true,
srcs: [
"HalProxy.cpp",
- "ScopedWakelock.cpp",
],
export_header_lib_headers: [
"android.hardware.sensors@2.0-multihal.header",
],
+ export_shared_lib_headers: [
+ "android.hardware.sensors@2.0-ScopedWakelock",
+ ],
shared_libs: [
"libutils",
+ "android.hardware.sensors@2.0-ScopedWakelock",
],
}
diff --git a/sensors/2.0/multihal/tests/Android.bp b/sensors/2.0/multihal/tests/Android.bp
index e7f9499..1637312 100644
--- a/sensors/2.0/multihal/tests/Android.bp
+++ b/sensors/2.0/multihal/tests/Android.bp
@@ -25,6 +25,7 @@
shared_libs: [
"android.hardware.sensors@1.0",
"android.hardware.sensors@2.0",
+ "android.hardware.sensors@2.0-ScopedWakelock",
"libcutils",
"libfmq",
"libhardware",
@@ -83,6 +84,7 @@
shared_libs: [
"android.hardware.sensors@1.0",
"android.hardware.sensors@2.0",
+ "android.hardware.sensors@2.0-ScopedWakelock",
"libbase",
"libcutils",
"libfmq",
diff --git a/tests/extension/vibrator/aidl/client/test-cpp-client.cpp b/tests/extension/vibrator/aidl/client/test-cpp-client.cpp
index f6f5537..015a345 100644
--- a/tests/extension/vibrator/aidl/client/test-cpp-client.cpp
+++ b/tests/extension/vibrator/aidl/client/test-cpp-client.cpp
@@ -20,9 +20,9 @@
#include <binder/IServiceManager.h>
#include <gtest/gtest.h>
+using android::checked_interface_cast;
using android::IBinder;
using android::IInterface;
-using android::interface_cast;
using android::OK;
using android::sp;
using android::waitForVintfService;
@@ -44,7 +44,7 @@
// getting the extension
sp<IBinder> ext;
ASSERT_EQ(OK, IInterface::asBinder(vib)->getExtension(&ext));
- sp<ICustomVibrator> cvib = interface_cast<ICustomVibrator>(ext);
+ sp<ICustomVibrator> cvib = checked_interface_cast<ICustomVibrator>(ext);
ASSERT_NE(nullptr, cvib.get());
// calling extension method
diff --git a/tests/memory/2.0/Android.bp b/tests/memory/2.0/Android.bp
new file mode 100644
index 0000000..5166652
--- /dev/null
+++ b/tests/memory/2.0/Android.bp
@@ -0,0 +1,12 @@
+hidl_interface {
+ name: "android.hardware.tests.memory@2.0",
+ root: "android.hardware",
+ srcs: [
+ "IMemoryInterface.hal",
+ "types.hal",
+ ],
+ interfaces: [
+ "android.hidl.base@1.0",
+ ],
+ gen_java: true,
+}
diff --git a/tests/memory/2.0/IMemoryInterface.hal b/tests/memory/2.0/IMemoryInterface.hal
new file mode 100644
index 0000000..2c824bf
--- /dev/null
+++ b/tests/memory/2.0/IMemoryInterface.hal
@@ -0,0 +1,12 @@
+package android.hardware.tests.memory@2.0;
+
+interface IMemoryInterface {
+ // Flips all the bits in the given memory buffer.
+ bitwiseNot(memory mem);
+ // Returns a read-only buffer of size 8, containing the bytes 0..7.
+ getTestMem() generates(memory mem);
+ // Given two memory regions of the same size, returns two memory fields of
+ // equal size, the first contains the byte-wise sum and the other the byte-
+ // wise difference.
+ getSumDiff(TwoMemory in) generates(TwoMemory out);
+};
diff --git a/tests/memory/2.0/types.hal b/tests/memory/2.0/types.hal
new file mode 100644
index 0000000..9ec357b
--- /dev/null
+++ b/tests/memory/2.0/types.hal
@@ -0,0 +1,6 @@
+package android.hardware.tests.memory@2.0;
+
+struct TwoMemory {
+ memory mem1;
+ memory mem2;
+};
diff --git a/vibrator/aidl/Android.bp b/vibrator/aidl/Android.bp
index cd5439f..e26041a 100644
--- a/vibrator/aidl/Android.bp
+++ b/vibrator/aidl/Android.bp
@@ -5,5 +5,11 @@
"android/hardware/vibrator/*.aidl",
],
stability: "vintf",
+ backend: {
+ ndk: {
+ vndk: {
+ enabled: true,
+ },
+ },
+ },
}
-