Merge "audio HAL V7: Update track metadata"
diff --git a/audio/7.0/IStreamOutEventCallback.hal b/audio/7.0/IStreamOutEventCallback.hal
index 52e65d3..4de767f 100644
--- a/audio/7.0/IStreamOutEventCallback.hal
+++ b/audio/7.0/IStreamOutEventCallback.hal
@@ -42,7 +42,7 @@
* is TEST(metadata_tests, compatibility_R) [3]. The test for R compatibility for JNI
* marshalling is android.media.cts.AudioMetadataTest#testCompatibilityR [4].
*
- * R (audio HAL 7.0) defined keys are as follows [2]:
+ * R (audio HAL 6.0) defined keys are as follows [2]:
* "bitrate", int32
* "channel-mask", int32
* "mime", string
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 a7d7ed1..c53ae8d 100644
--- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp
@@ -143,20 +143,23 @@
#if MAJOR_VERSION <= 6
using AD = AudioDevice;
for (auto deviceType : {AD::OUT_HDMI, AD::OUT_WIRED_HEADPHONE, AD::IN_USB_HEADSET}) {
+ SCOPED_TRACE("device=" + ::testing::PrintToString(deviceType));
#elif MAJOR_VERSION >= 7
using AD = xsd::AudioDevice;
- for (auto deviceType :
- {toString(AD::AUDIO_DEVICE_OUT_HDMI), toString(AD::AUDIO_DEVICE_OUT_WIRED_HEADPHONE),
- toString(AD::AUDIO_DEVICE_IN_USB_HEADSET)}) {
+ for (auto deviceType : {AD::AUDIO_DEVICE_OUT_HDMI, AD::AUDIO_DEVICE_OUT_WIRED_HEADPHONE,
+ AD::AUDIO_DEVICE_IN_USB_HEADSET}) {
+ SCOPED_TRACE("device=" + toString(deviceType));
#endif
- SCOPED_TRACE("device=" + ::testing::PrintToString(deviceType));
for (bool state : {true, false}) {
SCOPED_TRACE("state=" + ::testing::PrintToString(state));
DeviceAddress address = {};
#if MAJOR_VERSION <= 6
address.device = deviceType;
#elif MAJOR_VERSION >= 7
- address.deviceType = deviceType;
+ address.deviceType = toString(deviceType);
+ if (deviceType == AD::AUDIO_DEVICE_IN_USB_HEADSET) {
+ address.address.alsa({0, 0});
+ }
#endif
auto ret = getDevice()->setConnectedState(address, state);
ASSERT_TRUE(ret.isOk());
diff --git a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
index 941c4bd..6bb7995 100644
--- a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
@@ -44,22 +44,26 @@
for (const auto& device : getDeviceParameters()) {
auto module =
getCachedPolicyConfig().getModuleFromName(std::get<PARAM_DEVICE_NAME>(device));
+ if (!module || !module->getFirstMixPorts()) break;
for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
if (mixPort.getRole() != xsd::Role::source) continue; // not an output profile
- auto xsdFlags = mixPort.getFlags();
- const bool isOffload =
- std::find(xsdFlags.begin(), xsdFlags.end(),
- xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) !=
- xsdFlags.end();
std::vector<AudioInOutFlag> flags;
- if (!isOffload) {
- for (auto flag : xsdFlags) {
- if (flag != xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_PRIMARY) {
- flags.push_back(toString(flag));
+ bool isOffload = false;
+ if (mixPort.hasFlags()) {
+ auto xsdFlags = mixPort.getFlags();
+ isOffload =
+ std::find(xsdFlags.begin(), xsdFlags.end(),
+ xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) !=
+ xsdFlags.end();
+ if (!isOffload) {
+ for (auto flag : xsdFlags) {
+ if (flag != xsd::AudioInOutFlag::AUDIO_OUTPUT_FLAG_PRIMARY) {
+ flags.push_back(toString(flag));
+ }
}
+ } else {
+ flags = offloadFlags;
}
- } else {
- flags = offloadFlags;
}
for (const auto& profile : mixPort.getProfile()) {
auto configs =
@@ -94,11 +98,15 @@
for (const auto& device : getDeviceParameters()) {
auto module =
getCachedPolicyConfig().getModuleFromName(std::get<PARAM_DEVICE_NAME>(device));
+ if (!module || !module->getFirstMixPorts()) break;
for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
if (mixPort.getRole() != xsd::Role::sink) continue; // not an input profile
std::vector<AudioInOutFlag> flags;
- std::transform(mixPort.getFlags().begin(), mixPort.getFlags().end(), flags.begin(),
- [](auto flag) { return toString(flag); });
+ if (mixPort.hasFlags()) {
+ std::transform(mixPort.getFlags().begin(), mixPort.getFlags().end(),
+ std::back_inserter(flags),
+ [](auto flag) { return toString(flag); });
+ }
for (const auto& profile : mixPort.getProfile()) {
auto configs =
combineAudioConfig(profile.getChannelMasks(),
diff --git a/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h b/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h
index d790b34..7d88642 100644
--- a/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h
+++ b/audio/core/all-versions/vts/functional/7.0/PolicyConfig.h
@@ -33,10 +33,14 @@
if (mConfig) {
mStatus = OK;
mPrimaryModule = getModuleFromName(DeviceManager::kPrimaryDevice);
- for (const auto& module : mConfig->getFirstModules()->get_module()) {
- auto attachedDevices = module.getFirstAttachedDevices()->getItem();
- if (!attachedDevices.empty()) {
- mModulesWithDevicesNames.insert(module.getName());
+ if (mConfig->getFirstModules()) {
+ for (const auto& module : mConfig->getFirstModules()->get_module()) {
+ if (module.getFirstAttachedDevices()) {
+ auto attachedDevices = module.getFirstAttachedDevices()->getItem();
+ if (!attachedDevices.empty()) {
+ mModulesWithDevicesNames.insert(module.getName());
+ }
+ }
}
}
}
@@ -52,7 +56,7 @@
}
const std::string& getFilePath() const { return mFilePath; }
const xsd::Module* getModuleFromName(const std::string& name) const {
- if (mConfig) {
+ if (mConfig && mConfig->getFirstModules()) {
for (const auto& module : mConfig->getFirstModules()->get_module()) {
if (module.getName() == name) return &module;
}
@@ -65,8 +69,10 @@
}
bool haveInputProfilesInModule(const std::string& name) const {
auto module = getModuleFromName(name);
- for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
- if (mixPort.getRole() == xsd::Role::sink) return true;
+ if (module && module->getFirstMixPorts()) {
+ for (const auto& mixPort : module->getFirstMixPorts()->getMixPort()) {
+ if (mixPort.getRole() == xsd::Role::sink) return true;
+ }
}
return false;
}
diff --git a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
index 6333023..a16a0fb 100644
--- a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
+++ b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
@@ -156,6 +156,21 @@
return *policyConfig;
}
+TEST(CheckConfig, audioPolicyConfigurationValidation) {
+ const auto factories = ::android::hardware::getAllHalInstanceNames(IDevicesFactory::descriptor);
+ if (factories.size() == 0) {
+ GTEST_SKIP() << "Skipping audioPolicyConfigurationValidation because no factory instances "
+ "are found.";
+ }
+ RecordProperty("description",
+ "Verify that the audio policy configuration file "
+ "is valid according to the schema");
+
+ const char* xsd = "/data/local/tmp/audio_policy_configuration_" STRINGIFY(CPP_VERSION) ".xsd";
+ EXPECT_ONE_VALID_XML_MULTIPLE_LOCATIONS(kConfigFileName,
+ android::audio_get_configuration_paths(), xsd);
+}
+
//////////////////////////////////////////////////////////////////////////////
//////////////////// Test parameter types and definitions ////////////////////
//////////////////////////////////////////////////////////////////////////////
@@ -231,21 +246,6 @@
}
};
-TEST(CheckConfig, audioPolicyConfigurationValidation) {
- auto deviceParameters = getDeviceParametersForFactoryTests();
- if (deviceParameters.size() == 0) {
- GTEST_SKIP() << "Skipping audioPolicyConfigurationValidation because no device parameter "
- "is found.";
- }
- RecordProperty("description",
- "Verify that the audio policy configuration file "
- "is valid according to the schema");
-
- const char* xsd = "/data/local/tmp/audio_policy_configuration_" STRINGIFY(CPP_VERSION) ".xsd";
- EXPECT_ONE_VALID_XML_MULTIPLE_LOCATIONS(kConfigFileName,
- android::audio_get_configuration_paths(), xsd);
-}
-
class AudioPolicyConfigTest : public AudioHidlTestWithDeviceParameter {
public:
void SetUp() override {
diff --git a/automotive/can/1.0/default/libnl++/Android.bp b/automotive/can/1.0/default/libnl++/Android.bp
index 90e1002..a69e302 100644
--- a/automotive/can/1.0/default/libnl++/Android.bp
+++ b/automotive/can/1.0/default/libnl++/Android.bp
@@ -22,6 +22,7 @@
"protocols/common/Empty.cpp",
"protocols/common/Error.cpp",
"protocols/generic/Ctrl.cpp",
+ "protocols/generic/FamilyTracker.cpp",
"protocols/generic/Generic.cpp",
"protocols/generic/GenericMessageBase.cpp",
"protocols/generic/Unknown.cpp",
@@ -34,6 +35,7 @@
"protocols/all.cpp",
"Attributes.cpp",
"MessageFactory.cpp",
+ "MessageMutator.cpp",
"Socket.cpp",
"common.cpp",
"printer.cpp",
diff --git a/automotive/can/1.0/default/libnl++/MessageMutator.cpp b/automotive/can/1.0/default/libnl++/MessageMutator.cpp
new file mode 100644
index 0000000..00b48a6
--- /dev/null
+++ b/automotive/can/1.0/default/libnl++/MessageMutator.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libnl++/MessageMutator.h>
+
+namespace android::nl {
+
+MessageMutator::MessageMutator(nlmsghdr* buffer, size_t totalLen)
+ : mConstBuffer(buffer, totalLen), mMutableBuffer(buffer) {
+ CHECK(totalLen >= sizeof(nlmsghdr));
+}
+
+nlmsghdr* MessageMutator::operator->() const {
+ return mMutableBuffer;
+}
+
+MessageMutator::operator Buffer<nlmsghdr>() const {
+ return mConstBuffer;
+}
+
+uint64_t MessageMutator::read(Buffer<nlattr> attr) const {
+ return attr.data<uint64_t>().copyFirst();
+}
+
+void MessageMutator::write(Buffer<nlattr> attr, uint64_t val) const {
+ const auto attrData = attr.data<uint64_t>();
+ const auto offset = mConstBuffer.getOffset(attrData);
+ CHECK(offset.has_value()) << "Trying to write attribute that's not a member of this message";
+
+ const auto writeableBuffer = reinterpret_cast<uint8_t*>(mMutableBuffer) + *offset;
+ const auto attrSize = attrData.getRaw().len();
+
+ if (attrSize > sizeof(val)) memset(writeableBuffer, 0, attrSize);
+ memcpy(writeableBuffer, &val, std::min(sizeof(val), attrSize));
+}
+
+} // namespace android::nl
diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/Attributes.h b/automotive/can/1.0/default/libnl++/include/libnl++/Attributes.h
index f16d997..a438a69 100644
--- a/automotive/can/1.0/default/libnl++/include/libnl++/Attributes.h
+++ b/automotive/can/1.0/default/libnl++/include/libnl++/Attributes.h
@@ -93,14 +93,29 @@
*/
template <typename T>
T get(nlattrtype_t attrtype) const {
- const auto& ind = index();
- const auto it = ind.find(attrtype);
- if (it == ind.end()) {
+ const auto buffer = getBuffer(attrtype);
+ if (!buffer.has_value()) {
LOG(WARNING) << "Netlink attribute is missing: " << attrtype;
return T{};
}
- return parse<T>(it->second);
+ return parse<T>(*buffer);
+ }
+
+ /**
+ * Fetches underlying buffer of a given attribute.
+ *
+ * This is a low-level access method unlikely to be useful in most cases. Please consider
+ * using #get instead.
+ *
+ * \param attrtype Attribute to fetch
+ * \return Attribute buffer.
+ */
+ std::optional<Buffer<nlattr>> getBuffer(nlattrtype_t attrtype) const {
+ const auto& ind = index();
+ const auto it = ind.find(attrtype);
+ if (it == ind.end()) return std::nullopt;
+ return it->second;
}
/**
diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/Buffer.h b/automotive/can/1.0/default/libnl++/include/libnl++/Buffer.h
index bf83fbc..d759a0a 100644
--- a/automotive/can/1.0/default/libnl++/include/libnl++/Buffer.h
+++ b/automotive/can/1.0/default/libnl++/include/libnl++/Buffer.h
@@ -91,6 +91,18 @@
return {impl::data<const T, const D>(mData, offset), dataEnd()};
}
+ template <typename B>
+ std::optional<uintptr_t> getOffset(Buffer<B> inner) const {
+ const auto selfStart = uintptr_t(mData);
+ const auto selfEnd = uintptr_t(mBufferEnd);
+ const auto innerStart = uintptr_t(inner.mData);
+ const auto innerEnd = uintptr_t(inner.mBufferEnd);
+
+ if (innerStart < selfStart || innerEnd > selfEnd) return std::nullopt;
+
+ return innerStart - selfStart;
+ }
+
class iterator {
public:
iterator() : mCurrent(nullptr, size_t(0)) {
diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/MessageMutator.h b/automotive/can/1.0/default/libnl++/include/libnl++/MessageMutator.h
new file mode 100644
index 0000000..7d495e9
--- /dev/null
+++ b/automotive/can/1.0/default/libnl++/include/libnl++/MessageMutator.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <libnl++/Message.h>
+
+namespace android::nl {
+
+/**
+ * In-place message mutator.
+ *
+ * Useful for making small changes (such as adjusting const-sized attributes or struct fields)
+ * efficiently and in-place. However, if you need to rebuild the message (e.g. to modify variable
+ * sized attributes or add/remove them), you need to use MessageFactory instead.
+ */
+class MessageMutator {
+ public:
+ /**
+ * Construct message mutator object from editable buffer.
+ */
+ MessageMutator(nlmsghdr* buffer, size_t totalLen);
+
+ nlmsghdr* operator->() const;
+ operator Buffer<nlmsghdr>() const;
+
+ /**
+ * Read current attribute value.
+ *
+ * \param Read-only attribute buffer.
+ * \returns Attribute value.
+ */
+ uint64_t read(Buffer<nlattr> attr) const;
+
+ /**
+ * Write new attribute value.
+ *
+ * \param Read-only attribute buffer.
+ * \param val New value to set.
+ */
+ void write(Buffer<nlattr> attr, uint64_t val) const;
+
+ private:
+ const Buffer<nlmsghdr> mConstBuffer;
+ nlmsghdr* mMutableBuffer;
+};
+
+} // namespace android::nl
diff --git a/automotive/can/1.0/default/libnl++/include/libnl++/generic/FamilyTracker.h b/automotive/can/1.0/default/libnl++/include/libnl++/generic/FamilyTracker.h
new file mode 100644
index 0000000..2530035
--- /dev/null
+++ b/automotive/can/1.0/default/libnl++/include/libnl++/generic/FamilyTracker.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <libnl++/Buffer.h>
+#include <libnl++/Message.h>
+
+#include <linux/genetlink.h>
+
+#include <optional>
+
+namespace android::nl::generic {
+
+/**
+ * Tracker of Netlink family ID registrations.
+ */
+class FamilyTracker {
+ public:
+ /**
+ * Try parsing NL80211 message.
+ *
+ * Proper parsing of NL80211 nessages requires prior parsing of control message for Generic
+ * Netlink protocol.
+ *
+ * \param msg Message to parse
+ * \returns Parsed NL80211 message or std::nullopt if it wasn't one
+ */
+ std::optional<Message<genlmsghdr>> parseNl80211(Buffer<nlmsghdr> msg);
+
+ private:
+ /* For efficiency, we use a single hardcoded family ID. However, if we supported multiple family
+ * types, this should probably be a map.
+ */
+ std::optional<uint16_t> mNl80211FamilyId;
+
+ /**
+ * Track Generic protocol messages.
+ *
+ * This method is looking for family registration messages.
+ *
+ * \param msg Message to track
+ * \returns True, if the message was a control message (regardless of carrying
+ * family info or not)
+ */
+ bool track(const Buffer<nlmsghdr>& msg);
+};
+
+} // namespace android::nl::generic
diff --git a/automotive/can/1.0/default/libnl++/protocols/generic/FamilyTracker.cpp b/automotive/can/1.0/default/libnl++/protocols/generic/FamilyTracker.cpp
new file mode 100644
index 0000000..900560e
--- /dev/null
+++ b/automotive/can/1.0/default/libnl++/protocols/generic/FamilyTracker.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libnl++/generic/FamilyTracker.h>
+
+#include <android-base/logging.h>
+
+namespace android::nl::generic {
+
+bool FamilyTracker::track(const Buffer<nlmsghdr>& buffer) {
+ const auto msgMaybe = nl::Message<genlmsghdr>::parse(buffer, {GENL_ID_CTRL});
+ if (!msgMaybe.has_value()) return false;
+
+ const auto msg = *msgMaybe;
+ if (msg->cmd != CTRL_CMD_NEWFAMILY) return true;
+
+ const auto familyName = msg.attributes.get<std::string>(CTRL_ATTR_FAMILY_NAME);
+ const auto familyId = msg.attributes.get<uint16_t>(CTRL_ATTR_FAMILY_ID);
+
+ if (familyId < GENL_START_ALLOC) {
+ LOG(WARNING) << "Invalid family ID: " << familyId;
+ return true;
+ }
+
+ if (familyName == "nl80211") mNl80211FamilyId = familyId;
+
+ return true;
+}
+
+std::optional<Message<genlmsghdr>> FamilyTracker::parseNl80211(Buffer<nlmsghdr> msg) {
+ if (track(msg)) return std::nullopt;
+ if (!mNl80211FamilyId.has_value()) return std::nullopt;
+
+ return nl::Message<genlmsghdr>::parse(msg, {*mNl80211FamilyId});
+}
+
+} // namespace android::nl::generic
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 931fee4..0488b57 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -2773,7 +2773,7 @@
*
* int32[0]: 42 // request id
* int32[1]: 11 // Android id of the created user
- * int32[2]: 3 // Android flags (ephemeral guest) of the created user
+ * int32[2]: 6 // Android flags (ephemeral guest) of the created user
* int32[3]: 10 // current user
* int32[4]: 0 // current user flags (none)
* int32[5]: 3 // number of users
@@ -2782,7 +2782,7 @@
* int32[8]: 10 // 2nd user (user 10)
* int32[9]: 0 // 2nd user flags (none)
* int32[19]: 11 // 3rd user (user 11)
- * int32[11]: 3 // 3rd user flags (ephemeral guest)
+ * int32[11]: 6 // 3rd user flags (ephemeral guest)
* string: "ElGuesto" // name of the new user
*
* Then if the request succeeded, the HAL would return:
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index b16ae40..e12d920 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -354,6 +354,13 @@
<instance>default</instance>
</interface>
</hal>
+ <hal format="aidl" optional="true">
+ <name>android.hardware.memtrack</name>
+ <interface>
+ <name>IMemtrack</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
<hal format="hidl" optional="true">
<name>android.hardware.memtrack</name>
<version>1.0</version>
diff --git a/gnss/common/utils/default/Utils.cpp b/gnss/common/utils/default/Utils.cpp
index e383d51..21282f4 100644
--- a/gnss/common/utils/default/Utils.cpp
+++ b/gnss/common/utils/default/Utils.cpp
@@ -228,7 +228,8 @@
.verticalAccuracyMeters = kMockVerticalAccuracyMeters,
.speedAccuracyMetersPerSecond = kMockSpeedAccuracyMetersPerSecond,
.bearingAccuracyDegrees = kMockBearingAccuracyDegrees,
- .timestamp = kMockTimestamp};
+ .timestamp =
+ static_cast<int64_t>(kMockTimestamp + ::android::elapsedRealtimeNano() / 1e6)};
return location;
}
diff --git a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
index d8312a2..25c990b 100644
--- a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
+++ b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
@@ -19,6 +19,8 @@
#include <algorithm>
#include <regex>
#include <thread>
+#include <unordered_map>
+#include <utility>
#include <android-base/logging.h>
#include <android-base/properties.h>
@@ -152,9 +154,9 @@
void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
- const native_handle_t* allocate() {
+ const native_handle_t* allocate(int32_t width, int32_t height) {
return mGralloc->allocate(
- /*width*/ 64, /*height*/ 64, /*layerCount*/ 1,
+ width, height, /*layerCount*/ 1,
static_cast<common::V1_1::PixelFormat>(PixelFormat::RGBA_8888),
static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN));
}
@@ -285,6 +287,59 @@
}
}
+TEST_P(GraphicsComposerHidlTest, GetDisplayAttribute_2_4_ConfigsInAGroupDifferOnlyByVsyncPeriod) {
+ struct Resolution {
+ int32_t width, height;
+ };
+ struct Dpi {
+ int32_t x, y;
+ };
+ for (const auto& display : mDisplays) {
+ std::vector<Config> configs = mComposerClient->getDisplayConfigs(display.get());
+ std::unordered_map<int32_t, Resolution> configGroupToResolutionMap;
+ std::unordered_map<int32_t, Dpi> configGroupToDpiMap;
+ for (auto config : configs) {
+ const auto configGroup = mComposerClient->getDisplayAttribute_2_4(
+ display.get(), config, IComposerClient::Attribute::CONFIG_GROUP);
+ const auto width = mComposerClient->getDisplayAttribute_2_4(
+ display.get(), config, IComposerClient::Attribute::WIDTH);
+ const auto height = mComposerClient->getDisplayAttribute_2_4(
+ display.get(), config, IComposerClient::Attribute::HEIGHT);
+ if (configGroupToResolutionMap.find(configGroup) == configGroupToResolutionMap.end()) {
+ configGroupToResolutionMap[configGroup] = {width, height};
+ }
+ EXPECT_EQ(configGroupToResolutionMap[configGroup].width, width);
+ EXPECT_EQ(configGroupToResolutionMap[configGroup].height, height);
+
+ int32_t dpiX = -1;
+ mComposerClient->getRaw()->getDisplayAttribute_2_4(
+ display.get(), config, IComposerClient::Attribute::DPI_X,
+ [&](const auto& tmpError, const auto& value) {
+ if (tmpError == Error::NONE) {
+ dpiX = value;
+ }
+ });
+ int32_t dpiY = -1;
+ mComposerClient->getRaw()->getDisplayAttribute_2_4(
+ display.get(), config, IComposerClient::Attribute::DPI_Y,
+ [&](const auto& tmpError, const auto& value) {
+ if (tmpError == Error::NONE) {
+ dpiY = value;
+ }
+ });
+ if (dpiX == -1 && dpiY == -1) {
+ continue;
+ }
+
+ if (configGroupToDpiMap.find(configGroup) == configGroupToDpiMap.end()) {
+ configGroupToDpiMap[configGroup] = {dpiX, dpiY};
+ }
+ EXPECT_EQ(configGroupToDpiMap[configGroup].x, dpiX);
+ EXPECT_EQ(configGroupToDpiMap[configGroup].y, dpiY);
+ }
+ }
+}
+
TEST_P(GraphicsComposerHidlTest, getDisplayVsyncPeriod_BadDisplay) {
VsyncPeriodNanos vsyncPeriodNanos;
EXPECT_EQ(Error::BAD_DISPLAY,
@@ -407,7 +462,10 @@
mComposerClient->setPowerMode(display.get(), V2_1::IComposerClient::PowerMode::ON);
mComposerClient->setColorMode_2_3(display.get(), ColorMode::NATIVE, RenderIntent::COLORIMETRIC);
- auto handle = allocate();
+ IComposerClient::FRect displayCrop = display.getCrop();
+ int32_t displayWidth = static_cast<int32_t>(std::ceilf(displayCrop.right - displayCrop.left));
+ int32_t displayHeight = static_cast<int32_t>(std::ceilf(displayCrop.bottom - displayCrop.top));
+ auto handle = allocate(displayWidth, displayHeight);
ASSERT_NE(nullptr, handle);
Layer layer;
@@ -435,7 +493,7 @@
ASSERT_EQ(0, mReader->mErrors.size());
mWriter->selectLayer(layer);
- auto handle2 = allocate();
+ auto handle2 = allocate(displayWidth, displayHeight);
ASSERT_NE(nullptr, handle2);
mWriter->setLayerBuffer(0, handle2, -1);
@@ -703,4 +761,4 @@
}
return RUN_ALL_TESTS();
-}
\ No newline at end of file
+}
diff --git a/identity/support/src/IdentityCredentialSupport.cpp b/identity/support/src/IdentityCredentialSupport.cpp
index 77b795b..093120d 100644
--- a/identity/support/src/IdentityCredentialSupport.cpp
+++ b/identity/support/src/IdentityCredentialSupport.cpp
@@ -935,18 +935,19 @@
optional<vector<vector<uint8_t>>> createAttestation(
const EVP_PKEY* key, const vector<uint8_t>& applicationId, const vector<uint8_t>& challenge,
uint64_t activeTimeMilliSeconds, uint64_t expireTimeMilliSeconds, bool isTestCredential) {
- const keymaster_cert_chain_t* attestation_chain =
- ::keymaster::getAttestationChain(KM_ALGORITHM_EC, nullptr);
- if (attestation_chain == nullptr) {
- LOG(ERROR) << "Error getting attestation chain";
+ keymaster_error_t error;
+ ::keymaster::CertificateChain attestation_chain =
+ ::keymaster::getAttestationChain(KM_ALGORITHM_EC, &error);
+ if (KM_ERROR_OK != error) {
+ LOG(ERROR) << "Error getting attestation chain " << error;
return {};
}
if (expireTimeMilliSeconds == 0) {
- if (attestation_chain->entry_count < 1) {
+ if (attestation_chain.entry_count < 1) {
LOG(ERROR) << "Expected at least one entry in attestation chain";
return {};
}
- keymaster_blob_t* bcBlob = &(attestation_chain->entries[0]);
+ keymaster_blob_t* bcBlob = &(attestation_chain.entries[0]);
const uint8_t* bcData = bcBlob->data;
auto bc = X509_Ptr(d2i_X509(nullptr, &bcData, bcBlob->data_length));
time_t bcNotAfter;
@@ -1015,34 +1016,30 @@
}
::keymaster::AuthorizationSet hwEnforced(hwEnforcedBuilder);
- keymaster_error_t error;
- ::keymaster::CertChainPtr cert_chain_out;
-
// Pretend to be implemented in a trusted environment just so we can pass
// the VTS tests. Of course, this is a pretend-only game since hopefully no
// relying party is ever going to trust our batch key and those keys above
// it.
- //
::keymaster::PureSoftKeymasterContext context(::keymaster::KmVersion::KEYMASTER_4_1,
KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT);
- error = generate_attestation_from_EVP(key, swEnforced, hwEnforced, auth_set, context,
- *attestation_chain, *attestation_signing_key,
- &cert_chain_out);
+ ::keymaster::CertificateChain cert_chain_out = generate_attestation_from_EVP(
+ key, swEnforced, hwEnforced, auth_set, context, move(attestation_chain),
+ *attestation_signing_key, &error);
- if (KM_ERROR_OK != error || !cert_chain_out) {
+ if (KM_ERROR_OK != error) {
LOG(ERROR) << "Error generate attestation from EVP key" << error;
return {};
}
- // translate certificate format from keymaster_cert_chain_t to vector<uint8_t>.
+ // translate certificate format from keymaster_cert_chain_t to vector<vector<uint8_t>>.
vector<vector<uint8_t>> attestationCertificate;
- for (int i = 0; i < cert_chain_out->entry_count; i++) {
+ for (int i = 0; i < cert_chain_out.entry_count; i++) {
attestationCertificate.insert(
attestationCertificate.end(),
vector<uint8_t>(
- cert_chain_out->entries[i].data,
- cert_chain_out->entries[i].data + cert_chain_out->entries[i].data_length));
+ cert_chain_out.entries[i].data,
+ cert_chain_out.entries[i].data + cert_chain_out.entries[i].data_length));
}
return attestationCertificate;
diff --git a/memtrack/aidl/Android.bp b/memtrack/aidl/Android.bp
new file mode 100644
index 0000000..fe4d01b
--- /dev/null
+++ b/memtrack/aidl/Android.bp
@@ -0,0 +1,33 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+aidl_interface {
+ name: "android.hardware.memtrack",
+ vendor_available: true,
+ srcs: ["android/hardware/memtrack/*.aidl"],
+ stability: "vintf",
+ backend: {
+ cpp: {
+ enabled: false,
+ },
+ java: {
+ enabled: false,
+ },
+ ndk: {
+ vndk: {
+ enabled: true,
+ },
+ },
+ },
+}
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl b/memtrack/aidl/aidl_api/android.hardware.memtrack/current/android/hardware/memtrack/DeviceInfo.aidl
similarity index 79%
copy from security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl
copy to memtrack/aidl/aidl_api/android.hardware.memtrack/current/android/hardware/memtrack/DeviceInfo.aidl
index 83b7e6e..00abff9 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl
+++ b/memtrack/aidl/aidl_api/android.hardware.memtrack/current/android/hardware/memtrack/DeviceInfo.aidl
@@ -15,13 +15,9 @@
// with such a backward incompatible change, it has a high risk of breaking
// later when a module using the interface is updated, e.g., Mainline modules.
-package android.hardware.security.keymint;
-@Backing(type="int") @VintfStability
-enum KeyDerivationFunction {
- NONE = 0,
- RFC5869_SHA256 = 1,
- ISO18033_2_KDF1_SHA1 = 2,
- ISO18033_2_KDF1_SHA256 = 3,
- ISO18033_2_KDF2_SHA1 = 4,
- ISO18033_2_KDF2_SHA256 = 5,
+package android.hardware.memtrack;
+@VintfStability
+parcelable DeviceInfo {
+ int id;
+ @utf8InCpp String name;
}
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl b/memtrack/aidl/aidl_api/android.hardware.memtrack/current/android/hardware/memtrack/IMemtrack.aidl
similarity index 79%
copy from security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl
copy to memtrack/aidl/aidl_api/android.hardware.memtrack/current/android/hardware/memtrack/IMemtrack.aidl
index 83b7e6e..844a1bb 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl
+++ b/memtrack/aidl/aidl_api/android.hardware.memtrack/current/android/hardware/memtrack/IMemtrack.aidl
@@ -15,13 +15,9 @@
// with such a backward incompatible change, it has a high risk of breaking
// later when a module using the interface is updated, e.g., Mainline modules.
-package android.hardware.security.keymint;
-@Backing(type="int") @VintfStability
-enum KeyDerivationFunction {
- NONE = 0,
- RFC5869_SHA256 = 1,
- ISO18033_2_KDF1_SHA1 = 2,
- ISO18033_2_KDF1_SHA256 = 3,
- ISO18033_2_KDF2_SHA1 = 4,
- ISO18033_2_KDF2_SHA256 = 5,
+package android.hardware.memtrack;
+@VintfStability
+interface IMemtrack {
+ android.hardware.memtrack.MemtrackRecord[] getMemory(in int pid, in android.hardware.memtrack.MemtrackType type);
+ android.hardware.memtrack.DeviceInfo[] getGpuDeviceInfo();
}
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl b/memtrack/aidl/aidl_api/android.hardware.memtrack/current/android/hardware/memtrack/MemtrackRecord.aidl
similarity index 71%
copy from security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl
copy to memtrack/aidl/aidl_api/android.hardware.memtrack/current/android/hardware/memtrack/MemtrackRecord.aidl
index 83b7e6e..09ecefc 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl
+++ b/memtrack/aidl/aidl_api/android.hardware.memtrack/current/android/hardware/memtrack/MemtrackRecord.aidl
@@ -15,13 +15,18 @@
// with such a backward incompatible change, it has a high risk of breaking
// later when a module using the interface is updated, e.g., Mainline modules.
-package android.hardware.security.keymint;
-@Backing(type="int") @VintfStability
-enum KeyDerivationFunction {
- NONE = 0,
- RFC5869_SHA256 = 1,
- ISO18033_2_KDF1_SHA1 = 2,
- ISO18033_2_KDF1_SHA256 = 3,
- ISO18033_2_KDF2_SHA1 = 4,
- ISO18033_2_KDF2_SHA256 = 5,
+package android.hardware.memtrack;
+@VintfStability
+parcelable MemtrackRecord {
+ int flags;
+ long sizeInBytes;
+ const int FLAG_SMAPS_ACCOUNTED = 2;
+ const int FLAG_SMAPS_UNACCOUNTED = 4;
+ const int FLAG_SHARED = 8;
+ const int FLAG_SHARED_PSS = 16;
+ const int FLAG_PRIVATE = 32;
+ const int FLAG_SYSTEM = 64;
+ const int FLAG_DEDICATED = 128;
+ const int FLAG_NONSECURE = 256;
+ const int FLAG_SECURE = 512;
}
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl b/memtrack/aidl/aidl_api/android.hardware.memtrack/current/android/hardware/memtrack/MemtrackType.aidl
similarity index 82%
rename from security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl
rename to memtrack/aidl/aidl_api/android.hardware.memtrack/current/android/hardware/memtrack/MemtrackType.aidl
index 83b7e6e..7f3f939 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyDerivationFunction.aidl
+++ b/memtrack/aidl/aidl_api/android.hardware.memtrack/current/android/hardware/memtrack/MemtrackType.aidl
@@ -15,13 +15,13 @@
// with such a backward incompatible change, it has a high risk of breaking
// later when a module using the interface is updated, e.g., Mainline modules.
-package android.hardware.security.keymint;
+package android.hardware.memtrack;
@Backing(type="int") @VintfStability
-enum KeyDerivationFunction {
- NONE = 0,
- RFC5869_SHA256 = 1,
- ISO18033_2_KDF1_SHA1 = 2,
- ISO18033_2_KDF1_SHA256 = 3,
- ISO18033_2_KDF2_SHA1 = 4,
- ISO18033_2_KDF2_SHA256 = 5,
+enum MemtrackType {
+ OTHER = 0,
+ GL = 1,
+ GRAPHICS = 2,
+ MULTIMEDIA = 3,
+ CAMERA = 4,
+ NUM_TYPES = 5,
}
diff --git a/memtrack/aidl/android/hardware/memtrack/DeviceInfo.aidl b/memtrack/aidl/android/hardware/memtrack/DeviceInfo.aidl
new file mode 100644
index 0000000..bcba544
--- /dev/null
+++ b/memtrack/aidl/android/hardware/memtrack/DeviceInfo.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.memtrack;
+
+/*
+ * Contains the device name and the device id.
+ */
+@VintfStability
+parcelable DeviceInfo {
+ int id;
+ @utf8InCpp String name;
+}
+
diff --git a/memtrack/aidl/android/hardware/memtrack/IMemtrack.aidl b/memtrack/aidl/android/hardware/memtrack/IMemtrack.aidl
new file mode 100644
index 0000000..18587ee
--- /dev/null
+++ b/memtrack/aidl/android/hardware/memtrack/IMemtrack.aidl
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.memtrack;
+
+import android.hardware.memtrack.DeviceInfo;
+import android.hardware.memtrack.MemtrackRecord;
+import android.hardware.memtrack.MemtrackType;
+
+/**
+ * The Memory Tracker HAL is designed to return information about
+ * device-specific memory usage.
+ * The primary goal is to be able to track memory that is not
+ * trackable in any other way, for example texture memory that is allocated by
+ * a process, but not mapped in to that process's address space.
+ * A secondary goal is to be able to categorize memory used by a process into
+ * GL, graphics, etc. All memory sizes must be in real memory usage,
+ * accounting for stride, bit depth, rounding up to page size, etc.
+ *
+ * Constructor for the interface should be used to perform memtrack management
+ * setup actions and must be called once before any calls to getMemory().
+ */
+@VintfStability
+interface IMemtrack {
+ /**
+ * getMemory() populates MemtrackRecord vector with the sizes of memory
+ * plus associated flags for that memory.
+ *
+ * A process collecting memory statistics will call getMemory for each
+ * combination of pid and memory type. For each memory type that it
+ * recognizes, the HAL must fill out an array of memtrack_record
+ * structures breaking down the statistics of that memory type as much as
+ * possible. For example,
+ * getMemory(<pid>, GL) might return:
+ * { { 4096, ACCOUNTED | PRIVATE | SYSTEM },
+ * { 40960, UNACCOUNTED | PRIVATE | SYSTEM },
+ * { 8192, ACCOUNTED | PRIVATE | DEDICATED },
+ * { 8192, UNACCOUNTED | PRIVATE | DEDICATED } }
+ * If the HAL cannot differentiate between SYSTEM and DEDICATED memory, it
+ * could return:
+ * { { 12288, ACCOUNTED | PRIVATE },
+ * { 49152, UNACCOUNTED | PRIVATE } }
+ *
+ * Memory must not overlap between types. For example, a graphics buffer
+ * that has been mapped into the GPU as a surface must show up when
+ * GRAPHICS is requested and not when GL
+ * is requested.
+ *
+ * @param pid process for which memory information is requested
+ * @param type memory type that information is being requested about
+ * @return vector of MemtrackRecord containing memory information
+ */
+ MemtrackRecord[] getMemory(in int pid, in MemtrackType type);
+
+ /**
+ * getGpuDeviceInfo() populates DeviceInfo with the ID and name
+ * of each GPU device.
+ *
+ * For example, getGpuDeviceInfor, might return:
+ * { { 0, <gpu-device-name> },
+ * { 1, <gpu-device-name> } }
+ *
+ * This information is used to identify GPU devices for GPU specific
+ * memory accounting (e.g. DMA buffer usage).
+ *
+ * @return vector of DeviceInfo populated for all GPU devices.
+ */
+ DeviceInfo[] getGpuDeviceInfo();
+}
diff --git a/memtrack/aidl/android/hardware/memtrack/MemtrackRecord.aidl b/memtrack/aidl/android/hardware/memtrack/MemtrackRecord.aidl
new file mode 100644
index 0000000..dae026e
--- /dev/null
+++ b/memtrack/aidl/android/hardware/memtrack/MemtrackRecord.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.memtrack;
+
+/*
+ * Each record consists of the size of the memory used by the process and
+ * flags indicate all the MemtrackFlags that are valid for this record.
+ */
+@VintfStability
+parcelable MemtrackRecord {
+ /* Memtrack Flags */
+ const int FLAG_SMAPS_ACCOUNTED = 1 << 1;
+ const int FLAG_SMAPS_UNACCOUNTED = 1 << 2;
+ const int FLAG_SHARED = 1 << 3;
+ const int FLAG_SHARED_PSS = 1 << 4;
+ const int FLAG_PRIVATE = 1 << 5;
+ const int FLAG_SYSTEM = 1 << 6;
+ const int FLAG_DEDICATED = 1 << 7;
+ const int FLAG_NONSECURE = 1 << 8;
+ const int FLAG_SECURE = 1 << 9;
+
+ /* Bitfield indicating all flags that are valid for this record */
+ int flags;
+
+ long sizeInBytes;
+}
+
diff --git a/memtrack/aidl/android/hardware/memtrack/MemtrackType.aidl b/memtrack/aidl/android/hardware/memtrack/MemtrackType.aidl
new file mode 100644
index 0000000..715c6bf
--- /dev/null
+++ b/memtrack/aidl/android/hardware/memtrack/MemtrackType.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.memtrack;
+
+/**
+ * Tags which define the usage of the memory buffers.
+ */
+@VintfStability
+@Backing(type="int")
+enum MemtrackType {
+ OTHER = 0,
+ GL = 1,
+ GRAPHICS = 2,
+ MULTIMEDIA = 3,
+ CAMERA = 4,
+ NUM_TYPES,
+}
diff --git a/memtrack/aidl/default/Android.bp b/memtrack/aidl/default/Android.bp
new file mode 100644
index 0000000..52f88c8
--- /dev/null
+++ b/memtrack/aidl/default/Android.bp
@@ -0,0 +1,30 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_binary {
+ name: "android.hardware.memtrack-service.example",
+ relative_install_path: "hw",
+ init_rc: ["memtrack-default.rc"],
+ vintf_fragments: ["memtrack-default.xml"],
+ vendor: true,
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "android.hardware.memtrack-ndk_platform",
+ ],
+ srcs: [
+ "main.cpp",
+ "Memtrack.cpp",
+ ],
+}
diff --git a/memtrack/aidl/default/Memtrack.cpp b/memtrack/aidl/default/Memtrack.cpp
new file mode 100644
index 0000000..7361719
--- /dev/null
+++ b/memtrack/aidl/default/Memtrack.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Memtrack.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace memtrack {
+
+ndk::ScopedAStatus Memtrack::getMemory(int pid, MemtrackType type,
+ std::vector<MemtrackRecord>* _aidl_return) {
+ if (pid < 0) {
+ return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_ILLEGAL_ARGUMENT));
+ }
+ if (type < MemtrackType::OTHER || type >= MemtrackType::NUM_TYPES) {
+ return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+ }
+ _aidl_return->clear();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Memtrack::getGpuDeviceInfo(std::vector<DeviceInfo>* _aidl_return) {
+ _aidl_return->clear();
+ return ndk::ScopedAStatus::ok();
+}
+
+} // namespace memtrack
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/memtrack/aidl/default/Memtrack.h b/memtrack/aidl/default/Memtrack.h
new file mode 100644
index 0000000..f2ef60e
--- /dev/null
+++ b/memtrack/aidl/default/Memtrack.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/memtrack/BnMemtrack.h>
+#include <aidl/android/hardware/memtrack/DeviceInfo.h>
+#include <aidl/android/hardware/memtrack/MemtrackRecord.h>
+#include <aidl/android/hardware/memtrack/MemtrackType.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace memtrack {
+
+class Memtrack : public BnMemtrack {
+ ndk::ScopedAStatus getMemory(int pid, MemtrackType type,
+ std::vector<MemtrackRecord>* _aidl_return) override;
+
+ ndk::ScopedAStatus getGpuDeviceInfo(std::vector<DeviceInfo>* _aidl_return) override;
+};
+
+} // namespace memtrack
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/memtrack/aidl/default/main.cpp b/memtrack/aidl/default/main.cpp
new file mode 100644
index 0000000..d063d2a
--- /dev/null
+++ b/memtrack/aidl/default/main.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Memtrack.h"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+using aidl::android::hardware::memtrack::Memtrack;
+
+int main() {
+ ABinderProcess_setThreadPoolMaxThreadCount(0);
+ std::shared_ptr<Memtrack> memtrack = ndk::SharedRefBase::make<Memtrack>();
+
+ const std::string instance = std::string() + Memtrack::descriptor + "/default";
+ binder_status_t status =
+ AServiceManager_addService(memtrack->asBinder().get(), instance.c_str());
+ CHECK(status == STATUS_OK);
+
+ ABinderProcess_joinThreadPool();
+ return EXIT_FAILURE; // Unreachable
+}
diff --git a/memtrack/aidl/default/memtrack-default.rc b/memtrack/aidl/default/memtrack-default.rc
new file mode 100644
index 0000000..1725cd0
--- /dev/null
+++ b/memtrack/aidl/default/memtrack-default.rc
@@ -0,0 +1,4 @@
+service vendor.memtrack-default /vendor/bin/hw/android.hardware.memtrack-service.example
+ class hal
+ user nobody
+ group system
diff --git a/memtrack/aidl/default/memtrack-default.xml b/memtrack/aidl/default/memtrack-default.xml
new file mode 100644
index 0000000..3e3e0f6
--- /dev/null
+++ b/memtrack/aidl/default/memtrack-default.xml
@@ -0,0 +1,7 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.memtrack</name>
+ <fqname>IMemtrack/default</fqname>
+ </hal>
+</manifest>
+
diff --git a/memtrack/aidl/vts/Android.bp b/memtrack/aidl/vts/Android.bp
new file mode 100644
index 0000000..ea36677
--- /dev/null
+++ b/memtrack/aidl/vts/Android.bp
@@ -0,0 +1,17 @@
+cc_test {
+ name: "VtsHalMemtrackTargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: ["VtsHalMemtrackTargetTest.cpp"],
+ shared_libs: [
+ "libbinder_ndk",
+ ],
+ static_libs: [
+ "android.hardware.memtrack-unstable-ndk_platform",
+ ],
+ test_suites: [
+ "vts-core",
+ ],
+}
diff --git a/memtrack/aidl/vts/VtsHalMemtrackTargetTest.cpp b/memtrack/aidl/vts/VtsHalMemtrackTargetTest.cpp
new file mode 100644
index 0000000..4d33101
--- /dev/null
+++ b/memtrack/aidl/vts/VtsHalMemtrackTargetTest.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+
+#include <aidl/android/hardware/memtrack/DeviceInfo.h>
+#include <aidl/android/hardware/memtrack/IMemtrack.h>
+#include <aidl/android/hardware/memtrack/MemtrackType.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+using aidl::android::hardware::memtrack::DeviceInfo;
+using aidl::android::hardware::memtrack::IMemtrack;
+using aidl::android::hardware::memtrack::MemtrackRecord;
+using aidl::android::hardware::memtrack::MemtrackType;
+
+class MemtrackAidlTest : public testing::TestWithParam<std::string> {
+ public:
+ virtual void SetUp() override {
+ const auto instance = GetParam();
+ ASSERT_TRUE(AServiceManager_isDeclared(instance.c_str()));
+ auto memtrackBinder = ndk::SpAIBinder(AServiceManager_waitForService(instance.c_str()));
+ memtrack_ = IMemtrack::fromBinder(memtrackBinder);
+ ASSERT_NE(memtrack_, nullptr);
+ }
+
+ std::shared_ptr<IMemtrack> memtrack_;
+};
+
+TEST_P(MemtrackAidlTest, GetMemoryInvalidPid) {
+ int pid = -1;
+ MemtrackType type = MemtrackType::OTHER;
+ std::vector<MemtrackRecord> records;
+
+ auto status = memtrack_->getMemory(pid, type, &records);
+
+ EXPECT_EQ(status.getExceptionCode(), EX_ILLEGAL_ARGUMENT);
+}
+
+TEST_P(MemtrackAidlTest, GetMemoryInvalidType) {
+ int pid = 1;
+ MemtrackType type = MemtrackType::NUM_TYPES;
+ std::vector<MemtrackRecord> records;
+
+ auto status = memtrack_->getMemory(pid, type, &records);
+
+ EXPECT_EQ(status.getExceptionCode(), EX_UNSUPPORTED_OPERATION);
+}
+
+TEST_P(MemtrackAidlTest, GetMemory) {
+ int pid = 1;
+ MemtrackType type = MemtrackType::OTHER;
+ std::vector<MemtrackRecord> records;
+
+ auto status = memtrack_->getMemory(pid, type, &records);
+
+ EXPECT_TRUE(status.isOk());
+}
+
+TEST_P(MemtrackAidlTest, GetGpuDeviceInfo) {
+ std::vector<DeviceInfo> device_info;
+
+ auto status = memtrack_->getGpuDeviceInfo(&device_info);
+
+ EXPECT_TRUE(status.isOk());
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MemtrackAidlTest);
+INSTANTIATE_TEST_SUITE_P(PerInstance, MemtrackAidlTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IMemtrack::descriptor)),
+ android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+ return RUN_ALL_TESTS();
+}
diff --git a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Callbacks.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Callbacks.h
index 2e00fce..3b32e1d 100644
--- a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Callbacks.h
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Callbacks.h
@@ -32,6 +32,26 @@
namespace android::hardware::neuralnetworks::V1_0::utils {
+// Converts the results of IDevice::getSupportedOperations* to the NN canonical format. On success,
+// this function returns with the supported operations as indicated by a driver. On failure, this
+// function returns with the appropriate nn::GeneralError.
+nn::GeneralResult<std::vector<bool>> supportedOperationsCallback(
+ ErrorStatus status, const hidl_vec<bool>& supportedOperations);
+
+// Converts the results of IDevice::prepareModel* to the NN canonical format. On success, this
+// function returns with a non-null nn::SharedPreparedModel with a feature level of
+// nn::Version::ANDROID_OC_MR1. On failure, this function returns with the appropriate
+// nn::GeneralError.
+nn::GeneralResult<nn::SharedPreparedModel> prepareModelCallback(
+ ErrorStatus status, const sp<IPreparedModel>& preparedModel);
+
+// Converts the results of IDevice::execute* to the NN canonical format. On success, this function
+// returns with an empty output shape vector and no timing information. On failure, this function
+// returns with the appropriate nn::ExecutionError.
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> executionCallback(
+ ErrorStatus status);
+
+// A HIDL callback class to receive the results of IDevice::prepareModel asynchronously.
class PreparedModelCallback final : public IPreparedModelCallback,
public hal::utils::IProtectedCallback {
public:
@@ -44,11 +64,10 @@
Data get();
private:
- void notifyInternal(Data result);
-
hal::utils::TransferValue<Data> mData;
};
+// A HIDL callback class to receive the results of IDevice::execute asynchronously.
class ExecutionCallback final : public IExecutionCallback, public hal::utils::IProtectedCallback {
public:
using Data = nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>;
@@ -60,8 +79,6 @@
Data get();
private:
- void notifyInternal(Data result);
-
hal::utils::TransferValue<Data> mData;
};
diff --git a/neuralnetworks/1.0/utils/src/Callbacks.cpp b/neuralnetworks/1.0/utils/src/Callbacks.cpp
index a0bdb3c..ea3ea56 100644
--- a/neuralnetworks/1.0/utils/src/Callbacks.cpp
+++ b/neuralnetworks/1.0/utils/src/Callbacks.cpp
@@ -27,6 +27,7 @@
#include <nnapi/Result.h>
#include <nnapi/Types.h>
#include <nnapi/hal/CommonUtils.h>
+#include <nnapi/hal/HandleError.h>
#include <nnapi/hal/ProtectCallback.h>
#include <nnapi/hal/TransferValue.h>
@@ -36,63 +37,52 @@
// lifetimes across processes and for protecting asynchronous calls across HIDL.
namespace android::hardware::neuralnetworks::V1_0::utils {
-namespace {
-nn::GeneralResult<nn::SharedPreparedModel> convertPreparedModel(
- const sp<IPreparedModel>& preparedModel) {
- return NN_TRY(utils::PreparedModel::create(preparedModel));
+nn::GeneralResult<std::vector<bool>> supportedOperationsCallback(
+ ErrorStatus status, const hidl_vec<bool>& supportedOperations) {
+ HANDLE_HAL_STATUS(status) << "get supported operations failed with " << toString(status);
+ return supportedOperations;
}
-} // namespace
+nn::GeneralResult<nn::SharedPreparedModel> prepareModelCallback(
+ ErrorStatus status, const sp<IPreparedModel>& preparedModel) {
+ HANDLE_HAL_STATUS(status) << "model preparation failed with " << toString(status);
+ return NN_TRY(PreparedModel::create(preparedModel));
+}
+
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> executionCallback(
+ ErrorStatus status) {
+ HANDLE_HAL_STATUS(status) << "execution failed with " << toString(status);
+ return {};
+}
Return<void> PreparedModelCallback::notify(ErrorStatus status,
const sp<IPreparedModel>& preparedModel) {
- if (status != ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- notifyInternal(NN_ERROR(canonical) << "preparedModel failed with " << toString(status));
- } else if (preparedModel == nullptr) {
- notifyInternal(NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
- << "Returned preparedModel is nullptr");
- } else {
- notifyInternal(convertPreparedModel(preparedModel));
- }
+ mData.put(prepareModelCallback(status, preparedModel));
return Void();
}
void PreparedModelCallback::notifyAsDeadObject() {
- notifyInternal(NN_ERROR(nn::ErrorStatus::DEAD_OBJECT) << "Dead object");
+ mData.put(NN_ERROR(nn::ErrorStatus::DEAD_OBJECT) << "Dead object");
}
PreparedModelCallback::Data PreparedModelCallback::get() {
return mData.take();
}
-void PreparedModelCallback::notifyInternal(PreparedModelCallback::Data result) {
- mData.put(std::move(result));
-}
-
// ExecutionCallback methods begin here
Return<void> ExecutionCallback::notify(ErrorStatus status) {
- if (status != ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- notifyInternal(NN_ERROR(canonical) << "execute failed with " << toString(status));
- } else {
- notifyInternal({});
- }
+ mData.put(executionCallback(status));
return Void();
}
void ExecutionCallback::notifyAsDeadObject() {
- notifyInternal(NN_ERROR(nn::ErrorStatus::DEAD_OBJECT) << "Dead object");
+ mData.put(NN_ERROR(nn::ErrorStatus::DEAD_OBJECT) << "Dead object");
}
ExecutionCallback::Data ExecutionCallback::get() {
return mData.take();
}
-void ExecutionCallback::notifyInternal(ExecutionCallback::Data result) {
- mData.put(std::move(result));
-}
-
} // namespace android::hardware::neuralnetworks::V1_0::utils
diff --git a/neuralnetworks/1.0/utils/src/Device.cpp b/neuralnetworks/1.0/utils/src/Device.cpp
index 83e0015..93bd81a 100644
--- a/neuralnetworks/1.0/utils/src/Device.cpp
+++ b/neuralnetworks/1.0/utils/src/Device.cpp
@@ -31,6 +31,7 @@
#include <nnapi/hal/CommonUtils.h>
#include <nnapi/hal/HandleError.h>
#include <nnapi/hal/ProtectCallback.h>
+#include <nnapi/hal/TransferValue.h>
#include <functional>
#include <memory>
@@ -44,24 +45,21 @@
namespace android::hardware::neuralnetworks::V1_0::utils {
namespace {
-nn::GeneralResult<nn::Capabilities> initCapabilities(V1_0::IDevice* device) {
+nn::GeneralResult<nn::Capabilities> capabilitiesCallback(ErrorStatus status,
+ const Capabilities& capabilities) {
+ HANDLE_HAL_STATUS(status) << "getting capabilities failed with " << toString(status);
+ return nn::convert(capabilities);
+}
+
+nn::GeneralResult<nn::Capabilities> getCapabilitiesFrom(V1_0::IDevice* device) {
CHECK(device != nullptr);
- nn::GeneralResult<nn::Capabilities> result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
- << "uninitialized";
- const auto cb = [&result](ErrorStatus status, const Capabilities& capabilities) {
- if (status != ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- result = NN_ERROR(canonical) << "getCapabilities failed with " << toString(status);
- } else {
- result = nn::convert(capabilities);
- }
- };
+ auto cb = hal::utils::CallbackValue(capabilitiesCallback);
const auto ret = device->getCapabilities(cb);
HANDLE_TRANSPORT_FAILURE(ret);
- return result;
+ return cb.take();
}
} // namespace
@@ -77,7 +75,7 @@
<< "V1_0::utils::Device::create must have non-null device";
}
- auto capabilities = NN_TRY(initCapabilities(device.get()));
+ auto capabilities = NN_TRY(getCapabilitiesFrom(device.get()));
auto deathHandler = NN_TRY(hal::utils::DeathHandler::create(device));
return std::make_shared<const Device>(PrivateConstructorTag{}, std::move(name),
@@ -134,27 +132,12 @@
const auto hidlModel = NN_TRY(convert(modelInShared));
- nn::GeneralResult<std::vector<bool>> result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
- << "uninitialized";
- auto cb = [&result, &model](ErrorStatus status, const hidl_vec<bool>& supportedOperations) {
- if (status != ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- result = NN_ERROR(canonical)
- << "getSupportedOperations failed with " << toString(status);
- } else if (supportedOperations.size() != model.main.operations.size()) {
- result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
- << "getSupportedOperations returned vector of size "
- << supportedOperations.size() << " but expected "
- << model.main.operations.size();
- } else {
- result = supportedOperations;
- }
- };
+ auto cb = hal::utils::CallbackValue(supportedOperationsCallback);
const auto ret = kDevice->getSupportedOperations(hidlModel, cb);
HANDLE_TRANSPORT_FAILURE(ret);
- return result;
+ return cb.take();
}
nn::GeneralResult<nn::SharedPreparedModel> Device::prepareModel(
@@ -173,10 +156,7 @@
const auto ret = kDevice->prepareModel(hidlModel, cb);
const auto status = HANDLE_TRANSPORT_FAILURE(ret);
- if (status != ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- return NN_ERROR(canonical) << "prepareModel failed with " << toString(status);
- }
+ HANDLE_HAL_STATUS(status) << "model preparation failed with " << toString(status);
return cb->get();
}
diff --git a/neuralnetworks/1.0/utils/src/PreparedModel.cpp b/neuralnetworks/1.0/utils/src/PreparedModel.cpp
index c1dd1d9..c0c22fb 100644
--- a/neuralnetworks/1.0/utils/src/PreparedModel.cpp
+++ b/neuralnetworks/1.0/utils/src/PreparedModel.cpp
@@ -42,8 +42,7 @@
nn::GeneralResult<std::shared_ptr<const PreparedModel>> PreparedModel::create(
sp<V1_0::IPreparedModel> preparedModel) {
if (preparedModel == nullptr) {
- return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
- << "V1_0::utils::PreparedModel::create must have non-null preparedModel";
+ return NN_ERROR() << "V1_0::utils::PreparedModel::create must have non-null preparedModel";
}
auto deathHandler = NN_TRY(hal::utils::DeathHandler::create(preparedModel));
@@ -71,10 +70,7 @@
const auto ret = kPreparedModel->execute(hidlRequest, cb);
const auto status = HANDLE_TRANSPORT_FAILURE(ret);
- if (status != ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- return NN_ERROR(canonical) << "execute failed with " << toString(status);
- }
+ HANDLE_HAL_STATUS(status) << "execution failed with " << toString(status);
auto result = NN_TRY(cb->get());
NN_TRY(hal::utils::makeExecutionFailure(
diff --git a/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Conversions.h b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Conversions.h
index f646462..5d0769f 100644
--- a/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Conversions.h
+++ b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Conversions.h
@@ -51,6 +51,10 @@
nn::GeneralResult<Model> convert(const nn::Model& model);
nn::GeneralResult<ExecutionPreference> convert(const nn::ExecutionPreference& executionPreference);
+nn::GeneralResult<V1_0::DeviceStatus> convert(const nn::DeviceStatus& deviceStatus);
+nn::GeneralResult<V1_0::Request> convert(const nn::Request& request);
+nn::GeneralResult<V1_0::ErrorStatus> convert(const nn::ErrorStatus& status);
+
} // namespace android::hardware::neuralnetworks::V1_1::utils
#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_1_CONVERSIONS_H
diff --git a/neuralnetworks/1.1/utils/src/Conversions.cpp b/neuralnetworks/1.1/utils/src/Conversions.cpp
index 359f68a..b47f25a 100644
--- a/neuralnetworks/1.1/utils/src/Conversions.cpp
+++ b/neuralnetworks/1.1/utils/src/Conversions.cpp
@@ -275,4 +275,16 @@
return validatedConvert(executionPreference);
}
+nn::GeneralResult<V1_0::DeviceStatus> convert(const nn::DeviceStatus& deviceStatus) {
+ return V1_0::utils::convert(deviceStatus);
+}
+
+nn::GeneralResult<V1_0::Request> convert(const nn::Request& request) {
+ return V1_0::utils::convert(request);
+}
+
+nn::GeneralResult<V1_0::ErrorStatus> convert(const nn::ErrorStatus& status) {
+ return V1_0::utils::convert(status);
+}
+
} // namespace android::hardware::neuralnetworks::V1_1::utils
diff --git a/neuralnetworks/1.1/utils/src/Device.cpp b/neuralnetworks/1.1/utils/src/Device.cpp
index b57c7f4..3197ef4 100644
--- a/neuralnetworks/1.1/utils/src/Device.cpp
+++ b/neuralnetworks/1.1/utils/src/Device.cpp
@@ -45,24 +45,21 @@
namespace android::hardware::neuralnetworks::V1_1::utils {
namespace {
-nn::GeneralResult<nn::Capabilities> initCapabilities(V1_1::IDevice* device) {
+nn::GeneralResult<nn::Capabilities> capabilitiesCallback(V1_0::ErrorStatus status,
+ const Capabilities& capabilities) {
+ HANDLE_HAL_STATUS(status) << "getting capabilities failed with " << toString(status);
+ return nn::convert(capabilities);
+}
+
+nn::GeneralResult<nn::Capabilities> getCapabilitiesFrom(V1_1::IDevice* device) {
CHECK(device != nullptr);
- nn::GeneralResult<nn::Capabilities> result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
- << "uninitialized";
- const auto cb = [&result](V1_0::ErrorStatus status, const Capabilities& capabilities) {
- if (status != V1_0::ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- result = NN_ERROR(canonical) << "getCapabilities_1_1 failed with " << toString(status);
- } else {
- result = nn::convert(capabilities);
- }
- };
+ auto cb = hal::utils::CallbackValue(capabilitiesCallback);
const auto ret = device->getCapabilities_1_1(cb);
HANDLE_TRANSPORT_FAILURE(ret);
- return result;
+ return cb.take();
}
} // namespace
@@ -78,7 +75,7 @@
<< "V1_1::utils::Device::create must have non-null device";
}
- auto capabilities = NN_TRY(initCapabilities(device.get()));
+ auto capabilities = NN_TRY(getCapabilitiesFrom(device.get()));
auto deathHandler = NN_TRY(hal::utils::DeathHandler::create(device));
return std::make_shared<const Device>(PrivateConstructorTag{}, std::move(name),
@@ -135,28 +132,12 @@
const auto hidlModel = NN_TRY(convert(modelInShared));
- nn::GeneralResult<std::vector<bool>> result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
- << "uninitialized";
- auto cb = [&result, &model](V1_0::ErrorStatus status,
- const hidl_vec<bool>& supportedOperations) {
- if (status != V1_0::ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- result = NN_ERROR(canonical)
- << "getSupportedOperations_1_1 failed with " << toString(status);
- } else if (supportedOperations.size() != model.main.operations.size()) {
- result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
- << "getSupportedOperations_1_1 returned vector of size "
- << supportedOperations.size() << " but expected "
- << model.main.operations.size();
- } else {
- result = supportedOperations;
- }
- };
+ auto cb = hal::utils::CallbackValue(V1_0::utils::supportedOperationsCallback);
const auto ret = kDevice->getSupportedOperations_1_1(hidlModel, cb);
HANDLE_TRANSPORT_FAILURE(ret);
- return result;
+ return cb.take();
}
nn::GeneralResult<nn::SharedPreparedModel> Device::prepareModel(
@@ -176,10 +157,7 @@
const auto ret = kDevice->prepareModel_1_1(hidlModel, hidlPreference, cb);
const auto status = HANDLE_TRANSPORT_FAILURE(ret);
- if (status != V1_0::ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- return NN_ERROR(canonical) << "prepareModel failed with " << toString(status);
- }
+ HANDLE_HAL_STATUS(status) << "model preparation failed with " << toString(status);
return cb->get();
}
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Callbacks.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Callbacks.h
index 1162bc3..ba3c1ba 100644
--- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Callbacks.h
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Callbacks.h
@@ -36,6 +36,19 @@
namespace android::hardware::neuralnetworks::V1_2::utils {
+// Converts the results of IDevice::prepareModel* to the NN canonical format. On success, this
+// function returns with a non-null nn::SharedPreparedModel with a feature level of
+// nn::Version::ANDROID_Q. On failure, this function returns with the appropriate nn::GeneralError.
+nn::GeneralResult<nn::SharedPreparedModel> prepareModelCallback(
+ V1_0::ErrorStatus status, const sp<IPreparedModel>& preparedModel);
+
+// Converts the results of IDevice::execute* to the NN canonical format. On success, this function
+// returns with the output shapes and the timing information. On failure, this function returns with
+// the appropriate nn::ExecutionError.
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> executionCallback(
+ V1_0::ErrorStatus status, const hidl_vec<OutputShape>& outputShapes, const Timing& timing);
+
+// A HIDL callback class to receive the results of IDevice::prepareModel* asynchronously.
class PreparedModelCallback final : public IPreparedModelCallback,
public hal::utils::IProtectedCallback {
public:
@@ -51,11 +64,10 @@
Data get();
private:
- void notifyInternal(Data result);
-
hal::utils::TransferValue<Data> mData;
};
+// A HIDL callback class to receive the results of IDevice::execute_1_2 asynchronously.
class ExecutionCallback final : public IExecutionCallback, public hal::utils::IProtectedCallback {
public:
using Data = nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>;
@@ -69,8 +81,6 @@
Data get();
private:
- void notifyInternal(Data result);
-
hal::utils::TransferValue<Data> mData;
};
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Conversions.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Conversions.h
index 5dcbc0b..6fd1337 100644
--- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Conversions.h
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Conversions.h
@@ -97,6 +97,12 @@
nn::GeneralResult<hidl_vec<hidl_handle>> convert(const std::vector<nn::SharedHandle>& handles);
nn::GeneralResult<hidl_vec<OutputShape>> convert(const std::vector<nn::OutputShape>& outputShapes);
+nn::GeneralResult<V1_0::DeviceStatus> convert(const nn::DeviceStatus& deviceStatus);
+nn::GeneralResult<V1_0::Request> convert(const nn::Request& request);
+nn::GeneralResult<V1_0::ErrorStatus> convert(const nn::ErrorStatus& status);
+nn::GeneralResult<V1_1::ExecutionPreference> convert(
+ const nn::ExecutionPreference& executionPreference);
+
} // namespace android::hardware::neuralnetworks::V1_2::utils
#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_2_CONVERSIONS_H
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h
index 79c3b04..b4bef5e 100644
--- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h
@@ -37,10 +37,21 @@
namespace android::hardware::neuralnetworks::V1_2::utils {
-nn::GeneralResult<std::string> initVersionString(V1_2::IDevice* device);
-nn::GeneralResult<nn::DeviceType> initDeviceType(V1_2::IDevice* device);
-nn::GeneralResult<std::vector<nn::Extension>> initExtensions(V1_2::IDevice* device);
-nn::GeneralResult<std::pair<uint32_t, uint32_t>> initNumberOfCacheFilesNeeded(
+// Retrieves the version string from the provided device object. On failure, this function returns
+// with the appropriate nn::GeneralError.
+nn::GeneralResult<std::string> getVersionStringFrom(V1_2::IDevice* device);
+
+// Retrieves the device type from the provided device object. On failure, this function returns with
+// the appropriate nn::GeneralError.
+nn::GeneralResult<nn::DeviceType> getDeviceTypeFrom(V1_2::IDevice* device);
+
+// Retrieves the extensions supported by the provided device object. On failure, this function
+// returns with the appropriate nn::GeneralError.
+nn::GeneralResult<std::vector<nn::Extension>> getSupportedExtensionsFrom(V1_2::IDevice* device);
+
+// Retrieves the number of model cache files and data cache files needed by the provided device
+// object. On failure, this function returns with the appropriate nn::GeneralError.
+nn::GeneralResult<std::pair<uint32_t, uint32_t>> getNumberOfCacheFilesNeededFrom(
V1_2::IDevice* device);
// Class that adapts V1_2::IDevice to nn::IDevice.
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/PreparedModel.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/PreparedModel.h
index 8ed5ca7..6a56a82 100644
--- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/PreparedModel.h
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/PreparedModel.h
@@ -41,10 +41,10 @@
public:
static nn::GeneralResult<std::shared_ptr<const PreparedModel>> create(
- sp<V1_2::IPreparedModel> preparedModel);
+ sp<V1_2::IPreparedModel> preparedModel, bool executeSynchronously);
- PreparedModel(PrivateConstructorTag tag, sp<V1_2::IPreparedModel> preparedModel,
- hal::utils::DeathHandler deathHandler);
+ PreparedModel(PrivateConstructorTag tag, bool executeSynchronously,
+ sp<V1_2::IPreparedModel> preparedModel, hal::utils::DeathHandler deathHandler);
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
const nn::Request& request, nn::MeasureTiming measure,
@@ -65,6 +65,7 @@
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> executeAsynchronously(
const V1_0::Request& request, MeasureTiming measure) const;
+ const bool kExecuteSynchronously;
const sp<V1_2::IPreparedModel> kPreparedModel;
const hal::utils::DeathHandler kDeathHandler;
};
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Utils.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Utils.h
index 70149a2..c289fc8 100644
--- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Utils.h
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Utils.h
@@ -30,6 +30,8 @@
namespace android::hardware::neuralnetworks::V1_2::utils {
+using CacheToken = hidl_array<uint8_t, static_cast<size_t>(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>;
+
constexpr auto kDefaultMesaureTiming = MeasureTiming::NO;
constexpr auto kNoTiming = Timing{.timeOnDevice = std::numeric_limits<uint64_t>::max(),
.timeInDriver = std::numeric_limits<uint64_t>::max()};
diff --git a/neuralnetworks/1.2/utils/src/Callbacks.cpp b/neuralnetworks/1.2/utils/src/Callbacks.cpp
index ab3e0ca..fefa122 100644
--- a/neuralnetworks/1.2/utils/src/Callbacks.cpp
+++ b/neuralnetworks/1.2/utils/src/Callbacks.cpp
@@ -27,6 +27,7 @@
#include <nnapi/IPreparedModel.h>
#include <nnapi/Result.h>
#include <nnapi/Types.h>
+#include <nnapi/hal/1.0/Callbacks.h>
#include <nnapi/hal/1.0/Conversions.h>
#include <nnapi/hal/1.0/PreparedModel.h>
#include <nnapi/hal/CommonUtils.h>
@@ -42,104 +43,73 @@
namespace android::hardware::neuralnetworks::V1_2::utils {
namespace {
-nn::GeneralResult<nn::SharedPreparedModel> convertPreparedModel(
- const sp<V1_0::IPreparedModel>& preparedModel) {
- return NN_TRY(V1_0::utils::PreparedModel::create(preparedModel));
-}
-
-nn::GeneralResult<nn::SharedPreparedModel> convertPreparedModel(
- const sp<IPreparedModel>& preparedModel) {
- return NN_TRY(utils::PreparedModel::create(preparedModel));
-}
-
nn::GeneralResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
convertExecutionGeneralResultsHelper(const hidl_vec<OutputShape>& outputShapes,
const Timing& timing) {
return std::make_pair(NN_TRY(nn::convert(outputShapes)), NN_TRY(nn::convert(timing)));
}
-nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
-convertExecutionGeneralResults(const hidl_vec<OutputShape>& outputShapes, const Timing& timing) {
+} // namespace
+
+nn::GeneralResult<nn::SharedPreparedModel> prepareModelCallback(
+ V1_0::ErrorStatus status, const sp<IPreparedModel>& preparedModel) {
+ HANDLE_HAL_STATUS(status) << "model preparation failed with " << toString(status);
+ return NN_TRY(PreparedModel::create(preparedModel, /*executeSynchronously=*/true));
+}
+
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> executionCallback(
+ V1_0::ErrorStatus status, const hidl_vec<OutputShape>& outputShapes, const Timing& timing) {
+ if (status == V1_0::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE) {
+ auto canonicalOutputShapes =
+ nn::convert(outputShapes).value_or(std::vector<nn::OutputShape>{});
+ return NN_ERROR(nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE, std::move(canonicalOutputShapes))
+ << "execution failed with " << toString(status);
+ }
+ HANDLE_HAL_STATUS(status) << "execution failed with " << toString(status);
return hal::utils::makeExecutionFailure(
convertExecutionGeneralResultsHelper(outputShapes, timing));
}
-} // namespace
-
Return<void> PreparedModelCallback::notify(V1_0::ErrorStatus status,
const sp<V1_0::IPreparedModel>& preparedModel) {
- if (status != V1_0::ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- notifyInternal(NN_ERROR(canonical) << "preparedModel failed with " << toString(status));
- } else if (preparedModel == nullptr) {
- notifyInternal(NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
- << "Returned preparedModel is nullptr");
- } else {
- notifyInternal(convertPreparedModel(preparedModel));
- }
+ mData.put(V1_0::utils::prepareModelCallback(status, preparedModel));
return Void();
}
Return<void> PreparedModelCallback::notify_1_2(V1_0::ErrorStatus status,
const sp<IPreparedModel>& preparedModel) {
- if (status != V1_0::ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- notifyInternal(NN_ERROR(canonical) << "preparedModel failed with " << toString(status));
- } else if (preparedModel == nullptr) {
- notifyInternal(NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
- << "Returned preparedModel is nullptr");
- } else {
- notifyInternal(convertPreparedModel(preparedModel));
- }
+ mData.put(prepareModelCallback(status, preparedModel));
return Void();
}
void PreparedModelCallback::notifyAsDeadObject() {
- notifyInternal(NN_ERROR(nn::ErrorStatus::DEAD_OBJECT) << "Dead object");
+ mData.put(NN_ERROR(nn::ErrorStatus::DEAD_OBJECT) << "Dead object");
}
PreparedModelCallback::Data PreparedModelCallback::get() {
return mData.take();
}
-void PreparedModelCallback::notifyInternal(PreparedModelCallback::Data result) {
- mData.put(std::move(result));
-}
-
// ExecutionCallback methods begin here
Return<void> ExecutionCallback::notify(V1_0::ErrorStatus status) {
- if (status != V1_0::ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- notifyInternal(NN_ERROR(canonical) << "execute failed with " << toString(status));
- } else {
- notifyInternal({});
- }
+ mData.put(V1_0::utils::executionCallback(status));
return Void();
}
Return<void> ExecutionCallback::notify_1_2(V1_0::ErrorStatus status,
const hidl_vec<OutputShape>& outputShapes,
const Timing& timing) {
- if (status != V1_0::ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- notifyInternal(NN_ERROR(canonical) << "execute failed with " << toString(status));
- } else {
- notifyInternal(convertExecutionGeneralResults(outputShapes, timing));
- }
+ mData.put(executionCallback(status, outputShapes, timing));
return Void();
}
void ExecutionCallback::notifyAsDeadObject() {
- notifyInternal(NN_ERROR(nn::ErrorStatus::DEAD_OBJECT) << "Dead object");
+ mData.put(NN_ERROR(nn::ErrorStatus::DEAD_OBJECT) << "Dead object");
}
ExecutionCallback::Data ExecutionCallback::get() {
return mData.take();
}
-void ExecutionCallback::notifyInternal(ExecutionCallback::Data result) {
- mData.put(std::move(result));
-}
-
} // namespace android::hardware::neuralnetworks::V1_2::utils
diff --git a/neuralnetworks/1.2/utils/src/Conversions.cpp b/neuralnetworks/1.2/utils/src/Conversions.cpp
index 3790d1f..062f6f7 100644
--- a/neuralnetworks/1.2/utils/src/Conversions.cpp
+++ b/neuralnetworks/1.2/utils/src/Conversions.cpp
@@ -26,6 +26,7 @@
#include <nnapi/Types.h>
#include <nnapi/Validation.h>
#include <nnapi/hal/1.0/Conversions.h>
+#include <nnapi/hal/1.1/Conversions.h>
#include <nnapi/hal/CommonUtils.h>
#include <nnapi/hal/HandleError.h>
@@ -622,4 +623,21 @@
return validatedConvert(outputShapes);
}
+nn::GeneralResult<V1_0::DeviceStatus> convert(const nn::DeviceStatus& deviceStatus) {
+ return V1_1::utils::convert(deviceStatus);
+}
+
+nn::GeneralResult<V1_0::Request> convert(const nn::Request& request) {
+ return V1_1::utils::convert(request);
+}
+
+nn::GeneralResult<V1_0::ErrorStatus> convert(const nn::ErrorStatus& status) {
+ return V1_1::utils::convert(status);
+}
+
+nn::GeneralResult<V1_1::ExecutionPreference> convert(
+ const nn::ExecutionPreference& executionPreference) {
+ return V1_1::utils::convert(executionPreference);
+}
+
} // namespace android::hardware::neuralnetworks::V1_2::utils
diff --git a/neuralnetworks/1.2/utils/src/Device.cpp b/neuralnetworks/1.2/utils/src/Device.cpp
index 6cca841..9fe0de2 100644
--- a/neuralnetworks/1.2/utils/src/Device.cpp
+++ b/neuralnetworks/1.2/utils/src/Device.cpp
@@ -47,109 +47,102 @@
namespace android::hardware::neuralnetworks::V1_2::utils {
namespace {
-nn::GeneralResult<nn::Capabilities> initCapabilities(V1_2::IDevice* device) {
+nn::GeneralResult<nn::Capabilities> capabilitiesCallback(V1_0::ErrorStatus status,
+ const Capabilities& capabilities) {
+ HANDLE_HAL_STATUS(status) << "getting capabilities failed with " << toString(status);
+ return nn::convert(capabilities);
+}
+
+nn::GeneralResult<std::string> versionStringCallback(V1_0::ErrorStatus status,
+ const hidl_string& versionString) {
+ HANDLE_HAL_STATUS(status) << "getVersionString failed with " << toString(status);
+ return versionString;
+}
+
+nn::GeneralResult<nn::DeviceType> deviceTypeCallback(V1_0::ErrorStatus status,
+ DeviceType deviceType) {
+ HANDLE_HAL_STATUS(status) << "getDeviceType failed with " << toString(status);
+ return nn::convert(deviceType);
+}
+
+nn::GeneralResult<std::vector<nn::Extension>> supportedExtensionsCallback(
+ V1_0::ErrorStatus status, const hidl_vec<Extension>& extensions) {
+ HANDLE_HAL_STATUS(status) << "getExtensions failed with " << toString(status);
+ return nn::convert(extensions);
+}
+
+nn::GeneralResult<std::pair<uint32_t, uint32_t>> numberOfCacheFilesNeededCallback(
+ V1_0::ErrorStatus status, uint32_t numModelCache, uint32_t numDataCache) {
+ HANDLE_HAL_STATUS(status) << "getNumberOfCacheFilesNeeded failed with " << toString(status);
+ if (numModelCache > nn::kMaxNumberOfCacheFiles) {
+ return NN_ERROR() << "getNumberOfCacheFilesNeeded returned numModelCache files greater "
+ "than allowed max ("
+ << numModelCache << " vs " << nn::kMaxNumberOfCacheFiles << ")";
+ }
+ if (numDataCache > nn::kMaxNumberOfCacheFiles) {
+ return NN_ERROR() << "getNumberOfCacheFilesNeeded returned numDataCache files greater "
+ "than allowed max ("
+ << numDataCache << " vs " << nn::kMaxNumberOfCacheFiles << ")";
+ }
+ return std::make_pair(numModelCache, numDataCache);
+}
+
+nn::GeneralResult<nn::Capabilities> getCapabilitiesFrom(V1_2::IDevice* device) {
CHECK(device != nullptr);
- nn::GeneralResult<nn::Capabilities> result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
- << "uninitialized";
- const auto cb = [&result](V1_0::ErrorStatus status, const Capabilities& capabilities) {
- if (status != V1_0::ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- result = NN_ERROR(canonical) << "getCapabilities_1_2 failed with " << toString(status);
- } else {
- result = nn::convert(capabilities);
- }
- };
+ auto cb = hal::utils::CallbackValue(capabilitiesCallback);
const auto ret = device->getCapabilities_1_2(cb);
HANDLE_TRANSPORT_FAILURE(ret);
- return result;
+ return cb.take();
}
} // namespace
-nn::GeneralResult<std::string> initVersionString(V1_2::IDevice* device) {
+nn::GeneralResult<std::string> getVersionStringFrom(V1_2::IDevice* device) {
CHECK(device != nullptr);
- nn::GeneralResult<std::string> result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
- << "uninitialized";
- const auto cb = [&result](V1_0::ErrorStatus status, const hidl_string& versionString) {
- if (status != V1_0::ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- result = NN_ERROR(canonical) << "getVersionString failed with " << toString(status);
- } else {
- result = versionString;
- }
- };
+ auto cb = hal::utils::CallbackValue(versionStringCallback);
const auto ret = device->getVersionString(cb);
HANDLE_TRANSPORT_FAILURE(ret);
- return result;
+ return cb.take();
}
-nn::GeneralResult<nn::DeviceType> initDeviceType(V1_2::IDevice* device) {
+nn::GeneralResult<nn::DeviceType> getDeviceTypeFrom(V1_2::IDevice* device) {
CHECK(device != nullptr);
- nn::GeneralResult<nn::DeviceType> result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
- << "uninitialized";
- const auto cb = [&result](V1_0::ErrorStatus status, DeviceType deviceType) {
- if (status != V1_0::ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- result = NN_ERROR(canonical) << "getDeviceType failed with " << toString(status);
- } else {
- result = nn::convert(deviceType);
- }
- };
+ auto cb = hal::utils::CallbackValue(deviceTypeCallback);
const auto ret = device->getType(cb);
HANDLE_TRANSPORT_FAILURE(ret);
- return result;
+ return cb.take();
}
-nn::GeneralResult<std::vector<nn::Extension>> initExtensions(V1_2::IDevice* device) {
+nn::GeneralResult<std::vector<nn::Extension>> getSupportedExtensionsFrom(V1_2::IDevice* device) {
CHECK(device != nullptr);
- nn::GeneralResult<std::vector<nn::Extension>> result =
- NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "uninitialized";
- const auto cb = [&result](V1_0::ErrorStatus status, const hidl_vec<Extension>& extensions) {
- if (status != V1_0::ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- result = NN_ERROR(canonical) << "getExtensions failed with " << toString(status);
- } else {
- result = nn::convert(extensions);
- }
- };
+ auto cb = hal::utils::CallbackValue(supportedExtensionsCallback);
const auto ret = device->getSupportedExtensions(cb);
HANDLE_TRANSPORT_FAILURE(ret);
- return result;
+ return cb.take();
}
-nn::GeneralResult<std::pair<uint32_t, uint32_t>> initNumberOfCacheFilesNeeded(
+nn::GeneralResult<std::pair<uint32_t, uint32_t>> getNumberOfCacheFilesNeededFrom(
V1_2::IDevice* device) {
CHECK(device != nullptr);
- nn::GeneralResult<std::pair<uint32_t, uint32_t>> result =
- NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "uninitialized";
- const auto cb = [&result](V1_0::ErrorStatus status, uint32_t numModelCache,
- uint32_t numDataCache) {
- if (status != V1_0::ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- result = NN_ERROR(canonical)
- << "getNumberOfCacheFilesNeeded failed with " << toString(status);
- } else {
- result = std::make_pair(numModelCache, numDataCache);
- }
- };
+ auto cb = hal::utils::CallbackValue(numberOfCacheFilesNeededCallback);
const auto ret = device->getNumberOfCacheFilesNeeded(cb);
HANDLE_TRANSPORT_FAILURE(ret);
- return result;
+ return cb.take();
}
nn::GeneralResult<std::shared_ptr<const Device>> Device::create(std::string name,
@@ -163,11 +156,11 @@
<< "V1_2::utils::Device::create must have non-null device";
}
- auto versionString = NN_TRY(initVersionString(device.get()));
- const auto deviceType = NN_TRY(initDeviceType(device.get()));
- auto extensions = NN_TRY(initExtensions(device.get()));
- auto capabilities = NN_TRY(initCapabilities(device.get()));
- const auto numberOfCacheFilesNeeded = NN_TRY(initNumberOfCacheFilesNeeded(device.get()));
+ auto versionString = NN_TRY(getVersionStringFrom(device.get()));
+ const auto deviceType = NN_TRY(getDeviceTypeFrom(device.get()));
+ auto extensions = NN_TRY(getSupportedExtensionsFrom(device.get()));
+ auto capabilities = NN_TRY(getCapabilitiesFrom(device.get()));
+ const auto numberOfCacheFilesNeeded = NN_TRY(getNumberOfCacheFilesNeededFrom(device.get()));
auto deathHandler = NN_TRY(hal::utils::DeathHandler::create(device));
return std::make_shared<const Device>(
@@ -232,28 +225,12 @@
const auto hidlModel = NN_TRY(convert(modelInShared));
- nn::GeneralResult<std::vector<bool>> result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
- << "uninitialized";
- auto cb = [&result, &model](V1_0::ErrorStatus status,
- const hidl_vec<bool>& supportedOperations) {
- if (status != V1_0::ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- result = NN_ERROR(canonical)
- << "getSupportedOperations_1_2 failed with " << toString(status);
- } else if (supportedOperations.size() != model.main.operations.size()) {
- result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
- << "getSupportedOperations_1_2 returned vector of size "
- << supportedOperations.size() << " but expected "
- << model.main.operations.size();
- } else {
- result = supportedOperations;
- }
- };
+ auto cb = hal::utils::CallbackValue(V1_0::utils::supportedOperationsCallback);
const auto ret = kDevice->getSupportedOperations_1_2(hidlModel, cb);
HANDLE_TRANSPORT_FAILURE(ret);
- return result;
+ return cb.take();
}
nn::GeneralResult<nn::SharedPreparedModel> Device::prepareModel(
@@ -266,10 +243,10 @@
NN_TRY(hal::utils::flushDataFromPointerToShared(&model, &maybeModelInShared));
const auto hidlModel = NN_TRY(convert(modelInShared));
- const auto hidlPreference = NN_TRY(V1_1::utils::convert(preference));
+ const auto hidlPreference = NN_TRY(convert(preference));
const auto hidlModelCache = NN_TRY(convert(modelCache));
const auto hidlDataCache = NN_TRY(convert(dataCache));
- const auto hidlToken = token;
+ const auto hidlToken = CacheToken{token};
const auto cb = sp<PreparedModelCallback>::make();
const auto scoped = kDeathHandler.protectCallback(cb.get());
@@ -277,10 +254,7 @@
const auto ret = kDevice->prepareModel_1_2(hidlModel, hidlPreference, hidlModelCache,
hidlDataCache, hidlToken, cb);
const auto status = HANDLE_TRANSPORT_FAILURE(ret);
- if (status != V1_0::ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- return NN_ERROR(canonical) << "prepareModel_1_2 failed with " << toString(status);
- }
+ HANDLE_HAL_STATUS(status) << "model preparation failed with " << toString(status);
return cb->get();
}
@@ -290,17 +264,14 @@
const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const {
const auto hidlModelCache = NN_TRY(convert(modelCache));
const auto hidlDataCache = NN_TRY(convert(dataCache));
- const auto hidlToken = token;
+ const auto hidlToken = CacheToken{token};
const auto cb = sp<PreparedModelCallback>::make();
const auto scoped = kDeathHandler.protectCallback(cb.get());
const auto ret = kDevice->prepareModelFromCache(hidlModelCache, hidlDataCache, hidlToken, cb);
const auto status = HANDLE_TRANSPORT_FAILURE(ret);
- if (status != V1_0::ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- return NN_ERROR(canonical) << "prepareModelFromCache failed with " << toString(status);
- }
+ HANDLE_HAL_STATUS(status) << "model preparation from cache failed with " << toString(status);
return cb->get();
}
diff --git a/neuralnetworks/1.2/utils/src/PreparedModel.cpp b/neuralnetworks/1.2/utils/src/PreparedModel.cpp
index b422ced..6d00082 100644
--- a/neuralnetworks/1.2/utils/src/PreparedModel.cpp
+++ b/neuralnetworks/1.2/utils/src/PreparedModel.cpp
@@ -41,54 +41,33 @@
// lifetimes across processes and for protecting asynchronous calls across HIDL.
namespace android::hardware::neuralnetworks::V1_2::utils {
-namespace {
-
-nn::GeneralResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
-convertExecutionResultsHelper(const hidl_vec<OutputShape>& outputShapes, const Timing& timing) {
- return std::make_pair(NN_TRY(nn::convert(outputShapes)), NN_TRY(nn::convert(timing)));
-}
-
-nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> convertExecutionResults(
- const hidl_vec<OutputShape>& outputShapes, const Timing& timing) {
- return hal::utils::makeExecutionFailure(convertExecutionResultsHelper(outputShapes, timing));
-}
-
-} // namespace
nn::GeneralResult<std::shared_ptr<const PreparedModel>> PreparedModel::create(
- sp<V1_2::IPreparedModel> preparedModel) {
+ sp<V1_2::IPreparedModel> preparedModel, bool executeSynchronously) {
if (preparedModel == nullptr) {
- return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
- << "V1_2::utils::PreparedModel::create must have non-null preparedModel";
+ return NN_ERROR() << "V1_2::utils::PreparedModel::create must have non-null preparedModel";
}
auto deathHandler = NN_TRY(hal::utils::DeathHandler::create(preparedModel));
- return std::make_shared<const PreparedModel>(PrivateConstructorTag{}, std::move(preparedModel),
- std::move(deathHandler));
+ return std::make_shared<const PreparedModel>(PrivateConstructorTag{}, executeSynchronously,
+ std::move(preparedModel), std::move(deathHandler));
}
-PreparedModel::PreparedModel(PrivateConstructorTag /*tag*/, sp<V1_2::IPreparedModel> preparedModel,
+PreparedModel::PreparedModel(PrivateConstructorTag /*tag*/, bool executeSynchronously,
+ sp<V1_2::IPreparedModel> preparedModel,
hal::utils::DeathHandler deathHandler)
- : kPreparedModel(std::move(preparedModel)), kDeathHandler(std::move(deathHandler)) {}
+ : kExecuteSynchronously(executeSynchronously),
+ kPreparedModel(std::move(preparedModel)),
+ kDeathHandler(std::move(deathHandler)) {}
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
PreparedModel::executeSynchronously(const V1_0::Request& request, MeasureTiming measure) const {
- nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> result =
- NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "uninitialized";
- const auto cb = [&result](V1_0::ErrorStatus status, const hidl_vec<OutputShape>& outputShapes,
- const Timing& timing) {
- if (status != V1_0::ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- result = NN_ERROR(canonical) << "executeSynchronously failed with " << toString(status);
- } else {
- result = convertExecutionResults(outputShapes, timing);
- }
- };
+ auto cb = hal::utils::CallbackValue(executionCallback);
const auto ret = kPreparedModel->executeSynchronously(request, measure, cb);
HANDLE_TRANSPORT_FAILURE(ret);
- return result;
+ return cb.take();
}
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
@@ -98,9 +77,8 @@
const auto ret = kPreparedModel->execute_1_2(request, measure, cb);
const auto status = HANDLE_TRANSPORT_FAILURE(ret);
- if (status != V1_0::ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- return NN_ERROR(canonical) << "execute failed with " << toString(status);
+ if (status != V1_0::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE) {
+ HANDLE_HAL_STATUS(status) << "execution failed with " << toString(status);
}
return cb->get();
@@ -115,31 +93,17 @@
const nn::Request& requestInShared = NN_TRY(hal::utils::makeExecutionFailure(
hal::utils::flushDataFromPointerToShared(&request, &maybeRequestInShared)));
- const auto hidlRequest =
- NN_TRY(hal::utils::makeExecutionFailure(V1_0::utils::convert(requestInShared)));
+ const auto hidlRequest = NN_TRY(hal::utils::makeExecutionFailure(convert(requestInShared)));
const auto hidlMeasure = NN_TRY(hal::utils::makeExecutionFailure(convert(measure)));
- nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> result =
- NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "uninitialized";
- const bool preferSynchronous = true;
+ auto result = kExecuteSynchronously ? executeSynchronously(hidlRequest, hidlMeasure)
+ : executeAsynchronously(hidlRequest, hidlMeasure);
+ auto [outputShapes, timing] = NN_TRY(std::move(result));
- // Execute synchronously if allowed.
- if (preferSynchronous) {
- result = executeSynchronously(hidlRequest, hidlMeasure);
- }
+ NN_TRY(hal::utils::makeExecutionFailure(
+ hal::utils::unflushDataFromSharedToPointer(request, maybeRequestInShared)));
- // Run asymchronous execution if execution has not already completed.
- if (!result.has_value()) {
- result = executeAsynchronously(hidlRequest, hidlMeasure);
- }
-
- // Flush output buffers if suxcessful execution.
- if (result.has_value()) {
- NN_TRY(hal::utils::makeExecutionFailure(
- hal::utils::unflushDataFromSharedToPointer(request, maybeRequestInShared)));
- }
-
- return result;
+ return std::make_pair(std::move(outputShapes), timing);
}
nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
@@ -154,7 +118,7 @@
}
std::any PreparedModel::getUnderlyingResource() const {
- sp<V1_0::IPreparedModel> resource = kPreparedModel;
+ sp<V1_2::IPreparedModel> resource = kPreparedModel;
return resource;
}
diff --git a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Callbacks.h b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Callbacks.h
index cb2a56a..643172e 100644
--- a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Callbacks.h
+++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Callbacks.h
@@ -39,6 +39,26 @@
namespace android::hardware::neuralnetworks::V1_3::utils {
+// Converts the results of IDevice::getSupportedOperations* to the NN canonical format. On success,
+// this function returns with the supported operations as indicated by a driver. On failure, this
+// function returns with the appropriate nn::GeneralError.
+nn::GeneralResult<std::vector<bool>> supportedOperationsCallback(
+ ErrorStatus status, const hidl_vec<bool>& supportedOperations);
+
+// Converts the results of IDevice::prepareModel* to the NN canonical format. On success, this
+// function returns with a non-null nn::SharedPreparedModel with a feature level of
+// nn::Version::ANDROID_R. On failure, this function returns with the appropriate nn::GeneralError.
+nn::GeneralResult<nn::SharedPreparedModel> prepareModelCallback(
+ ErrorStatus status, const sp<IPreparedModel>& preparedModel);
+
+// Converts the results of IDevice::execute* to the NN canonical format. On success, this function
+// returns with the output shapes and the timing information. On failure, this function returns with
+// the appropriate nn::ExecutionError.
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> executionCallback(
+ ErrorStatus status, const hidl_vec<V1_2::OutputShape>& outputShapes,
+ const V1_2::Timing& timing);
+
+// A HIDL callback class to receive the results of IDevice::prepareModel* asynchronously.
class PreparedModelCallback final : public IPreparedModelCallback,
public hal::utils::IProtectedCallback {
public:
@@ -55,11 +75,10 @@
Data get();
private:
- void notifyInternal(Data result);
-
hal::utils::TransferValue<Data> mData;
};
+// A HIDL callback class to receive the results of IDevice::execute_1_3 asynchronously.
class ExecutionCallback final : public IExecutionCallback, public hal::utils::IProtectedCallback {
public:
using Data = nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>;
@@ -76,8 +95,6 @@
Data get();
private:
- void notifyInternal(Data result);
-
hal::utils::TransferValue<Data> mData;
};
diff --git a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Conversions.h b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Conversions.h
index 477bb7b..74a6534 100644
--- a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Conversions.h
+++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Conversions.h
@@ -103,6 +103,17 @@
nn::GeneralResult<hidl_memory> convert(const nn::Memory& memory);
nn::GeneralResult<hidl_vec<BufferRole>> convert(const std::vector<nn::BufferRole>& bufferRoles);
+nn::GeneralResult<V1_0::DeviceStatus> convert(const nn::DeviceStatus& deviceStatus);
+nn::GeneralResult<V1_1::ExecutionPreference> convert(
+ const nn::ExecutionPreference& executionPreference);
+nn::GeneralResult<hidl_vec<V1_2::Extension>> convert(const std::vector<nn::Extension>& extensions);
+nn::GeneralResult<hidl_vec<hidl_handle>> convert(const std::vector<nn::SharedHandle>& handles);
+nn::GeneralResult<hidl_vec<V1_2::OutputShape>> convert(
+ const std::vector<nn::OutputShape>& outputShapes);
+nn::GeneralResult<V1_2::DeviceType> convert(const nn::DeviceType& deviceType);
+nn::GeneralResult<V1_2::MeasureTiming> convert(const nn::MeasureTiming& measureTiming);
+nn::GeneralResult<V1_2::Timing> convert(const nn::Timing& timing);
+
} // namespace android::hardware::neuralnetworks::V1_3::utils
#endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_1_3_CONVERSIONS_H
diff --git a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/PreparedModel.h b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/PreparedModel.h
index c4ba483..664d87a 100644
--- a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/PreparedModel.h
+++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/PreparedModel.h
@@ -40,10 +40,10 @@
public:
static nn::GeneralResult<std::shared_ptr<const PreparedModel>> create(
- sp<V1_3::IPreparedModel> preparedModel);
+ sp<V1_3::IPreparedModel> preparedModel, bool executeSynchronously);
- PreparedModel(PrivateConstructorTag tag, sp<V1_3::IPreparedModel> preparedModel,
- hal::utils::DeathHandler deathHandler);
+ PreparedModel(PrivateConstructorTag tag, bool executeSynchronously,
+ sp<V1_3::IPreparedModel> preparedModel, hal::utils::DeathHandler deathHandler);
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
const nn::Request& request, nn::MeasureTiming measure,
@@ -66,6 +66,7 @@
const Request& request, V1_2::MeasureTiming measure, const OptionalTimePoint& deadline,
const OptionalTimeoutDuration& loopTimeoutDuration) const;
+ const bool kExecuteSynchronously;
const sp<V1_3::IPreparedModel> kPreparedModel;
const hal::utils::DeathHandler kDeathHandler;
};
diff --git a/neuralnetworks/1.3/utils/src/Buffer.cpp b/neuralnetworks/1.3/utils/src/Buffer.cpp
index 4ef54a2..614033e 100644
--- a/neuralnetworks/1.3/utils/src/Buffer.cpp
+++ b/neuralnetworks/1.3/utils/src/Buffer.cpp
@@ -41,12 +41,10 @@
nn::GeneralResult<std::shared_ptr<const Buffer>> Buffer::create(
sp<V1_3::IBuffer> buffer, nn::Request::MemoryDomainToken token) {
if (buffer == nullptr) {
- return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
- << "V1_3::utils::Buffer::create must have non-null buffer";
+ return NN_ERROR() << "V1_3::utils::Buffer::create must have non-null buffer";
}
if (token == static_cast<nn::Request::MemoryDomainToken>(0)) {
- return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
- << "V1_3::utils::Buffer::create must have non-zero token";
+ return NN_ERROR() << "V1_3::utils::Buffer::create must have non-zero token";
}
return std::make_shared<const Buffer>(PrivateConstructorTag{}, std::move(buffer), token);
@@ -68,10 +66,7 @@
const auto ret = kBuffer->copyTo(hidlDst);
const auto status = HANDLE_TRANSPORT_FAILURE(ret);
- if (status != ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- return NN_ERROR(canonical) << "IBuffer::copyTo failed with " << toString(status);
- }
+ HANDLE_HAL_STATUS(status) << "IBuffer::copyTo failed with " << toString(status);
return {};
}
@@ -83,10 +78,7 @@
const auto ret = kBuffer->copyFrom(hidlSrc, hidlDimensions);
const auto status = HANDLE_TRANSPORT_FAILURE(ret);
- if (status != ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- return NN_ERROR(canonical) << "IBuffer::copyFrom failed with " << toString(status);
- }
+ HANDLE_HAL_STATUS(status) << "IBuffer::copyFrom failed with " << toString(status);
return {};
}
diff --git a/neuralnetworks/1.3/utils/src/Callbacks.cpp b/neuralnetworks/1.3/utils/src/Callbacks.cpp
index 17c20fb..af76e6a 100644
--- a/neuralnetworks/1.3/utils/src/Callbacks.cpp
+++ b/neuralnetworks/1.3/utils/src/Callbacks.cpp
@@ -30,6 +30,7 @@
#include <nnapi/Types.h>
#include <nnapi/hal/1.0/Conversions.h>
#include <nnapi/hal/1.0/PreparedModel.h>
+#include <nnapi/hal/1.2/Callbacks.h>
#include <nnapi/hal/1.2/Conversions.h>
#include <nnapi/hal/1.2/PreparedModel.h>
#include <nnapi/hal/CommonUtils.h>
@@ -45,136 +46,93 @@
namespace android::hardware::neuralnetworks::V1_3::utils {
namespace {
-nn::GeneralResult<nn::SharedPreparedModel> convertPreparedModel(
- const sp<V1_0::IPreparedModel>& preparedModel) {
- return NN_TRY(V1_0::utils::PreparedModel::create(preparedModel));
-}
-
-nn::GeneralResult<nn::SharedPreparedModel> convertPreparedModel(
- const sp<V1_2::IPreparedModel>& preparedModel) {
- return NN_TRY(V1_2::utils::PreparedModel::create(preparedModel));
-}
-
-nn::GeneralResult<nn::SharedPreparedModel> convertPreparedModel(
- const sp<IPreparedModel>& preparedModel) {
- return NN_TRY(utils::PreparedModel::create(preparedModel));
-}
-
nn::GeneralResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
convertExecutionGeneralResultsHelper(const hidl_vec<V1_2::OutputShape>& outputShapes,
const V1_2::Timing& timing) {
return std::make_pair(NN_TRY(nn::convert(outputShapes)), NN_TRY(nn::convert(timing)));
}
-nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
-convertExecutionGeneralResults(const hidl_vec<V1_2::OutputShape>& outputShapes,
- const V1_2::Timing& timing) {
+} // namespace
+
+nn::GeneralResult<std::vector<bool>> supportedOperationsCallback(
+ ErrorStatus status, const hidl_vec<bool>& supportedOperations) {
+ HANDLE_HAL_STATUS(status) << "get supported operations failed with " << toString(status);
+ return supportedOperations;
+}
+
+nn::GeneralResult<nn::SharedPreparedModel> prepareModelCallback(
+ ErrorStatus status, const sp<IPreparedModel>& preparedModel) {
+ HANDLE_HAL_STATUS(status) << "model preparation failed with " << toString(status);
+ return NN_TRY(PreparedModel::create(preparedModel, /*executeSynchronously=*/true));
+}
+
+nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> executionCallback(
+ ErrorStatus status, const hidl_vec<V1_2::OutputShape>& outputShapes,
+ const V1_2::Timing& timing) {
+ if (status == ErrorStatus::OUTPUT_INSUFFICIENT_SIZE) {
+ auto canonicalOutputShapes =
+ nn::convert(outputShapes).value_or(std::vector<nn::OutputShape>{});
+ return NN_ERROR(nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE, std::move(canonicalOutputShapes))
+ << "execution failed with " << toString(status);
+ }
+ HANDLE_HAL_STATUS(status) << "execution failed with " << toString(status);
return hal::utils::makeExecutionFailure(
convertExecutionGeneralResultsHelper(outputShapes, timing));
}
-} // namespace
-
Return<void> PreparedModelCallback::notify(V1_0::ErrorStatus status,
const sp<V1_0::IPreparedModel>& preparedModel) {
- if (status != V1_0::ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- notifyInternal(NN_ERROR(canonical) << "preparedModel failed with " << toString(status));
- } else if (preparedModel == nullptr) {
- notifyInternal(NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
- << "Returned preparedModel is nullptr");
- } else {
- notifyInternal(convertPreparedModel(preparedModel));
- }
+ mData.put(V1_0::utils::prepareModelCallback(status, preparedModel));
return Void();
}
Return<void> PreparedModelCallback::notify_1_2(V1_0::ErrorStatus status,
const sp<V1_2::IPreparedModel>& preparedModel) {
- if (status != V1_0::ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- notifyInternal(NN_ERROR(canonical) << "preparedModel failed with " << toString(status));
- } else if (preparedModel == nullptr) {
- notifyInternal(NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
- << "Returned preparedModel is nullptr");
- } else {
- notifyInternal(convertPreparedModel(preparedModel));
- }
+ mData.put(V1_2::utils::prepareModelCallback(status, preparedModel));
return Void();
}
Return<void> PreparedModelCallback::notify_1_3(ErrorStatus status,
const sp<IPreparedModel>& preparedModel) {
- if (status != ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- notifyInternal(NN_ERROR(canonical) << "preparedModel failed with " << toString(status));
- } else if (preparedModel == nullptr) {
- notifyInternal(NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
- << "Returned preparedModel is nullptr");
- } else {
- notifyInternal(convertPreparedModel(preparedModel));
- }
+ mData.put(prepareModelCallback(status, preparedModel));
return Void();
}
void PreparedModelCallback::notifyAsDeadObject() {
- notifyInternal(NN_ERROR(nn::ErrorStatus::DEAD_OBJECT) << "Dead object");
+ mData.put(NN_ERROR(nn::ErrorStatus::DEAD_OBJECT) << "Dead object");
}
PreparedModelCallback::Data PreparedModelCallback::get() {
return mData.take();
}
-void PreparedModelCallback::notifyInternal(PreparedModelCallback::Data result) {
- mData.put(std::move(result));
-}
-
// ExecutionCallback methods begin here
Return<void> ExecutionCallback::notify(V1_0::ErrorStatus status) {
- if (status != V1_0::ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- notifyInternal(NN_ERROR(canonical) << "execute failed with " << toString(status));
- } else {
- notifyInternal({});
- }
+ mData.put(V1_0::utils::executionCallback(status));
return Void();
}
Return<void> ExecutionCallback::notify_1_2(V1_0::ErrorStatus status,
const hidl_vec<V1_2::OutputShape>& outputShapes,
const V1_2::Timing& timing) {
- if (status != V1_0::ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- notifyInternal(NN_ERROR(canonical) << "execute failed with " << toString(status));
- } else {
- notifyInternal(convertExecutionGeneralResults(outputShapes, timing));
- }
+ mData.put(V1_2::utils::executionCallback(status, outputShapes, timing));
return Void();
}
Return<void> ExecutionCallback::notify_1_3(ErrorStatus status,
const hidl_vec<V1_2::OutputShape>& outputShapes,
const V1_2::Timing& timing) {
- if (status != ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- notifyInternal(NN_ERROR(canonical) << "execute failed with " << toString(status));
- } else {
- notifyInternal(convertExecutionGeneralResults(outputShapes, timing));
- }
+ mData.put(executionCallback(status, outputShapes, timing));
return Void();
}
void ExecutionCallback::notifyAsDeadObject() {
- notifyInternal(NN_ERROR(nn::ErrorStatus::DEAD_OBJECT) << "Dead object");
+ mData.put(NN_ERROR(nn::ErrorStatus::DEAD_OBJECT) << "Dead object");
}
ExecutionCallback::Data ExecutionCallback::get() {
return mData.take();
}
-void ExecutionCallback::notifyInternal(ExecutionCallback::Data result) {
- mData.put(std::move(result));
-}
-
} // namespace android::hardware::neuralnetworks::V1_3::utils
diff --git a/neuralnetworks/1.3/utils/src/Conversions.cpp b/neuralnetworks/1.3/utils/src/Conversions.cpp
index c89a69f..8b7db2b 100644
--- a/neuralnetworks/1.3/utils/src/Conversions.cpp
+++ b/neuralnetworks/1.3/utils/src/Conversions.cpp
@@ -685,4 +685,38 @@
return validatedConvert(bufferRoles);
}
+nn::GeneralResult<V1_0::DeviceStatus> convert(const nn::DeviceStatus& deviceStatus) {
+ return V1_2::utils::convert(deviceStatus);
+}
+
+nn::GeneralResult<V1_1::ExecutionPreference> convert(
+ const nn::ExecutionPreference& executionPreference) {
+ return V1_2::utils::convert(executionPreference);
+}
+
+nn::GeneralResult<hidl_vec<V1_2::Extension>> convert(const std::vector<nn::Extension>& extensions) {
+ return V1_2::utils::convert(extensions);
+}
+
+nn::GeneralResult<hidl_vec<hidl_handle>> convert(const std::vector<nn::SharedHandle>& handles) {
+ return V1_2::utils::convert(handles);
+}
+
+nn::GeneralResult<hidl_vec<V1_2::OutputShape>> convert(
+ const std::vector<nn::OutputShape>& outputShapes) {
+ return V1_2::utils::convert(outputShapes);
+}
+
+nn::GeneralResult<V1_2::DeviceType> convert(const nn::DeviceType& deviceType) {
+ return V1_2::utils::convert(deviceType);
+}
+
+nn::GeneralResult<V1_2::MeasureTiming> convert(const nn::MeasureTiming& measureTiming) {
+ return V1_2::utils::convert(measureTiming);
+}
+
+nn::GeneralResult<V1_2::Timing> convert(const nn::Timing& timing) {
+ return V1_2::utils::convert(timing);
+}
+
} // namespace android::hardware::neuralnetworks::V1_3::utils
diff --git a/neuralnetworks/1.3/utils/src/Device.cpp b/neuralnetworks/1.3/utils/src/Device.cpp
index 6056498..d710b85 100644
--- a/neuralnetworks/1.3/utils/src/Device.cpp
+++ b/neuralnetworks/1.3/utils/src/Device.cpp
@@ -36,6 +36,7 @@
#include <nnapi/hal/1.1/Conversions.h>
#include <nnapi/hal/1.2/Conversions.h>
#include <nnapi/hal/1.2/Device.h>
+#include <nnapi/hal/1.2/Utils.h>
#include <nnapi/hal/CommonUtils.h>
#include <nnapi/hal/HandleError.h>
#include <nnapi/hal/ProtectCallback.h>
@@ -69,29 +70,27 @@
return hidlPreparedModels;
}
-nn::GeneralResult<nn::SharedBuffer> convert(
- nn::GeneralResult<std::shared_ptr<const Buffer>> result) {
- return NN_TRY(std::move(result));
+nn::GeneralResult<nn::Capabilities> capabilitiesCallback(ErrorStatus status,
+ const Capabilities& capabilities) {
+ HANDLE_HAL_STATUS(status) << "getting capabilities failed with " << toString(status);
+ return nn::convert(capabilities);
}
-nn::GeneralResult<nn::Capabilities> initCapabilities(V1_3::IDevice* device) {
+nn::GeneralResult<nn::Capabilities> getCapabilitiesFrom(V1_3::IDevice* device) {
CHECK(device != nullptr);
- nn::GeneralResult<nn::Capabilities> result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
- << "uninitialized";
- const auto cb = [&result](ErrorStatus status, const Capabilities& capabilities) {
- if (status != ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- result = NN_ERROR(canonical) << "getCapabilities_1_3 failed with " << toString(status);
- } else {
- result = nn::convert(capabilities);
- }
- };
+ auto cb = hal::utils::CallbackValue(capabilitiesCallback);
const auto ret = device->getCapabilities_1_3(cb);
HANDLE_TRANSPORT_FAILURE(ret);
- return result;
+ return cb.take();
+}
+
+nn::GeneralResult<nn::SharedBuffer> allocationCallback(ErrorStatus status,
+ const sp<IBuffer>& buffer, uint32_t token) {
+ HANDLE_HAL_STATUS(status) << "IDevice::allocate failed with " << toString(status);
+ return Buffer::create(buffer, static_cast<nn::Request::MemoryDomainToken>(token));
}
} // namespace
@@ -107,12 +106,12 @@
<< "V1_3::utils::Device::create must have non-null device";
}
- auto versionString = NN_TRY(V1_2::utils::initVersionString(device.get()));
- const auto deviceType = NN_TRY(V1_2::utils::initDeviceType(device.get()));
- auto extensions = NN_TRY(V1_2::utils::initExtensions(device.get()));
- auto capabilities = NN_TRY(initCapabilities(device.get()));
+ auto versionString = NN_TRY(V1_2::utils::getVersionStringFrom(device.get()));
+ const auto deviceType = NN_TRY(V1_2::utils::getDeviceTypeFrom(device.get()));
+ auto extensions = NN_TRY(V1_2::utils::getSupportedExtensionsFrom(device.get()));
+ auto capabilities = NN_TRY(getCapabilitiesFrom(device.get()));
const auto numberOfCacheFilesNeeded =
- NN_TRY(V1_2::utils::initNumberOfCacheFilesNeeded(device.get()));
+ NN_TRY(V1_2::utils::getNumberOfCacheFilesNeededFrom(device.get()));
auto deathHandler = NN_TRY(hal::utils::DeathHandler::create(device));
return std::make_shared<const Device>(
@@ -177,27 +176,12 @@
const auto hidlModel = NN_TRY(convert(modelInShared));
- nn::GeneralResult<std::vector<bool>> result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
- << "uninitialized";
- auto cb = [&result, &model](ErrorStatus status, const hidl_vec<bool>& supportedOperations) {
- if (status != ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- result = NN_ERROR(canonical)
- << "IDevice::getSupportedOperations_1_3 failed with " << toString(status);
- } else if (supportedOperations.size() != model.main.operations.size()) {
- result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
- << "IDevice::getSupportedOperations_1_3 returned vector of size "
- << supportedOperations.size() << " but expected "
- << model.main.operations.size();
- } else {
- result = supportedOperations;
- }
- };
+ auto cb = hal::utils::CallbackValue(supportedOperationsCallback);
const auto ret = kDevice->getSupportedOperations_1_3(hidlModel, cb);
HANDLE_TRANSPORT_FAILURE(ret);
- return result;
+ return cb.take();
}
nn::GeneralResult<nn::SharedPreparedModel> Device::prepareModel(
@@ -210,12 +194,12 @@
NN_TRY(hal::utils::flushDataFromPointerToShared(&model, &maybeModelInShared));
const auto hidlModel = NN_TRY(convert(modelInShared));
- const auto hidlPreference = NN_TRY(V1_1::utils::convert(preference));
+ const auto hidlPreference = NN_TRY(convert(preference));
const auto hidlPriority = NN_TRY(convert(priority));
const auto hidlDeadline = NN_TRY(convert(deadline));
- const auto hidlModelCache = NN_TRY(V1_2::utils::convert(modelCache));
- const auto hidlDataCache = NN_TRY(V1_2::utils::convert(dataCache));
- const auto hidlToken = token;
+ const auto hidlModelCache = NN_TRY(convert(modelCache));
+ const auto hidlDataCache = NN_TRY(convert(dataCache));
+ const auto hidlToken = V1_2::utils::CacheToken{token};
const auto cb = sp<PreparedModelCallback>::make();
const auto scoped = kDeathHandler.protectCallback(cb.get());
@@ -224,10 +208,7 @@
kDevice->prepareModel_1_3(hidlModel, hidlPreference, hidlPriority, hidlDeadline,
hidlModelCache, hidlDataCache, hidlToken, cb);
const auto status = HANDLE_TRANSPORT_FAILURE(ret);
- if (status != ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- return NN_ERROR(canonical) << "prepareModel_1_3 failed with " << toString(status);
- }
+ HANDLE_HAL_STATUS(status) << "model preparation failed with " << toString(status);
return cb->get();
}
@@ -236,9 +217,9 @@
nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const {
const auto hidlDeadline = NN_TRY(convert(deadline));
- const auto hidlModelCache = NN_TRY(V1_2::utils::convert(modelCache));
- const auto hidlDataCache = NN_TRY(V1_2::utils::convert(dataCache));
- const auto hidlToken = token;
+ const auto hidlModelCache = NN_TRY(convert(modelCache));
+ const auto hidlDataCache = NN_TRY(convert(dataCache));
+ const auto hidlToken = V1_2::utils::CacheToken{token};
const auto cb = sp<PreparedModelCallback>::make();
const auto scoped = kDeathHandler.protectCallback(cb.get());
@@ -246,10 +227,7 @@
const auto ret = kDevice->prepareModelFromCache_1_3(hidlDeadline, hidlModelCache, hidlDataCache,
hidlToken, cb);
const auto status = HANDLE_TRANSPORT_FAILURE(ret);
- if (status != ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- return NN_ERROR(canonical) << "prepareModelFromCache_1_3 failed with " << toString(status);
- }
+ HANDLE_HAL_STATUS(status) << "model preparation from cache failed with " << toString(status);
return cb->get();
}
@@ -263,27 +241,13 @@
const auto hidlInputRoles = NN_TRY(convert(inputRoles));
const auto hidlOutputRoles = NN_TRY(convert(outputRoles));
- nn::GeneralResult<nn::SharedBuffer> result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
- << "uninitialized";
- auto cb = [&result](ErrorStatus status, const sp<IBuffer>& buffer, uint32_t token) {
- if (status != ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- result = NN_ERROR(canonical) << "IDevice::allocate failed with " << toString(status);
- } else if (buffer == nullptr) {
- result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Returned buffer is nullptr";
- } else if (token == 0) {
- result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Returned token is invalid (0)";
- } else {
- result = convert(
- Buffer::create(buffer, static_cast<nn::Request::MemoryDomainToken>(token)));
- }
- };
+ auto cb = hal::utils::CallbackValue(allocationCallback);
const auto ret =
kDevice->allocate(hidlDesc, hidlPreparedModels, hidlInputRoles, hidlOutputRoles, cb);
HANDLE_TRANSPORT_FAILURE(ret);
- return result;
+ return cb.take();
}
} // namespace android::hardware::neuralnetworks::V1_3::utils
diff --git a/neuralnetworks/1.3/utils/src/PreparedModel.cpp b/neuralnetworks/1.3/utils/src/PreparedModel.cpp
index 0bae95d..7b4b7ba 100644
--- a/neuralnetworks/1.3/utils/src/PreparedModel.cpp
+++ b/neuralnetworks/1.3/utils/src/PreparedModel.cpp
@@ -45,25 +45,17 @@
namespace android::hardware::neuralnetworks::V1_3::utils {
namespace {
-nn::GeneralResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
-convertExecutionResultsHelper(const hidl_vec<V1_2::OutputShape>& outputShapes,
- const V1_2::Timing& timing) {
- return std::make_pair(NN_TRY(nn::convert(outputShapes)), NN_TRY(nn::convert(timing)));
-}
-
-nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> convertExecutionResults(
- const hidl_vec<V1_2::OutputShape>& outputShapes, const V1_2::Timing& timing) {
- return hal::utils::makeExecutionFailure(convertExecutionResultsHelper(outputShapes, timing));
-}
-
nn::GeneralResult<std::pair<nn::Timing, nn::Timing>> convertFencedExecutionCallbackResults(
- const V1_2::Timing& timingLaunched, const V1_2::Timing& timingFenced) {
+ ErrorStatus status, const V1_2::Timing& timingLaunched, const V1_2::Timing& timingFenced) {
+ HANDLE_HAL_STATUS(status) << "fenced execution callback info failed with " << toString(status);
return std::make_pair(NN_TRY(nn::convert(timingLaunched)), NN_TRY(nn::convert(timingFenced)));
}
-nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
-convertExecuteFencedResults(const hidl_handle& syncFence,
- const sp<IFencedExecutionCallback>& callback) {
+nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> fencedExecutionCallback(
+ ErrorStatus status, const hidl_handle& syncFence,
+ const sp<IFencedExecutionCallback>& callback) {
+ HANDLE_HAL_STATUS(status) << "fenced execution failed with " << toString(status);
+
auto resultSyncFence = nn::SyncFence::createAsSignaled();
if (syncFence.getNativeHandle() != nullptr) {
auto sharedHandle = NN_TRY(nn::convert(syncFence));
@@ -78,23 +70,12 @@
// Create callback which can be used to retrieve the execution error status and timings.
nn::ExecuteFencedInfoCallback resultCallback =
[callback]() -> nn::GeneralResult<std::pair<nn::Timing, nn::Timing>> {
- nn::GeneralResult<std::pair<nn::Timing, nn::Timing>> result =
- NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "uninitialized";
- auto cb = [&result](ErrorStatus status, const V1_2::Timing& timingLaunched,
- const V1_2::Timing& timingFenced) {
- if (status != ErrorStatus::NONE) {
- const auto canonical =
- nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- result = NN_ERROR(canonical) << "getExecutionInfo failed with " << toString(status);
- } else {
- result = convertFencedExecutionCallbackResults(timingLaunched, timingFenced);
- }
- };
+ auto cb = hal::utils::CallbackValue(convertFencedExecutionCallbackResults);
const auto ret = callback->getExecutionInfo(cb);
HANDLE_TRANSPORT_FAILURE(ret);
- return result;
+ return cb.take();
};
return std::make_pair(std::move(resultSyncFence), std::move(resultCallback));
@@ -103,42 +84,34 @@
} // namespace
nn::GeneralResult<std::shared_ptr<const PreparedModel>> PreparedModel::create(
- sp<V1_3::IPreparedModel> preparedModel) {
+ sp<V1_3::IPreparedModel> preparedModel, bool executeSynchronously) {
if (preparedModel == nullptr) {
- return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
- << "V1_3::utils::PreparedModel::create must have non-null preparedModel";
+ return NN_ERROR() << "V1_3::utils::PreparedModel::create must have non-null preparedModel";
}
auto deathHandler = NN_TRY(hal::utils::DeathHandler::create(preparedModel));
- return std::make_shared<const PreparedModel>(PrivateConstructorTag{}, std::move(preparedModel),
- std::move(deathHandler));
+ return std::make_shared<const PreparedModel>(PrivateConstructorTag{}, executeSynchronously,
+ std::move(preparedModel), std::move(deathHandler));
}
-PreparedModel::PreparedModel(PrivateConstructorTag /*tag*/, sp<V1_3::IPreparedModel> preparedModel,
+PreparedModel::PreparedModel(PrivateConstructorTag /*tag*/, bool executeSynchronously,
+ sp<V1_3::IPreparedModel> preparedModel,
hal::utils::DeathHandler deathHandler)
- : kPreparedModel(std::move(preparedModel)), kDeathHandler(std::move(deathHandler)) {}
+ : kExecuteSynchronously(executeSynchronously),
+ kPreparedModel(std::move(preparedModel)),
+ kDeathHandler(std::move(deathHandler)) {}
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
PreparedModel::executeSynchronously(const Request& request, V1_2::MeasureTiming measure,
const OptionalTimePoint& deadline,
const OptionalTimeoutDuration& loopTimeoutDuration) const {
- nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> result =
- NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "uninitialized";
- const auto cb = [&result](ErrorStatus status, const hidl_vec<V1_2::OutputShape>& outputShapes,
- const V1_2::Timing& timing) {
- if (status != ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- result = NN_ERROR(canonical) << "executeSynchronously failed with " << toString(status);
- } else {
- result = convertExecutionResults(outputShapes, timing);
- }
- };
+ auto cb = hal::utils::CallbackValue(executionCallback);
const auto ret = kPreparedModel->executeSynchronously_1_3(request, measure, deadline,
loopTimeoutDuration, cb);
HANDLE_TRANSPORT_FAILURE(ret);
- return result;
+ return cb.take();
}
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
@@ -151,9 +124,8 @@
const auto ret =
kPreparedModel->execute_1_3(request, measure, deadline, loopTimeoutDuration, cb);
const auto status = HANDLE_TRANSPORT_FAILURE(ret);
- if (status != ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- return NN_ERROR(canonical) << "executeAsynchronously failed with " << toString(status);
+ if (status != ErrorStatus::OUTPUT_INSUFFICIENT_SIZE) {
+ HANDLE_HAL_STATUS(status) << "execution failed with " << toString(status);
}
return cb->get();
@@ -169,35 +141,22 @@
hal::utils::flushDataFromPointerToShared(&request, &maybeRequestInShared)));
const auto hidlRequest = NN_TRY(hal::utils::makeExecutionFailure(convert(requestInShared)));
- const auto hidlMeasure =
- NN_TRY(hal::utils::makeExecutionFailure(V1_2::utils::convert(measure)));
+ const auto hidlMeasure = NN_TRY(hal::utils::makeExecutionFailure(convert(measure)));
const auto hidlDeadline = NN_TRY(hal::utils::makeExecutionFailure(convert(deadline)));
const auto hidlLoopTimeoutDuration =
NN_TRY(hal::utils::makeExecutionFailure(convert(loopTimeoutDuration)));
- nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> result =
- NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "uninitialized";
- const bool preferSynchronous = true;
+ auto result = kExecuteSynchronously
+ ? executeSynchronously(hidlRequest, hidlMeasure, hidlDeadline,
+ hidlLoopTimeoutDuration)
+ : executeAsynchronously(hidlRequest, hidlMeasure, hidlDeadline,
+ hidlLoopTimeoutDuration);
+ auto [outputShapes, timing] = NN_TRY(std::move(result));
- // Execute synchronously if allowed.
- if (preferSynchronous) {
- result = executeSynchronously(hidlRequest, hidlMeasure, hidlDeadline,
- hidlLoopTimeoutDuration);
- }
+ NN_TRY(hal::utils::makeExecutionFailure(
+ hal::utils::unflushDataFromSharedToPointer(request, maybeRequestInShared)));
- // Run asymchronous execution if execution has not already completed.
- if (!result.has_value()) {
- result = executeAsynchronously(hidlRequest, hidlMeasure, hidlDeadline,
- hidlLoopTimeoutDuration);
- }
-
- // Flush output buffers if suxcessful execution.
- if (result.has_value()) {
- NN_TRY(hal::utils::makeExecutionFailure(
- hal::utils::unflushDataFromSharedToPointer(request, maybeRequestInShared)));
- }
-
- return result;
+ return std::make_pair(std::move(outputShapes), timing);
}
nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
@@ -212,28 +171,18 @@
const auto hidlRequest = NN_TRY(convert(requestInShared));
const auto hidlWaitFor = NN_TRY(hal::utils::convertSyncFences(waitFor));
- const auto hidlMeasure = NN_TRY(V1_2::utils::convert(measure));
+ const auto hidlMeasure = NN_TRY(convert(measure));
const auto hidlDeadline = NN_TRY(convert(deadline));
const auto hidlLoopTimeoutDuration = NN_TRY(convert(loopTimeoutDuration));
const auto hidlTimeoutDurationAfterFence = NN_TRY(convert(timeoutDurationAfterFence));
- nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> result =
- NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "uninitialized";
- auto cb = [&result](ErrorStatus status, const hidl_handle& syncFence,
- const sp<IFencedExecutionCallback>& callback) {
- if (status != ErrorStatus::NONE) {
- const auto canonical = nn::convert(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
- result = NN_ERROR(canonical) << "executeFenced failed with " << toString(status);
- } else {
- result = convertExecuteFencedResults(syncFence, callback);
- }
- };
+ auto cb = hal::utils::CallbackValue(fencedExecutionCallback);
const auto ret = kPreparedModel->executeFenced(hidlRequest, hidlWaitFor, hidlMeasure,
hidlDeadline, hidlLoopTimeoutDuration,
hidlTimeoutDurationAfterFence, cb);
HANDLE_TRANSPORT_FAILURE(ret);
- auto [syncFence, callback] = NN_TRY(std::move(result));
+ auto [syncFence, callback] = NN_TRY(cb.take());
// If executeFenced required the request memory to be moved into shared memory, block here until
// the fenced execution has completed and flush the memory back.
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/CommonUtils.h b/neuralnetworks/utils/common/include/nnapi/hal/CommonUtils.h
index 43bb0c6..b3989e5 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/CommonUtils.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/CommonUtils.h
@@ -44,9 +44,18 @@
bool hasNoPointerData(const nn::Model& model);
bool hasNoPointerData(const nn::Request& request);
-// Relocate pointer-based data to shared memory.
+// Relocate pointer-based data to shared memory. If `model` has no Operand::LifeTime::POINTER data,
+// the function returns with a reference to `model`. If `model` has Operand::LifeTime::POINTER data,
+// the model is copied to `maybeModelInSharedOut` with the POINTER data relocated to a memory pool,
+// and the function returns with a reference to `*maybeModelInSharedOut`.
nn::GeneralResult<std::reference_wrapper<const nn::Model>> flushDataFromPointerToShared(
const nn::Model* model, std::optional<nn::Model>* maybeModelInSharedOut);
+
+// Relocate pointer-based data to shared memory. If `request` has no
+// Request::Argument::LifeTime::POINTER data, the function returns with a reference to `request`. If
+// `request` has Request::Argument::LifeTime::POINTER data, the request is copied to
+// `maybeRequestInSharedOut` with the POINTER data relocated to a memory pool, and the function
+// returns with a reference to `*maybeRequestInSharedOut`.
nn::GeneralResult<std::reference_wrapper<const nn::Request>> flushDataFromPointerToShared(
const nn::Request* request, std::optional<nn::Request>* maybeRequestInSharedOut);
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/HandleError.h b/neuralnetworks/utils/common/include/nnapi/hal/HandleError.h
index 78b2a12..95a20a8 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/HandleError.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/HandleError.h
@@ -79,4 +79,11 @@
return makeExecutionFailure(makeGeneralFailure(result, status));
}
+#define HANDLE_HAL_STATUS(status) \
+ if (const auto canonical = ::android::nn::convert(status).value_or( \
+ ::android::nn::ErrorStatus::GENERAL_FAILURE); \
+ canonical == ::android::nn::ErrorStatus::NONE) { \
+ } else \
+ return NN_ERROR(canonical)
+
} // namespace android::hardware::neuralnetworks::utils
\ No newline at end of file
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/ResilientBuffer.h b/neuralnetworks/utils/common/include/nnapi/hal/ResilientBuffer.h
index 996ec1e..9d5e3e6 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/ResilientBuffer.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/ResilientBuffer.h
@@ -34,7 +34,7 @@
struct PrivateConstructorTag {};
public:
- using Factory = std::function<nn::GeneralResult<nn::SharedBuffer>(bool blocking)>;
+ using Factory = std::function<nn::GeneralResult<nn::SharedBuffer>()>;
static nn::GeneralResult<std::shared_ptr<const ResilientBuffer>> create(Factory makeBuffer);
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h b/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h
index 4bfed6c..84ae799 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/ResilientDevice.h
@@ -46,8 +46,8 @@
nn::Capabilities capabilities, nn::SharedDevice device);
nn::SharedDevice getDevice() const EXCLUDES(mMutex);
- nn::SharedDevice recover(const nn::IDevice* failingDevice, bool blocking) const
- EXCLUDES(mMutex);
+ nn::GeneralResult<nn::SharedDevice> recover(const nn::IDevice* failingDevice,
+ bool blocking) const EXCLUDES(mMutex);
const std::string& getName() const override;
const std::string& getVersionString() const override;
@@ -81,17 +81,14 @@
private:
bool isValidInternal() const EXCLUDES(mMutex);
nn::GeneralResult<nn::SharedPreparedModel> prepareModelInternal(
- bool blocking, const nn::Model& model, nn::ExecutionPreference preference,
- nn::Priority priority, nn::OptionalTimePoint deadline,
- const std::vector<nn::SharedHandle>& modelCache,
+ const nn::Model& model, nn::ExecutionPreference preference, nn::Priority priority,
+ nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const;
nn::GeneralResult<nn::SharedPreparedModel> prepareModelFromCacheInternal(
- bool blocking, nn::OptionalTimePoint deadline,
- const std::vector<nn::SharedHandle>& modelCache,
+ nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const;
nn::GeneralResult<nn::SharedBuffer> allocateInternal(
- bool blocking, const nn::BufferDesc& desc,
- const std::vector<nn::SharedPreparedModel>& preparedModels,
+ const nn::BufferDesc& desc, const std::vector<nn::SharedPreparedModel>& preparedModels,
const std::vector<nn::BufferRole>& inputRoles,
const std::vector<nn::BufferRole>& outputRoles) const;
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/ResilientPreparedModel.h b/neuralnetworks/utils/common/include/nnapi/hal/ResilientPreparedModel.h
index d86c88b..faae673 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/ResilientPreparedModel.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/ResilientPreparedModel.h
@@ -34,7 +34,7 @@
struct PrivateConstructorTag {};
public:
- using Factory = std::function<nn::GeneralResult<nn::SharedPreparedModel>(bool blocking)>;
+ using Factory = std::function<nn::GeneralResult<nn::SharedPreparedModel>()>;
static nn::GeneralResult<std::shared_ptr<const ResilientPreparedModel>> create(
Factory makePreparedModel);
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/TransferValue.h b/neuralnetworks/utils/common/include/nnapi/hal/TransferValue.h
index 7103c6b..6679afe 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/TransferValue.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/TransferValue.h
@@ -17,19 +17,60 @@
#ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_TRANSFER_VALUE_H
#define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_TRANSFER_VALUE_H
+#include <android-base/logging.h>
#include <android-base/thread_annotations.h>
#include <condition_variable>
+#include <functional>
#include <mutex>
#include <optional>
+#include <type_traits>
namespace android::hardware::neuralnetworks::utils {
-// This class is thread safe.
+// This class adapts a function pointer and offers two affordances:
+// 1) This class object can be used to generate a callback (via the implicit conversion operator)
+// that can be used to send the result to `CallbackValue` when called.
+// 2) This class object can be used to retrieve the result of the callback with `take`.
+//
+// This class is thread compatible.
+template <typename ReturnType, typename... ArgTypes>
+class CallbackValue final {
+ public:
+ using FunctionType = std::add_pointer_t<ReturnType(ArgTypes...)>;
+ using CallbackType = std::function<void(ArgTypes...)>;
+
+ explicit CallbackValue(FunctionType fn);
+
+ // Creates a callback that forwards its arguments to `mFunction` and stores the result in
+ // `mReturnValue`.
+ /*implicit*/ operator CallbackType(); // NOLINT(google-explicit-constructor)
+
+ // Take the result of calling `mFunction`.
+ // Precondition: mReturnValue.has_value()
+ // Postcondition: !mReturnValue.has_value()
+ [[nodiscard]] ReturnType take();
+
+ private:
+ std::optional<ReturnType> mReturnValue;
+ FunctionType mFunction;
+};
+
+// Deduction guidelines for CallbackValue when constructed with a function pointer.
+template <typename ReturnType, typename... ArgTypes>
+CallbackValue(ReturnType (*)(ArgTypes...))->CallbackValue<ReturnType, ArgTypes...>;
+
+// Thread-safe container to pass a value between threads.
template <typename Type>
class TransferValue final {
public:
+ // Put the value in `TransferValue`. If `TransferValue` already has a value, this function is a
+ // no-op.
void put(Type object) const;
+
+ // Take the value stored in `TransferValue`. If no value is available, this function will block
+ // until the value becomes available.
+ // Postcondition: !mObject.has_value()
[[nodiscard]] Type take() const;
private:
@@ -38,7 +79,23 @@
mutable std::optional<Type> mObject GUARDED_BY(mMutex);
};
-// template implementation
+// template implementations
+
+template <typename ReturnType, typename... ArgTypes>
+CallbackValue<ReturnType, ArgTypes...>::CallbackValue(FunctionType fn) : mFunction(fn) {}
+
+template <typename ReturnType, typename... ArgTypes>
+CallbackValue<ReturnType, ArgTypes...>::operator CallbackType() {
+ return [this](ArgTypes... args) { mReturnValue = mFunction(args...); };
+}
+
+template <typename ReturnType, typename... ArgTypes>
+ReturnType CallbackValue<ReturnType, ArgTypes...>::take() {
+ CHECK(mReturnValue.has_value());
+ std::optional<ReturnType> object;
+ std::swap(object, mReturnValue);
+ return std::move(object).value();
+}
template <typename Type>
void TransferValue<Type>::put(Type object) const {
@@ -56,6 +113,7 @@
std::unique_lock lock(mMutex);
base::ScopedLockAssertion lockAssertion(mMutex);
mCondition.wait(lock, [this]() REQUIRES(mMutex) { return mObject.has_value(); });
+ CHECK(mObject.has_value());
std::optional<Type> object;
std::swap(object, mObject);
return std::move(object).value();
diff --git a/neuralnetworks/utils/common/src/ResilientBuffer.cpp b/neuralnetworks/utils/common/src/ResilientBuffer.cpp
index 984295b..cf5496a 100644
--- a/neuralnetworks/utils/common/src/ResilientBuffer.cpp
+++ b/neuralnetworks/utils/common/src/ResilientBuffer.cpp
@@ -36,7 +36,7 @@
return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
<< "utils::ResilientBuffer::create must have non-empty makeBuffer";
}
- auto buffer = NN_TRY(makeBuffer(/*blocking=*/true));
+ auto buffer = NN_TRY(makeBuffer());
CHECK(buffer != nullptr);
return std::make_shared<const ResilientBuffer>(PrivateConstructorTag{}, std::move(makeBuffer),
std::move(buffer));
diff --git a/neuralnetworks/utils/common/src/ResilientDevice.cpp b/neuralnetworks/utils/common/src/ResilientDevice.cpp
index 2f83c5c..6ad3fad 100644
--- a/neuralnetworks/utils/common/src/ResilientDevice.cpp
+++ b/neuralnetworks/utils/common/src/ResilientDevice.cpp
@@ -49,7 +49,17 @@
return result;
}
- device = resilientDevice.recover(device.get(), blocking);
+ // Attempt recovery and return if it fails.
+ auto maybeDevice = resilientDevice.recover(device.get(), blocking);
+ if (!maybeDevice.has_value()) {
+ const auto& [resultErrorMessage, resultErrorCode] = result.error();
+ const auto& [recoveryErrorMessage, recoveryErrorCode] = maybeDevice.error();
+ return nn::error(resultErrorCode)
+ << resultErrorMessage << ", and failed to recover dead device with error "
+ << recoveryErrorCode << ": " << recoveryErrorMessage;
+ }
+ device = std::move(maybeDevice).value();
+
return fn(*device);
}
@@ -94,7 +104,8 @@
return mDevice;
}
-nn::SharedDevice ResilientDevice::recover(const nn::IDevice* failingDevice, bool blocking) const {
+nn::GeneralResult<nn::SharedDevice> ResilientDevice::recover(const nn::IDevice* failingDevice,
+ bool blocking) const {
std::lock_guard guard(mMutex);
// Another caller updated the failing device.
@@ -102,13 +113,7 @@
return mDevice;
}
- auto maybeDevice = kMakeDevice(blocking);
- if (!maybeDevice.has_value()) {
- const auto& [message, code] = maybeDevice.error();
- LOG(ERROR) << "Failed to recover dead device with error " << code << ": " << message;
- return mDevice;
- }
- auto device = std::move(maybeDevice).value();
+ auto device = NN_TRY(kMakeDevice(blocking));
// If recovered device has different metadata than what is cached (i.e., because it was
// updated), mark the device as invalid and preserve the cached data.
@@ -176,11 +181,11 @@
nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const {
auto self = shared_from_this();
- ResilientPreparedModel::Factory makePreparedModel =
- [device = std::move(self), model, preference, priority, deadline, modelCache, dataCache,
- token](bool blocking) -> nn::GeneralResult<nn::SharedPreparedModel> {
- return device->prepareModelInternal(blocking, model, preference, priority, deadline,
- modelCache, dataCache, token);
+ ResilientPreparedModel::Factory makePreparedModel = [device = std::move(self), model,
+ preference, priority, deadline, modelCache,
+ dataCache, token] {
+ return device->prepareModelInternal(model, preference, priority, deadline, modelCache,
+ dataCache, token);
};
return ResilientPreparedModel::create(std::move(makePreparedModel));
}
@@ -189,11 +194,9 @@
nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const {
auto self = shared_from_this();
- ResilientPreparedModel::Factory makePreparedModel =
- [device = std::move(self), deadline, modelCache, dataCache,
- token](bool blocking) -> nn::GeneralResult<nn::SharedPreparedModel> {
- return device->prepareModelFromCacheInternal(blocking, deadline, modelCache, dataCache,
- token);
+ ResilientPreparedModel::Factory makePreparedModel = [device = std::move(self), deadline,
+ modelCache, dataCache, token] {
+ return device->prepareModelFromCacheInternal(deadline, modelCache, dataCache, token);
};
return ResilientPreparedModel::create(std::move(makePreparedModel));
}
@@ -203,10 +206,9 @@
const std::vector<nn::BufferRole>& inputRoles,
const std::vector<nn::BufferRole>& outputRoles) const {
auto self = shared_from_this();
- ResilientBuffer::Factory makeBuffer =
- [device = std::move(self), desc, preparedModels, inputRoles,
- outputRoles](bool blocking) -> nn::GeneralResult<nn::SharedBuffer> {
- return device->allocateInternal(blocking, desc, preparedModels, inputRoles, outputRoles);
+ ResilientBuffer::Factory makeBuffer = [device = std::move(self), desc, preparedModels,
+ inputRoles, outputRoles] {
+ return device->allocateInternal(desc, preparedModels, inputRoles, outputRoles);
};
return ResilientBuffer::create(std::move(makeBuffer));
}
@@ -217,9 +219,8 @@
}
nn::GeneralResult<nn::SharedPreparedModel> ResilientDevice::prepareModelInternal(
- bool blocking, const nn::Model& model, nn::ExecutionPreference preference,
- nn::Priority priority, nn::OptionalTimePoint deadline,
- const std::vector<nn::SharedHandle>& modelCache,
+ const nn::Model& model, nn::ExecutionPreference preference, nn::Priority priority,
+ nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const {
if (!isValidInternal()) {
return std::make_shared<const InvalidPreparedModel>();
@@ -229,12 +230,11 @@
return device.prepareModel(model, preference, priority, deadline, modelCache, dataCache,
token);
};
- return protect(*this, fn, blocking);
+ return protect(*this, fn, /*blocking=*/false);
}
nn::GeneralResult<nn::SharedPreparedModel> ResilientDevice::prepareModelFromCacheInternal(
- bool blocking, nn::OptionalTimePoint deadline,
- const std::vector<nn::SharedHandle>& modelCache,
+ nn::OptionalTimePoint deadline, const std::vector<nn::SharedHandle>& modelCache,
const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const {
if (!isValidInternal()) {
return std::make_shared<const InvalidPreparedModel>();
@@ -242,12 +242,11 @@
const auto fn = [deadline, &modelCache, &dataCache, token](const nn::IDevice& device) {
return device.prepareModelFromCache(deadline, modelCache, dataCache, token);
};
- return protect(*this, fn, blocking);
+ return protect(*this, fn, /*blocking=*/false);
}
nn::GeneralResult<nn::SharedBuffer> ResilientDevice::allocateInternal(
- bool blocking, const nn::BufferDesc& desc,
- const std::vector<nn::SharedPreparedModel>& preparedModels,
+ const nn::BufferDesc& desc, const std::vector<nn::SharedPreparedModel>& preparedModels,
const std::vector<nn::BufferRole>& inputRoles,
const std::vector<nn::BufferRole>& outputRoles) const {
if (!isValidInternal()) {
@@ -256,7 +255,7 @@
const auto fn = [&desc, &preparedModels, &inputRoles, &outputRoles](const nn::IDevice& device) {
return device.allocate(desc, preparedModels, inputRoles, outputRoles);
};
- return protect(*this, fn, blocking);
+ return protect(*this, fn, /*blocking=*/false);
}
} // namespace android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/utils/common/src/ResilientPreparedModel.cpp b/neuralnetworks/utils/common/src/ResilientPreparedModel.cpp
index 012a1de..b8acee1 100644
--- a/neuralnetworks/utils/common/src/ResilientPreparedModel.cpp
+++ b/neuralnetworks/utils/common/src/ResilientPreparedModel.cpp
@@ -36,7 +36,7 @@
return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
<< "utils::ResilientPreparedModel::create must have non-empty makePreparedModel";
}
- auto preparedModel = NN_TRY(makePreparedModel(/*blocking=*/true));
+ auto preparedModel = NN_TRY(makePreparedModel());
CHECK(preparedModel != nullptr);
return std::make_shared<ResilientPreparedModel>(
PrivateConstructorTag{}, std::move(makePreparedModel), std::move(preparedModel));
diff --git a/radio/1.6/IRadio.hal b/radio/1.6/IRadio.hal
index 3dc80b9..a398e7d 100644
--- a/radio/1.6/IRadio.hal
+++ b/radio/1.6/IRadio.hal
@@ -117,6 +117,9 @@
* @param pduSessionId The pdu session id to be used for this data call. A value of 0 means
* no pdu session id was attached to this call.
* Reference: 3GPP TS 24.007 section 11.2.3.1b
+ * @param sliceInfo SliceInfo to be used for the data connection when a handover occurs from
+ * EPDG to 5G. It is valid only when accessNetwork is AccessNetwork:NGRAN. If the slice
+ * passed from EPDG is rejected, then the data failure cause must be DataCallFailCause:SLICE_REJECTED.
*
* Response function is IRadioResponse.setupDataCallResponse_1_6()
*
@@ -125,7 +128,7 @@
oneway setupDataCall_1_6(int32_t serial, AccessNetwork accessNetwork,
DataProfileInfo dataProfileInfo, bool roamingAllowed,
DataRequestReason reason, vec<LinkAddress> addresses, vec<string> dnses,
- int32_t pduSessionId);
+ int32_t pduSessionId, OptionalSliceInfo sliceInfo);
/**
* Send an SMS message
diff --git a/radio/1.6/types.hal b/radio/1.6/types.hal
index f4dc0bd..550e079 100644
--- a/radio/1.6/types.hal
+++ b/radio/1.6/types.hal
@@ -352,6 +352,12 @@
* Reference: 3GPP TS 24.007 section 11.2.3.1b
*/
int32_t pduSessionId;
+
+ /**
+ * Slice used for this data call. It is valid only when this data call is on
+ * AccessNetwork:NGRAN.
+ */
+ OptionalSliceInfo sliceInfo;
};
/**
@@ -405,7 +411,8 @@
* This bandwidth estimate shall be the estimated maximum sustainable link bandwidth
* (as would be measured at the Upper PDCP or SNDCP SAP). This is valid only
* in if device is connected to both primary and secodary in dual connected
- * mode. This must be filled with -1 if secondary is not connected.
+ * mode. This must be filled with -1 if secondary is not connected or if
+ * modem does not support this feature.
*/
uint32_t secondaryDownlinkCapacityKbps;
@@ -414,7 +421,8 @@
* This bandwidth estimate shall be the estimated
* maximum sustainable link bandwidth (as would be measured at the Upper PDCP or SNDCP SAP).
* This is valid only in if device is connected to both primary and secodary in dual connected
- * mode.This must be filled with -1 if secondary is not connected.
+ * mode.This must be filled with -1 if secondary is not connected or if modem
+ * does not support this feature.
*/
uint32_t secondaryUplinkCapacityKbps;
};
@@ -733,3 +741,80 @@
*/
string forwardedNumber;
};
+
+/**
+ * This safe_union represents an optional slice info
+ */
+safe_union OptionalSliceInfo {
+ Monostate noinit;
+ SliceInfo value;
+};
+
+/**
+ * This struct represents a S-NSSAI as defined in 3GPP TS 24.501.
+ */
+struct SliceInfo {
+ /**
+ * The type of service provided by the slice.
+ *
+ * see: 3GPP TS 24.501 Section 9.11.2.8.
+ */
+ SliceServiceType sst;
+
+ /**
+ * Slice differentiator is the identifier of a slice that has
+ * SliceServiceType as SST. A value of -1 indicates that there is
+ * no corresponding SliceInfo of the HPLMN.
+ *
+ * see: 3GPP TS 24.501 Section 9.11.2.8.
+ */
+ int32_t sliceDifferentiator;
+
+ /**
+ * This SST corresponds to a SliceInfo (S-NSSAI) of the HPLMN; the SST is
+ * mapped to this value.
+ *
+ * see: 3GPP TS 24.501 Section 9.11.2.8.
+ */
+ SliceServiceType mappedHplmnSst;
+
+ /**
+ * Present only if both sliceDifferentiator and mappedHplmnSst are also
+ * present. This SD corresponds to a SliceInfo (S-NSSAI) of the HPLMN;
+ * sliceDifferentiator is mapped to this value. A value of -1 indicates that
+ * there is no corresponding SliceInfo of the HPLMN.
+ *
+ * see: 3GPP TS 24.501 Section 9.11.2.8.
+ */
+ int32_t mappedHplmnSD;
+};
+
+/**
+ * Slice/Service Type as defined in 3GPP TS 23.501.
+ */
+enum SliceServiceType : uint8_t {
+ /* Not specified */
+ NONE = 0,
+
+ /* Slice suitable for the handling of 5G enhanced Mobile Broadband */
+ EMBB = 1,
+
+ /**
+ * Slice suitable for the handling of ultra-reliable low latency
+ * communications
+ */
+ URLLC = 2,
+
+ /* Slice suitable for the handling of massive IoT */
+ MIOT = 3,
+};
+
+/**
+ * Expose more setup data call failures.
+ */
+enum DataCallFailCause : @1.4::DataCallFailCause {
+ /**
+ * Data call fail due to the slice not being allowed for the data call.
+ */
+ SLICE_REJECTED = 0x8CC,
+};
diff --git a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
index 47babed..8b87292 100644
--- a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
@@ -56,8 +56,12 @@
::android::hardware::radio::V1_2::DataRequestReason reason =
::android::hardware::radio::V1_2::DataRequestReason::NORMAL;
- Return<void> res = radio_v1_6->setupDataCall_1_6(serial, accessNetwork, dataProfileInfo,
- roamingAllowed, reason, addresses, dnses, -1);
+ ::android::hardware::radio::V1_6::OptionalSliceInfo optionalSliceInfo;
+ memset(&optionalSliceInfo, 0, sizeof(optionalSliceInfo));
+
+ Return<void> res =
+ radio_v1_6->setupDataCall_1_6(serial, accessNetwork, dataProfileInfo, roamingAllowed,
+ reason, addresses, dnses, -1, optionalSliceInfo);
ASSERT_OK(res);
EXPECT_EQ(std::cv_status::no_timeout, wait());
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameter.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameter.aidl
index 91f83e4..4985768 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameter.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameter.aidl
@@ -16,11 +16,8 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.security.keymint;
-@VintfStability
+@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
parcelable KeyParameter {
android.hardware.security.keymint.Tag tag;
- boolean boolValue;
- int integer;
- long longInteger;
- byte[] blob;
+ android.hardware.security.keymint.KeyParameterValue value;
}
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameterValue.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameterValue.aidl
new file mode 100644
index 0000000..ecf20ad
--- /dev/null
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/KeyParameterValue.aidl
@@ -0,0 +1,36 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.security.keymint;
+@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
+union KeyParameterValue {
+ int invalid;
+ android.hardware.security.keymint.Algorithm algorithm;
+ android.hardware.security.keymint.BlockMode blockMode;
+ android.hardware.security.keymint.PaddingMode paddingMode;
+ android.hardware.security.keymint.Digest digest;
+ android.hardware.security.keymint.EcCurve ecCurve;
+ android.hardware.security.keymint.KeyOrigin origin;
+ android.hardware.security.keymint.KeyPurpose keyPurpose;
+ android.hardware.security.keymint.HardwareAuthenticatorType hardwareAuthenticatorType;
+ android.hardware.security.keymint.SecurityLevel securityLevel;
+ boolean boolValue;
+ int integer;
+ long longInteger;
+ long dateTime;
+ byte[] blob;
+}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyDerivationFunction.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyDerivationFunction.aidl
deleted file mode 100644
index e166ab6..0000000
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyDerivationFunction.aidl
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.security.keymint;
-
-/**
- * Key derivation functions, mostly used in ECIES.
- */
-@VintfStability
-@Backing(type="int")
-enum KeyDerivationFunction {
- /** Do not apply a key derivation function; use the raw agreed key */
- NONE = 0,
- /** HKDF defined in RFC 5869 with SHA256 */
- RFC5869_SHA256 = 1,
- /** KDF1 defined in ISO 18033-2 with SHA1 */
- ISO18033_2_KDF1_SHA1 = 2,
- /** KDF1 defined in ISO 18033-2 with SHA256 */
- ISO18033_2_KDF1_SHA256 = 3,
- /** KDF2 defined in ISO 18033-2 with SHA1 */
- ISO18033_2_KDF2_SHA1 = 4,
- /** KDF2 defined in ISO 18033-2 with SHA256 */
- ISO18033_2_KDF2_SHA256 = 5,
-}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyParameter.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyParameter.aidl
index 938064c..f3ed96b 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyParameter.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyParameter.aidl
@@ -16,40 +16,16 @@
package android.hardware.security.keymint;
-import android.hardware.security.keymint.Algorithm;
-import android.hardware.security.keymint.BlockMode;
-import android.hardware.security.keymint.Digest;
-import android.hardware.security.keymint.EcCurve;
-import android.hardware.security.keymint.HardwareAuthenticatorType;
-import android.hardware.security.keymint.KeyDerivationFunction;
-import android.hardware.security.keymint.KeyOrigin;
-import android.hardware.security.keymint.KeyPurpose;
-import android.hardware.security.keymint.PaddingMode;
-import android.hardware.security.keymint.SecurityLevel;
import android.hardware.security.keymint.Tag;
-
+import android.hardware.security.keymint.KeyParameterValue;
/**
* Identifies the key authorization parameters to be used with keyMint. This is usually
* provided as an array of KeyParameters to IKeyMintDevice or Operation.
- *
- * TODO(seleneh): Union was not supported in aidl when this cl is first drafted. So we just had
- * the Tags, and bool, int, long, int[], and we will cast to the appropate types base on the
- * Tag value. We need to update this defination to distingish Algorithm, BlockMode,
- * PaddingMode, KeyOrigin...etc later, as union support is recently added to aidl.
- * b/173253030
*/
@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
parcelable KeyParameter {
- /**
- * Identify what type of key parameter this parcelable actually holds, and based on the type
- * of tag is int, long, bool, or byte[], one of the fields below will be referenced.
- */
Tag tag;
-
- boolean boolValue;
- int integer;
- long longInteger;
- // TODO: change this to nullable.
- byte[] blob;
+ KeyParameterValue value;
}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyParameterValue.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyParameterValue.aidl
new file mode 100644
index 0000000..a4f5154
--- /dev/null
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyParameterValue.aidl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.keymint;
+
+import android.hardware.security.keymint.Algorithm;
+import android.hardware.security.keymint.BlockMode;
+import android.hardware.security.keymint.Digest;
+import android.hardware.security.keymint.EcCurve;
+import android.hardware.security.keymint.HardwareAuthenticatorType;
+import android.hardware.security.keymint.KeyOrigin;
+import android.hardware.security.keymint.KeyPurpose;
+import android.hardware.security.keymint.PaddingMode;
+import android.hardware.security.keymint.SecurityLevel;
+
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
+union KeyParameterValue {
+
+ /* Represents an invalid value type. */
+ int invalid;
+
+ /* Enum types */
+ Algorithm algorithm;
+ BlockMode blockMode;
+ PaddingMode paddingMode;
+ Digest digest;
+ EcCurve ecCurve;
+ KeyOrigin origin;
+ KeyPurpose keyPurpose;
+ HardwareAuthenticatorType hardwareAuthenticatorType;
+ SecurityLevel securityLevel;
+
+ /* Other types */
+ boolean boolValue; // Always true, if present.
+ int integer;
+ long longInteger;
+ long dateTime;
+
+ byte[] blob;
+}
diff --git a/security/keymint/aidl/vts/functional/AndroidTest.xml b/security/keymint/aidl/vts/functional/AndroidTest.xml
index 43e7a8a..de543f1 100644
--- a/security/keymint/aidl/vts/functional/AndroidTest.xml
+++ b/security/keymint/aidl/vts/functional/AndroidTest.xml
@@ -13,7 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<configuration description="Runs VtsAidlKeyMintV1_0TargetTest.">
+<configuration description="Runs VtsAidlKeyMintTargetTest.">
<option name="test-suite-tag" value="apct" />
<option name="test-suite-tag" value="apct-native" />
@@ -22,12 +22,13 @@
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
- <option name="push" value="VtsAidlKeyMintV1_0TargetTest->/data/local/tmp/VtsAidlKeyMintV1_0TargetTest" />
+ <option name="push"
+ value="VtsAidlKeyMintTargetTest->/data/local/tmp/VtsAidlKeyMintTargetTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
- <option name="module-name" value="VtsAidlKeyMintV1_0TargetTest" />
+ <option name="module-name" value="VtsAidlKeyMintTargetTest" />
<option name="native-test-timeout" value="900000"/>
</test>
</configuration>
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 9ba4099..94bc199 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -577,8 +577,8 @@
string ciphertext = EncryptMessage(message, params, &out_params);
EXPECT_EQ(1U, out_params.size());
auto ivVal = out_params.GetTagValue(TAG_NONCE);
- EXPECT_TRUE(ivVal.isOk());
- if (ivVal.isOk()) *iv_out = ivVal.value();
+ EXPECT_TRUE(ivVal);
+ if (ivVal) *iv_out = *ivVal;
return ciphertext;
}
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index 6e38539..3060153 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -80,7 +80,10 @@
template <TagType tag_type, Tag tag, typename ValueT>
bool contains(vector<KeyParameter>& set, TypedTag<tag_type, tag> ttag, ValueT expected_value) {
auto it = std::find_if(set.begin(), set.end(), [&](const KeyParameter& param) {
- return param.tag == tag && accessTagValue(ttag, param) == expected_value;
+ if (auto p = authorizationValue(ttag, param)) {
+ return *p == expected_value;
+ }
+ return false;
});
return (it != set.end());
}
@@ -251,10 +254,10 @@
EXPECT_TRUE(auths.Contains(TAG_OS_VERSION, os_version()))
<< "OS version is " << os_version() << " key reported "
- << auths.GetTagValue(TAG_OS_VERSION);
+ << auths.GetTagValue(TAG_OS_VERSION)->get();
EXPECT_TRUE(auths.Contains(TAG_OS_PATCHLEVEL, os_patch_level()))
<< "OS patch level is " << os_patch_level() << " key reported "
- << auths.GetTagValue(TAG_OS_PATCHLEVEL);
+ << auths.GetTagValue(TAG_OS_PATCHLEVEL)->get();
}
};
@@ -2333,8 +2336,8 @@
vector<uint8_t> CopyIv(const AuthorizationSet& set) {
auto iv = set.GetTagValue(TAG_NONCE);
- EXPECT_TRUE(iv.isOk());
- return iv.value();
+ EXPECT_TRUE(iv);
+ return iv->get();
}
/*
@@ -2459,13 +2462,13 @@
case BlockMode::CBC:
case BlockMode::GCM:
case BlockMode::CTR:
- ASSERT_TRUE(iv.isOk()) << "No IV for block mode " << block_mode;
- EXPECT_EQ(block_mode == BlockMode::GCM ? 12U : 16U, iv.value().size());
- params.push_back(TAG_NONCE, iv.value());
+ ASSERT_TRUE(iv) << "No IV for block mode " << block_mode;
+ EXPECT_EQ(block_mode == BlockMode::GCM ? 12U : 16U, iv->get().size());
+ params.push_back(TAG_NONCE, iv->get());
break;
case BlockMode::ECB:
- EXPECT_FALSE(iv.isOk()) << "ECB mode should not generate IV";
+ EXPECT_FALSE(iv) << "ECB mode should not generate IV";
break;
}
@@ -2649,9 +2652,9 @@
AuthorizationSet out_params;
string ciphertext = EncryptMessage(message, params, &out_params);
EXPECT_EQ(message.size(), ciphertext.size());
- EXPECT_EQ(16U, out_params.GetTagValue(TAG_NONCE).value().size());
+ EXPECT_EQ(16U, out_params.GetTagValue(TAG_NONCE)->get().size());
- params.push_back(TAG_NONCE, out_params.GetTagValue(TAG_NONCE).value());
+ params.push_back(TAG_NONCE, out_params.GetTagValue(TAG_NONCE)->get());
string plaintext = DecryptMessage(ciphertext, params);
EXPECT_EQ(message, plaintext);
@@ -2697,9 +2700,9 @@
AuthorizationSet out_params;
string ciphertext = EncryptMessage(message, params, &out_params);
EXPECT_EQ(message.size(), ciphertext.size());
- EXPECT_EQ(16U, out_params.GetTagValue(TAG_NONCE).value().size());
+ EXPECT_EQ(16U, out_params.GetTagValue(TAG_NONCE)->get().size());
- params.push_back(TAG_NONCE, out_params.GetTagValue(TAG_NONCE).value());
+ params.push_back(TAG_NONCE, out_params.GetTagValue(TAG_NONCE)->get());
string plaintext = DecryptMessage(ciphertext, params);
EXPECT_EQ(message, plaintext);
@@ -2893,7 +2896,7 @@
AuthorizationSet begin_out_params;
EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &begin_out_params));
EXPECT_EQ(1U, begin_out_params.size());
- ASSERT_TRUE(begin_out_params.GetTagValue(TAG_NONCE).isOk());
+ ASSERT_TRUE(begin_out_params.GetTagValue(TAG_NONCE));
AuthorizationSet finish_out_params;
string ciphertext;
diff --git a/security/keymint/support/authorization_set.cpp b/security/keymint/support/authorization_set.cpp
index 37b6cd1..f98851c 100644
--- a/security/keymint/support/authorization_set.cpp
+++ b/security/keymint/support/authorization_set.cpp
@@ -106,10 +106,11 @@
return false;
}
-NullOr<const KeyParameter&> AuthorizationSet::GetEntry(Tag tag) const {
+std::optional<std::reference_wrapper<const KeyParameter>> AuthorizationSet::GetEntry(
+ Tag tag) const {
int pos = find(tag);
if (pos == -1) return {};
- return data_[pos];
+ return std::reference_wrapper(data_[pos]);
}
AuthorizationSetBuilder& AuthorizationSetBuilder::RsaKey(uint32_t key_size,
diff --git a/security/keymint/support/include/keymint_support/authorization_set.h b/security/keymint/support/include/keymint_support/authorization_set.h
index c85f305..4ff1705 100644
--- a/security/keymint/support/include/keymint_support/authorization_set.h
+++ b/security/keymint/support/include/keymint_support/authorization_set.h
@@ -168,7 +168,7 @@
bool Contains(TypedTag<tag_type, tag> ttag, const ValueT& value) const {
for (const auto& param : data_) {
auto entry = authorizationValue(ttag, param);
- if (entry.isOk() && static_cast<ValueT>(entry.value()) == value) return true;
+ if (entry && static_cast<ValueT>(*entry) == value) return true;
}
return false;
}
@@ -178,9 +178,9 @@
size_t GetTagCount(Tag tag) const;
template <typename T>
- inline NullOr<const typename TypedTag2ValueType<T>::type&> GetTagValue(T tag) const {
+ inline auto GetTagValue(T tag) const -> decltype(authorizationValue(tag, KeyParameter())) {
auto entry = GetEntry(tag);
- if (entry.isOk()) return authorizationValue(tag, entry.value());
+ if (entry) return authorizationValue(tag, *entry);
return {};
}
@@ -219,7 +219,7 @@
}
private:
- NullOr<const KeyParameter&> GetEntry(Tag tag) const;
+ std::optional<std::reference_wrapper<const KeyParameter>> GetEntry(Tag tag) const;
std::vector<KeyParameter> data_;
};
diff --git a/security/keymint/support/include/keymint_support/key_param_output.h b/security/keymint/support/include/keymint_support/key_param_output.h
index 6e0e35d..5f004fe 100644
--- a/security/keymint/support/include/keymint_support/key_param_output.h
+++ b/security/keymint/support/include/keymint_support/key_param_output.h
@@ -71,7 +71,7 @@
}
template <typename ValueT>
-::std::ostream& operator<<(::std::ostream& os, const NullOr<ValueT>& value) {
+::std::ostream& operator<<(::std::ostream& os, const std::optional<ValueT>& value) {
if (!value.isOk()) {
os << "(value not present)";
} else {
diff --git a/security/keymint/support/include/keymint_support/keymint_tags.h b/security/keymint/support/include/keymint_support/keymint_tags.h
index 4e3d7ff..d932b40 100644
--- a/security/keymint/support/include/keymint_support/keymint_tags.h
+++ b/security/keymint/support/include/keymint_support/keymint_tags.h
@@ -58,6 +58,10 @@
typedef TypedTag<typeFromTag(tag), tag> type;
};
+#ifdef DECLARE_TYPED_TAG
+#undef DECLARE_TYPED_TAG
+#endif
+
#define DECLARE_TYPED_TAG(name) \
typedef typename Tag2TypedTag<Tag::name>::type TAG_##name##_t; \
static TAG_##name##_t TAG_##name;
@@ -72,9 +76,12 @@
DECLARE_TYPED_TAG(ATTESTATION_CHALLENGE);
DECLARE_TYPED_TAG(ATTESTATION_ID_BRAND);
DECLARE_TYPED_TAG(ATTESTATION_ID_DEVICE);
-DECLARE_TYPED_TAG(ATTESTATION_ID_PRODUCT);
+DECLARE_TYPED_TAG(ATTESTATION_ID_IMEI);
DECLARE_TYPED_TAG(ATTESTATION_ID_MANUFACTURER);
+DECLARE_TYPED_TAG(ATTESTATION_ID_MEID);
+DECLARE_TYPED_TAG(ATTESTATION_ID_PRODUCT);
DECLARE_TYPED_TAG(ATTESTATION_ID_MODEL);
+DECLARE_TYPED_TAG(ATTESTATION_ID_SERIAL);
DECLARE_TYPED_TAG(AUTH_TIMEOUT);
DECLARE_TYPED_TAG(BLOCK_MODE);
DECLARE_TYPED_TAG(BOOTLOADER_ONLY);
@@ -118,6 +125,8 @@
DECLARE_TYPED_TAG(USER_SECURE_ID);
DECLARE_TYPED_TAG(VENDOR_PATCHLEVEL);
+#undef DECLARE_TYPED_TAG
+
template <typename... Elems>
struct MetaList {};
@@ -133,6 +142,7 @@
TAG_OS_VERSION_t, TAG_OS_PATCHLEVEL_t, TAG_UNIQUE_ID_t, TAG_ATTESTATION_CHALLENGE_t,
TAG_ATTESTATION_APPLICATION_ID_t, TAG_ATTESTATION_ID_BRAND_t, TAG_ATTESTATION_ID_DEVICE_t,
TAG_ATTESTATION_ID_PRODUCT_t, TAG_ATTESTATION_ID_MANUFACTURER_t, TAG_ATTESTATION_ID_MODEL_t,
+ TAG_ATTESTATION_ID_SERIAL_t, TAG_ATTESTATION_ID_IMEI_t, TAG_ATTESTATION_ID_MEID_t,
TAG_RESET_SINCE_ID_ROTATION_t, TAG_PURPOSE_t, TAG_ALGORITHM_t, TAG_BLOCK_MODE_t,
TAG_DIGEST_t, TAG_PADDING_t, TAG_ORIGIN_t, TAG_USER_AUTH_TYPE_t, TAG_EC_CURVE_t,
TAG_BOOT_PATCHLEVEL_t, TAG_VENDOR_PATCHLEVEL_t, TAG_TRUSTED_CONFIRMATION_REQUIRED_t,
@@ -141,72 +151,121 @@
template <typename TypedTagType>
struct TypedTag2ValueType;
-#define MAKE_TAG_VALUE_ACCESSOR(tag_type, field_name) \
- template <Tag tag> \
- struct TypedTag2ValueType<TypedTag<tag_type, tag>> { \
- typedef decltype(static_cast<KeyParameter*>(nullptr)->field_name) type; \
- }; \
- template <Tag tag> \
- inline auto accessTagValue(TypedTag<tag_type, tag>, const KeyParameter& param) \
- ->const decltype(param.field_name)& { \
- return param.field_name; \
- } \
- template <Tag tag> \
- inline auto accessTagValue(TypedTag<tag_type, tag>, KeyParameter& param) \
- ->decltype(param.field_name)& { \
- return param.field_name; \
+#ifdef MAKE_TAG_VALUE_ACCESSOR
+#undef MAKE_TAG_VALUE_ACCESSOR
+#endif
+
+#define MAKE_TAG_VALUE_ACCESSOR(tag_type, field_name) \
+ template <Tag tag> \
+ struct TypedTag2ValueType<TypedTag<tag_type, tag>> { \
+ using type = std::remove_reference< \
+ decltype(static_cast<KeyParameterValue*>(nullptr) \
+ ->get<KeyParameterValue::field_name>())>::type; \
+ static constexpr KeyParameterValue::Tag unionTag = KeyParameterValue::field_name; \
+ }; \
+ template <Tag tag> \
+ inline std::optional<std::reference_wrapper< \
+ const typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type>> \
+ accessTagValue(TypedTag<tag_type, tag>, const KeyParameter& param) { \
+ if (param.value.getTag() == KeyParameterValue::field_name) { \
+ return std::optional( \
+ std::reference_wrapper(param.value.get<KeyParameterValue::field_name>())); \
+ } else { \
+ return std::nullopt; \
+ } \
+ } \
+ template <Tag tag> \
+ inline std::optional< \
+ std::reference_wrapper<typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type>> \
+ accessTagValue(TypedTag<tag_type, tag>, KeyParameter& param) { \
+ if (param.value.getTag() == KeyParameterValue::field_name) { \
+ return std::optional( \
+ std::reference_wrapper(param.value.get<KeyParameterValue::field_name>())); \
+ } else { \
+ return std::nullopt; \
+ } \
}
MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG, longInteger)
MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG_REP, longInteger)
-MAKE_TAG_VALUE_ACCESSOR(TagType::DATE, longInteger)
+MAKE_TAG_VALUE_ACCESSOR(TagType::DATE, dateTime)
MAKE_TAG_VALUE_ACCESSOR(TagType::UINT, integer)
MAKE_TAG_VALUE_ACCESSOR(TagType::UINT_REP, integer)
MAKE_TAG_VALUE_ACCESSOR(TagType::BOOL, boolValue)
MAKE_TAG_VALUE_ACCESSOR(TagType::BYTES, blob)
MAKE_TAG_VALUE_ACCESSOR(TagType::BIGNUM, blob)
-// TODO(seleneh) change these MAKE_TAG_ENUM_VALUE_ACCESSOR back to the 2 parameter
-// version when aidl supports union
-#define MAKE_TAG_ENUM_VALUE_ACCESSOR(typed_tag, field_name, field_type) \
- template <> \
- struct TypedTag2ValueType<decltype(typed_tag)> { \
- typedef field_type type; \
- }; \
- inline auto accessTagValue(decltype(typed_tag), const KeyParameter& param) \
- ->const field_type& { \
- return *reinterpret_cast<const field_type*>(¶m.field_name); \
- } \
- inline auto accessTagValue(decltype(typed_tag), KeyParameter& param)->field_type& { \
- return *reinterpret_cast<field_type*>(¶m.field_name); \
+#undef MAKE_TAG_VALUE_ACCESSOR
+
+#ifdef MAKE_TAG_ENUM_VALUE_ACCESSOR
+#undef MAKE_TAG_ENUM_VALUE_ACCESSOR
+#endif
+
+#define MAKE_TAG_ENUM_VALUE_ACCESSOR(typed_tag, field_name) \
+ template <> \
+ struct TypedTag2ValueType<decltype(typed_tag)> { \
+ using type = std::remove_reference< \
+ decltype(static_cast<KeyParameterValue*>(nullptr) \
+ ->get<KeyParameterValue::field_name>())>::type; \
+ static constexpr KeyParameterValue::Tag unionTag = KeyParameterValue::field_name; \
+ }; \
+ inline std::optional< \
+ std::reference_wrapper<const typename TypedTag2ValueType<decltype(typed_tag)>::type>> \
+ accessTagValue(decltype(typed_tag), const KeyParameter& param) { \
+ if (param.value.getTag() == KeyParameterValue::field_name) { \
+ return std::optional( \
+ std::reference_wrapper(param.value.get<KeyParameterValue::field_name>())); \
+ } else { \
+ return std::nullopt; \
+ } \
+ } \
+ inline std::optional< \
+ std::reference_wrapper<typename TypedTag2ValueType<decltype(typed_tag)>::type>> \
+ accessTagValue(decltype(typed_tag), KeyParameter& param) { \
+ if (param.value.getTag() == KeyParameterValue::field_name) { \
+ return std::optional( \
+ std::reference_wrapper(param.value.get<KeyParameterValue::field_name>())); \
+ } else { \
+ return std::nullopt; \
+ } \
}
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ALGORITHM, integer, Algorithm)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_BLOCK_MODE, integer, BlockMode)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_DIGEST, integer, Digest)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_EC_CURVE, integer, EcCurve)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ORIGIN, integer, KeyOrigin)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PADDING, integer, PaddingMode)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PURPOSE, integer, KeyPurpose)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_USER_AUTH_TYPE, integer, HardwareAuthenticatorType)
-MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_HARDWARE_TYPE, integer, SecurityLevel)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ALGORITHM, algorithm)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_BLOCK_MODE, blockMode)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_DIGEST, digest)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_EC_CURVE, ecCurve)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ORIGIN, origin)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PADDING, paddingMode)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PURPOSE, keyPurpose)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_USER_AUTH_TYPE, hardwareAuthenticatorType)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_HARDWARE_TYPE, securityLevel)
+
+#undef MAKE_TAG_ENUM_VALUE_ACCESSOR
template <TagType tag_type, Tag tag, typename ValueT>
inline KeyParameter makeKeyParameter(TypedTag<tag_type, tag> ttag, ValueT&& value) {
- KeyParameter param;
- param.tag = tag;
- param.longInteger = 0;
- accessTagValue(ttag, param) = std::forward<ValueT>(value);
- return param;
+ KeyParameter retval;
+ retval.tag = tag;
+ retval.value = KeyParameterValue::make<TypedTag2ValueType<decltype(ttag)>::unionTag>(
+ std::forward<ValueT>(value));
+ return retval;
}
// the boolean case
template <Tag tag>
inline KeyParameter makeKeyParameter(TypedTag<TagType::BOOL, tag>) {
- KeyParameter param;
- param.tag = tag;
- param.boolValue = true;
- return param;
+ KeyParameter retval;
+ retval.tag = tag;
+ retval.value = KeyParameterValue::make<KeyParameterValue::boolValue>(true);
+ return retval;
+}
+
+// the invalid case
+inline KeyParameter makeKeyParameter(TypedTag<TagType::INVALID, Tag::INVALID>) {
+ KeyParameter retval;
+ retval.tag = Tag::INVALID;
+ retval.value = KeyParameterValue::make<KeyParameterValue::invalid>(0);
+ return retval;
}
template <typename... Pack>
@@ -239,89 +298,32 @@
return makeKeyParameter(ttag, std::forward<Args>(args)...);
}
-/**
- * This class wraps a (mostly return) value and stores whether or not the wrapped value is valid out
- * of band. Note that if the wrapped value is a reference it is unsafe to access the value if
- * !isOk(). If the wrapped type is a pointer or value and !isOk(), it is still safe to access the
- * wrapped value. In this case the pointer will be NULL though, and the value will be default
- * constructed.
- *
- * TODO(seleneh) replace this with std::optional.
- */
-template <typename ValueT>
-class NullOr {
- using internal_t = std::conditional_t<std::is_lvalue_reference<ValueT>::value,
- std::remove_reference_t<ValueT>*, ValueT>;
-
- struct pointer_initializer {
- static std::nullptr_t init() { return nullptr; }
- };
- struct value_initializer {
- static ValueT init() { return ValueT(); }
- };
- struct value_pointer_deref_t {
- static ValueT& deref(ValueT& v) { return v; }
- };
- struct reference_deref_t {
- static auto& deref(internal_t v) { return *v; }
- };
- using initializer_t = std::conditional_t<std::is_lvalue_reference<ValueT>::value ||
- std::is_pointer<ValueT>::value,
- pointer_initializer, value_initializer>;
- using deref_t = std::conditional_t<std::is_lvalue_reference<ValueT>::value, reference_deref_t,
- value_pointer_deref_t>;
-
- public:
- NullOr() : value_(initializer_t::init()), null_(true) {}
- template <typename T>
- NullOr(T&& value, typename std::enable_if<
- !std::is_lvalue_reference<ValueT>::value &&
- std::is_same<std::decay_t<ValueT>, std::decay_t<T>>::value,
- int>::type = 0)
- : value_(std::forward<ValueT>(value)), null_(false) {}
- template <typename T>
- NullOr(T& value, typename std::enable_if<
- std::is_lvalue_reference<ValueT>::value &&
- std::is_same<std::decay_t<ValueT>, std::decay_t<T>>::value,
- int>::type = 0)
- : value_(&value), null_(false) {}
-
- bool isOk() const { return !null_; }
-
- const ValueT& value() const& { return deref_t::deref(value_); }
- ValueT& value() & { return deref_t::deref(value_); }
- ValueT&& value() && { return std::move(deref_t::deref(value_)); }
-
- private:
- internal_t value_;
- bool null_;
-};
-
template <typename T>
std::remove_reference_t<T> NullOrOr(T&& v) {
- if (v.isOk()) return v;
+ if (v) return v;
return {};
}
template <typename Head, typename... Tail>
std::remove_reference_t<Head> NullOrOr(Head&& head, Tail&&... tail) {
- if (head.isOk()) return head;
+ if (head) return head;
return NullOrOr(std::forward<Tail>(tail)...);
}
template <typename Default, typename Wrapped>
-std::remove_reference_t<Wrapped> defaultOr(NullOr<Wrapped>&& optional, Default&& def) {
+std::remove_reference_t<Wrapped> defaultOr(std::optional<Wrapped>&& optional, Default&& def) {
static_assert(std::is_convertible<std::remove_reference_t<Default>,
std::remove_reference_t<Wrapped>>::value,
- "Type of default value must match the type wrapped by NullOr");
- if (optional.isOk()) return optional.value();
+ "Type of default value must match the type wrapped by std::optional");
+ if (optional) return *optional;
return def;
}
template <TagType tag_type, Tag tag>
-inline NullOr<const typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type&> authorizationValue(
- TypedTag<tag_type, tag> ttag, const KeyParameter& param) {
- if (tag != param.tag) return {};
+inline std::optional<
+ std::reference_wrapper<const typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type>>
+authorizationValue(TypedTag<tag_type, tag> ttag, const KeyParameter& param) {
+ if (TypedTag2ValueType<TypedTag<tag_type, tag>>::unionTag != param.value.getTag()) return {};
return accessTagValue(ttag, param);
}
diff --git a/security/keymint/support/key_param_output.cpp b/security/keymint/support/key_param_output.cpp
index c56e035..0950eb6 100644
--- a/security/keymint/support/key_param_output.cpp
+++ b/security/keymint/support/key_param_output.cpp
@@ -35,38 +35,8 @@
return os;
}
-// TODO(seleneh) update this to a parsing that looks at each tags individually
-// such as ALGORITHM BLOCK_MODE when aidl union support is added.
ostream& operator<<(ostream& os, const KeyParameter& param) {
- os << param.tag << ": ";
- switch (typeFromTag(param.tag)) {
- case TagType::INVALID:
- return os << " Invalid";
- case TagType::ENUM_REP:
- case TagType::ENUM:
- case TagType::UINT_REP:
- case TagType::UINT:
- return os << param.integer;
- case TagType::ULONG_REP:
- case TagType::ULONG:
- case TagType::DATE:
- return os << param.longInteger;
- case TagType::BOOL:
- return os << "true";
- case TagType::BIGNUM:
- os << " Bignum: ";
- for (size_t i = 0; i < param.blob.size(); ++i) {
- os << std::hex << ::std::setw(2) << static_cast<int>(param.blob[i]) << ::std::dec;
- }
- return os;
- case TagType::BYTES:
- os << " Bytes: ";
- for (size_t i = 0; i < param.blob.size(); ++i) {
- os << ::std::hex << ::std::setw(2) << static_cast<int>(param.blob[i]) << ::std::dec;
- }
- return os;
- }
- return os << "UNKNOWN TAG TYPE!";
+ return os << param.toString();
}
} // namespace aidl::android::hardware::security::keymint
diff --git a/wifi/1.5/default/wifi_legacy_hal.cpp b/wifi/1.5/default/wifi_legacy_hal.cpp
index 773dd9b..e1a5a8c 100644
--- a/wifi/1.5/default/wifi_legacy_hal.cpp
+++ b/wifi/1.5/default/wifi_legacy_hal.cpp
@@ -343,6 +343,43 @@
on_nan_event_schedule_update_user_callback(*event);
}
}
+
+// Callbacks for the various TWT operations.
+std::function<void(const TwtSetupResponse&)>
+ on_twt_event_setup_response_callback;
+void onAsyncTwtEventSetupResponse(TwtSetupResponse* event) {
+ const auto lock = hidl_sync_util::acquireGlobalLock();
+ if (on_twt_event_setup_response_callback && event) {
+ on_twt_event_setup_response_callback(*event);
+ }
+}
+
+std::function<void(const TwtTeardownCompletion&)>
+ on_twt_event_teardown_completion_callback;
+void onAsyncTwtEventTeardownCompletion(TwtTeardownCompletion* event) {
+ const auto lock = hidl_sync_util::acquireGlobalLock();
+ if (on_twt_event_teardown_completion_callback && event) {
+ on_twt_event_teardown_completion_callback(*event);
+ }
+}
+
+std::function<void(const TwtInfoFrameReceived&)>
+ on_twt_event_info_frame_received_callback;
+void onAsyncTwtEventInfoFrameReceived(TwtInfoFrameReceived* event) {
+ const auto lock = hidl_sync_util::acquireGlobalLock();
+ if (on_twt_event_info_frame_received_callback && event) {
+ on_twt_event_info_frame_received_callback(*event);
+ }
+}
+
+std::function<void(const TwtDeviceNotify&)> on_twt_event_device_notify_callback;
+void onAsyncTwtEventDeviceNotify(TwtDeviceNotify* event) {
+ const auto lock = hidl_sync_util::acquireGlobalLock();
+ if (on_twt_event_device_notify_callback && event) {
+ on_twt_event_device_notify_callback(*event);
+ }
+}
+
// End of the free-standing "C" style callbacks.
WifiLegacyHal::WifiLegacyHal(
@@ -1529,6 +1566,70 @@
restrictions);
}
+wifi_error WifiLegacyHal::setVoipMode(const std::string& iface_name,
+ wifi_voip_mode mode) {
+ return global_func_table_.wifi_set_voip_mode(getIfaceHandle(iface_name),
+ mode);
+}
+
+wifi_error WifiLegacyHal::twtRegisterHandler(
+ const std::string& iface_name, const TwtCallbackHandlers& user_callbacks) {
+ on_twt_event_setup_response_callback = user_callbacks.on_setup_response;
+ on_twt_event_teardown_completion_callback =
+ user_callbacks.on_teardown_completion;
+ on_twt_event_info_frame_received_callback =
+ user_callbacks.on_info_frame_received;
+ on_twt_event_device_notify_callback = user_callbacks.on_device_notify;
+
+ return global_func_table_.wifi_twt_register_handler(
+ getIfaceHandle(iface_name),
+ {onAsyncTwtEventSetupResponse, onAsyncTwtEventTeardownCompletion,
+ onAsyncTwtEventInfoFrameReceived, onAsyncTwtEventDeviceNotify});
+}
+
+std::pair<wifi_error, TwtCapabilitySet> WifiLegacyHal::twtGetCapability(
+ const std::string& iface_name) {
+ TwtCapabilitySet capSet;
+ wifi_error status = global_func_table_.wifi_twt_get_capability(
+ getIfaceHandle(iface_name), &capSet);
+ return {status, capSet};
+}
+
+wifi_error WifiLegacyHal::twtSetupRequest(const std::string& iface_name,
+ const TwtSetupRequest& msg) {
+ TwtSetupRequest msgInternal(msg);
+ return global_func_table_.wifi_twt_setup_request(getIfaceHandle(iface_name),
+ &msgInternal);
+}
+
+wifi_error WifiLegacyHal::twtTearDownRequest(const std::string& iface_name,
+ const TwtTeardownRequest& msg) {
+ TwtTeardownRequest msgInternal(msg);
+ return global_func_table_.wifi_twt_teardown_request(
+ getIfaceHandle(iface_name), &msgInternal);
+}
+
+wifi_error WifiLegacyHal::twtInfoFrameRequest(const std::string& iface_name,
+ const TwtInfoFrameRequest& msg) {
+ TwtInfoFrameRequest msgInternal(msg);
+ return global_func_table_.wifi_twt_info_frame_request(
+ getIfaceHandle(iface_name), &msgInternal);
+}
+
+std::pair<wifi_error, TwtStats> WifiLegacyHal::twtGetStats(
+ const std::string& iface_name, uint8_t configId) {
+ TwtStats stats;
+ wifi_error status = global_func_table_.wifi_twt_get_stats(
+ getIfaceHandle(iface_name), configId, &stats);
+ return {status, stats};
+}
+
+wifi_error WifiLegacyHal::twtClearStats(const std::string& iface_name,
+ uint8_t configId) {
+ return global_func_table_.wifi_twt_clear_stats(getIfaceHandle(iface_name),
+ configId);
+}
+
void WifiLegacyHal::invalidate() {
global_handle_ = nullptr;
iface_name_to_handle_.clear();
@@ -1560,6 +1661,10 @@
on_nan_event_range_request_user_callback = nullptr;
on_nan_event_range_report_user_callback = nullptr;
on_nan_event_schedule_update_user_callback = nullptr;
+ on_twt_event_setup_response_callback = nullptr;
+ on_twt_event_teardown_completion_callback = nullptr;
+ on_twt_event_info_frame_received_callback = nullptr;
+ on_twt_event_device_notify_callback = nullptr;
}
} // namespace legacy_hal
diff --git a/wifi/1.5/default/wifi_legacy_hal.h b/wifi/1.5/default/wifi_legacy_hal.h
index 6266cf6..11efe7e 100644
--- a/wifi/1.5/default/wifi_legacy_hal.h
+++ b/wifi/1.5/default/wifi_legacy_hal.h
@@ -164,6 +164,18 @@
using on_radio_mode_change_callback =
std::function<void(const std::vector<WifiMacInfo>&)>;
+// TWT response and event callbacks struct.
+struct TwtCallbackHandlers {
+ // Callback for TWT setup response
+ std::function<void(const TwtSetupResponse&)> on_setup_response;
+ // Callback for TWT teardown completion
+ std::function<void(const TwtTeardownCompletion&)> on_teardown_completion;
+ // Callback for TWT info frame received event
+ std::function<void(const TwtInfoFrameReceived&)> on_info_frame_received;
+ // Callback for TWT notification from the device
+ std::function<void(const TwtDeviceNotify&)> on_device_notify;
+};
+
/**
* Class that encapsulates all legacy HAL interactions.
* This class manages the lifetime of the event loop thread used by legacy HAL.
@@ -391,6 +403,28 @@
std::vector<wifi_coex_unsafe_channel> unsafe_channels,
uint32_t restrictions);
+ wifi_error setVoipMode(const std::string& iface_name, wifi_voip_mode mode);
+
+ wifi_error twtRegisterHandler(const std::string& iface_name,
+ const TwtCallbackHandlers& handler);
+
+ std::pair<wifi_error, TwtCapabilitySet> twtGetCapability(
+ const std::string& iface_name);
+
+ wifi_error twtSetupRequest(const std::string& iface_name,
+ const TwtSetupRequest& msg);
+
+ wifi_error twtTearDownRequest(const std::string& iface_name,
+ const TwtTeardownRequest& msg);
+
+ wifi_error twtInfoFrameRequest(const std::string& iface_name,
+ const TwtInfoFrameRequest& msg);
+
+ std::pair<wifi_error, TwtStats> twtGetStats(const std::string& iface_name,
+ uint8_t configId);
+
+ wifi_error twtClearStats(const std::string& iface_name, uint8_t configId);
+
private:
// Retrieve interface handles for all the available interfaces.
wifi_error retrieveIfaceHandles();
diff --git a/wifi/1.5/default/wifi_legacy_hal_stubs.cpp b/wifi/1.5/default/wifi_legacy_hal_stubs.cpp
index b6c908b..4b005d6 100644
--- a/wifi/1.5/default/wifi_legacy_hal_stubs.cpp
+++ b/wifi/1.5/default/wifi_legacy_hal_stubs.cpp
@@ -150,7 +150,14 @@
populateStubFor(&hal_fn->wifi_multi_sta_set_primary_connection);
populateStubFor(&hal_fn->wifi_multi_sta_set_use_case);
populateStubFor(&hal_fn->wifi_set_coex_unsafe_channels);
-
+ populateStubFor(&hal_fn->wifi_set_voip_mode);
+ populateStubFor(&hal_fn->wifi_twt_register_handler);
+ populateStubFor(&hal_fn->wifi_twt_get_capability);
+ populateStubFor(&hal_fn->wifi_twt_setup_request);
+ populateStubFor(&hal_fn->wifi_twt_teardown_request);
+ populateStubFor(&hal_fn->wifi_twt_info_frame_request);
+ populateStubFor(&hal_fn->wifi_twt_get_stats);
+ populateStubFor(&hal_fn->wifi_twt_clear_stats);
return true;
}
} // namespace legacy_hal
diff --git a/wifi/hostapd/1.3/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.3/vts/functional/hostapd_hidl_test.cpp
index bdbe651..a22252c 100644
--- a/wifi/hostapd/1.3/vts/functional/hostapd_hidl_test.cpp
+++ b/wifi/hostapd/1.3/vts/functional/hostapd_hidl_test.cpp
@@ -124,6 +124,7 @@
// Newly added attributes in V1_3
channelParams_1_3.channel = iface_params.channelParams.channel;
channelParams_1_3.enableAcs = iface_params.channelParams.enableAcs;
+ channelParams_1_3.bandMask = iface_params_1_2.channelParams.bandMask;
channelParams_1_3.V1_2 = iface_params_1_2.channelParams;
vec_channelParams.push_back(channelParams_1_3);
@@ -147,7 +148,8 @@
iface_params_1_3.V1_2.V1_1.V1_0.channelParams.enableAcs;
iface_params_1_3.channelParamsList[0].V1_2 =
iface_params_1_3.V1_2.channelParams;
-
+ iface_params_1_3.channelParamsList[0].bandMask =
+ iface_params_1_3.V1_2.channelParams.bandMask;
return iface_params_1_3;
}