Merge "graphics.composer: add @2.3 compatibility"
diff --git a/biometrics/face/1.0/types.hal b/biometrics/face/1.0/types.hal
index 2628af9..f6827d5 100644
--- a/biometrics/face/1.0/types.hal
+++ b/biometrics/face/1.0/types.hal
@@ -245,9 +245,22 @@
RECALIBRATE = 13,
/**
+ * The face is too different from a previous acquisition. This condition
+ * only applies to enrollment. This can happen if the user passes the
+ * device to someone else in the middle of enrollment.
+ */
+ TOO_DIFFERENT = 14,
+
+ /**
+ * The face is too similar to a previous acquisition. This condition only
+ * applies to enrollment. The user should change their pose.
+ */
+ TOO_SIMILAR = 15,
+
+ /**
* Used to enable a vendor-specific acquisition message.
*/
- VENDOR = 14
+ VENDOR = 16
};
/**
diff --git a/bluetooth/.clang-format b/bluetooth/.clang-format
new file mode 100644
index 0000000..9564994
--- /dev/null
+++ b/bluetooth/.clang-format
@@ -0,0 +1,20 @@
+#
+# Copyright 2018 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.
+#
+
+BasedOnStyle: Google
+CommentPragmas: NOLINT:.*
+DerivePointerAlignment: false
+
diff --git a/bluetooth/1.0/default/async_fd_watcher.cc b/bluetooth/1.0/default/async_fd_watcher.cc
index 7c74643..18098ca 100644
--- a/bluetooth/1.0/default/async_fd_watcher.cc
+++ b/bluetooth/1.0/default/async_fd_watcher.cc
@@ -18,13 +18,13 @@
#include "async_fd_watcher.h"
+#include <log/log.h>
#include <algorithm>
#include <atomic>
#include <condition_variable>
#include <map>
#include <mutex>
#include <thread>
-#include <log/log.h>
#include <vector>
#include "fcntl.h"
#include "sys/select.h"
@@ -159,11 +159,9 @@
TimeoutCallback saved_cb;
{
std::unique_lock<std::mutex> guard(timeout_mutex_);
- if (timeout_ms_ > std::chrono::milliseconds(0))
- saved_cb = timeout_cb_;
+ if (timeout_ms_ > std::chrono::milliseconds(0)) saved_cb = timeout_cb_;
}
- if (saved_cb != nullptr)
- saved_cb();
+ if (saved_cb != nullptr) saved_cb();
continue;
}
@@ -180,14 +178,14 @@
std::unique_lock<std::mutex> guard(internal_mutex_);
for (auto& it : watched_fds_) {
if (FD_ISSET(it.first, &read_fds)) {
- it.second(it.first);
+ it.second(it.first);
}
}
}
}
}
-} // namespace async
-} // namespace bluetooth
-} // namespace hardware
-} // namespace android
+} // namespace async
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
diff --git a/bluetooth/1.0/default/async_fd_watcher.h b/bluetooth/1.0/default/async_fd_watcher.h
index 358cbc3..b51f921 100644
--- a/bluetooth/1.0/default/async_fd_watcher.h
+++ b/bluetooth/1.0/default/async_fd_watcher.h
@@ -60,8 +60,7 @@
std::chrono::milliseconds timeout_ms_;
};
-
-} // namespace async
-} // namespace bluetooth
-} // namespace hardware
-} // namespace android
+} // namespace async
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
diff --git a/bluetooth/1.0/default/bluetooth_address.h b/bluetooth/1.0/default/bluetooth_address.h
index 94bf616..010a113 100644
--- a/bluetooth/1.0/default/bluetooth_address.h
+++ b/bluetooth/1.0/default/bluetooth_address.h
@@ -54,8 +54,8 @@
static bool get_local_address(uint8_t* addr);
};
-} // namespace implementation
-} // namespace V1_0
-} // namespace bluetooth
-} // namespace hardware
-} // namespace android
+} // namespace implementation
+} // namespace V1_0
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
diff --git a/bluetooth/1.0/default/bluetooth_hci.h b/bluetooth/1.0/default/bluetooth_hci.h
index e2797b1..c966990 100644
--- a/bluetooth/1.0/default/bluetooth_hci.h
+++ b/bluetooth/1.0/default/bluetooth_hci.h
@@ -29,8 +29,8 @@
namespace V1_0 {
namespace implementation {
-using ::android::hardware::Return;
using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
class BluetoothDeathRecipient;
diff --git a/bluetooth/1.0/default/bt_vendor_lib.h b/bluetooth/1.0/default/bt_vendor_lib.h
index c140e52..c4035b7 100644
--- a/bluetooth/1.0/default/bt_vendor_lib.h
+++ b/bluetooth/1.0/default/bt_vendor_lib.h
@@ -418,13 +418,12 @@
// DIRECTORIES.
// ONLY USED INSIDE transmit_cb.
// DO NOT USE IN NEW HAL IMPLEMENTATIONS GOING FORWARD
-typedef struct
-{
- uint16_t event;
- uint16_t len;
- uint16_t offset;
- uint16_t layer_specific;
- uint8_t data[];
+typedef struct {
+ uint16_t event;
+ uint16_t len;
+ uint16_t offset;
+ uint16_t layer_specific;
+ uint8_t data[];
} HC_BT_HDR;
// /MODIFICATION
diff --git a/bluetooth/1.0/default/h4_protocol.cc b/bluetooth/1.0/default/h4_protocol.cc
index df40507..98e3273 100644
--- a/bluetooth/1.0/default/h4_protocol.cc
+++ b/bluetooth/1.0/default/h4_protocol.cc
@@ -34,7 +34,8 @@
{const_cast<uint8_t*>(data), length}};
ssize_t ret = 0;
do {
- ret = TEMP_FAILURE_RETRY(writev(uart_fd_, iov, sizeof(iov) / sizeof(iov[0])));
+ ret =
+ TEMP_FAILURE_RETRY(writev(uart_fd_, iov, sizeof(iov) / sizeof(iov[0])));
} while (-1 == ret && EAGAIN == errno);
if (ret == -1) {
diff --git a/bluetooth/1.0/default/hci_packetizer.cc b/bluetooth/1.0/default/hci_packetizer.cc
index 71f4328..7cb3a11 100644
--- a/bluetooth/1.0/default/hci_packetizer.cc
+++ b/bluetooth/1.0/default/hci_packetizer.cc
@@ -46,9 +46,7 @@
namespace bluetooth {
namespace hci {
-const hidl_vec<uint8_t>& HciPacketizer::GetPacket() const {
- return packet_;
-}
+const hidl_vec<uint8_t>& HciPacketizer::GetPacket() const { return packet_; }
void HciPacketizer::OnDataReady(int fd, HciPacketType packet_type) {
switch (state_) {
diff --git a/bluetooth/1.0/default/hci_protocol.cc b/bluetooth/1.0/default/hci_protocol.cc
index bf94dfe..7e88dc4 100644
--- a/bluetooth/1.0/default/hci_protocol.cc
+++ b/bluetooth/1.0/default/hci_protocol.cc
@@ -20,8 +20,8 @@
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
-#include <unistd.h>
#include <log/log.h>
+#include <unistd.h>
namespace android {
namespace hardware {
diff --git a/bluetooth/1.0/default/service.cpp b/bluetooth/1.0/default/service.cpp
index 3a7aad0..dd3f6a9 100644
--- a/bluetooth/1.0/default/service.cpp
+++ b/bluetooth/1.0/default/service.cpp
@@ -24,9 +24,9 @@
static const size_t kMaxThreads = 5;
// Generated HIDL files
-using android::hardware::bluetooth::V1_0::IBluetoothHci;
using android::hardware::defaultPassthroughServiceImplementation;
+using android::hardware::bluetooth::V1_0::IBluetoothHci;
int main() {
- return defaultPassthroughServiceImplementation<IBluetoothHci>(kMaxThreads);
+ return defaultPassthroughServiceImplementation<IBluetoothHci>(kMaxThreads);
}
diff --git a/bluetooth/1.0/default/test/async_fd_watcher_unittest.cc b/bluetooth/1.0/default/test/async_fd_watcher_unittest.cc
index ee7d8d1..07d8d54 100644
--- a/bluetooth/1.0/default/test/async_fd_watcher_unittest.cc
+++ b/bluetooth/1.0/default/test/async_fd_watcher_unittest.cc
@@ -252,13 +252,13 @@
});
// Set a timeout flag in each callback.
- conn_watcher.ConfigureTimeout(
- std::chrono::milliseconds(500),
- [&conn_watcher, &timed_out, &timed_out2]() {
- timed_out = true;
- conn_watcher.ConfigureTimeout(std::chrono::seconds(1),
+ conn_watcher.ConfigureTimeout(std::chrono::milliseconds(500),
+ [&conn_watcher, &timed_out, &timed_out2]() {
+ timed_out = true;
+ conn_watcher.ConfigureTimeout(
+ std::chrono::seconds(1),
[&timed_out2]() { timed_out2 = true; });
- });
+ });
EXPECT_FALSE(timed_out);
EXPECT_FALSE(timed_out2);
sleep(1);
@@ -385,8 +385,8 @@
CleanUpServer();
}
-} // namespace implementation
-} // namespace V1_0
-} // namespace bluetooth
-} // namespace hardware
-} // namespace android
+} // namespace implementation
+} // namespace V1_0
+} // namespace bluetooth
+} // namespace hardware
+} // namespace android
diff --git a/bluetooth/1.0/default/test/h4_protocol_unittest.cc b/bluetooth/1.0/default/test/h4_protocol_unittest.cc
index ad08086..ba56c0d 100644
--- a/bluetooth/1.0/default/test/h4_protocol_unittest.cc
+++ b/bluetooth/1.0/default/test/h4_protocol_unittest.cc
@@ -36,8 +36,8 @@
namespace V1_0 {
namespace implementation {
-using ::testing::Eq;
using hci::H4Protocol;
+using ::testing::Eq;
static char sample_data1[100] = "A point is that which has no part.";
static char sample_data2[100] = "A line is breadthless length.";
diff --git a/bluetooth/1.0/default/test/mct_protocol_unittest.cc b/bluetooth/1.0/default/test/mct_protocol_unittest.cc
index d45058e..60dbc88 100644
--- a/bluetooth/1.0/default/test/mct_protocol_unittest.cc
+++ b/bluetooth/1.0/default/test/mct_protocol_unittest.cc
@@ -36,8 +36,8 @@
namespace V1_0 {
namespace implementation {
-using ::testing::Eq;
using hci::MctProtocol;
+using ::testing::Eq;
static char sample_data1[100] = "A point is that which has no part.";
static char sample_data2[100] = "A line is breadthless length.";
diff --git a/bluetooth/1.0/default/test/properties.cc b/bluetooth/1.0/default/test/properties.cc
index 6ac4fb4..70de01e 100644
--- a/bluetooth/1.0/default/test/properties.cc
+++ b/bluetooth/1.0/default/test/properties.cc
@@ -36,7 +36,7 @@
struct property properties[MAX_PROPERTIES];
// Find the correct entry.
-static int property_find(const char *key) {
+static int property_find(const char* key) {
for (int i = 0; i < num_properties; i++) {
if (strncmp(properties[i].key, key, PROP_KEY_MAX) == 0) {
return i;
@@ -45,7 +45,7 @@
return MAX_PROPERTIES;
}
-int property_set(const char *key, const char *value) {
+int property_set(const char* key, const char* value) {
if (strnlen(value, PROP_VALUE_MAX) > PROP_VALUE_MAX) return -1;
// Check to see if the property exists.
@@ -63,7 +63,7 @@
return 0;
}
-int property_get(const char *key, char *value, const char *default_value) {
+int property_get(const char* key, char* value, const char* default_value) {
// This doesn't mock the behavior of default value
if (default_value != NULL) ALOGE("%s: default_value is ignored!", __func__);
diff --git a/bluetooth/1.0/default/vendor_interface.cc b/bluetooth/1.0/default/vendor_interface.cc
index a8f5bb4..e5f02f3 100644
--- a/bluetooth/1.0/default/vendor_interface.cc
+++ b/bluetooth/1.0/default/vendor_interface.cc
@@ -35,8 +35,8 @@
namespace {
-using android::hardware::bluetooth::V1_0::implementation::VendorInterface;
using android::hardware::hidl_vec;
+using android::hardware::bluetooth::V1_0::implementation::VendorInterface;
struct {
tINT_CMD_CBACK cb;
@@ -258,8 +258,7 @@
fd_watcher_.WatchFdForNonBlockingReads(
fd_list[CH_EVT], [mct_hci](int fd) { mct_hci->OnEventDataReady(fd); });
fd_watcher_.WatchFdForNonBlockingReads(
- fd_list[CH_ACL_IN],
- [mct_hci](int fd) { mct_hci->OnAclDataReady(fd); });
+ fd_list[CH_ACL_IN], [mct_hci](int fd) { mct_hci->OnAclDataReady(fd); });
hci_ = mct_hci;
}
diff --git a/bluetooth/1.0/default/vendor_interface.h b/bluetooth/1.0/default/vendor_interface.h
index a401ee6..36f4e1b 100644
--- a/bluetooth/1.0/default/vendor_interface.h
+++ b/bluetooth/1.0/default/vendor_interface.h
@@ -40,9 +40,9 @@
PacketReadCallback event_cb, PacketReadCallback acl_cb,
PacketReadCallback sco_cb);
static void Shutdown();
- static VendorInterface *get();
+ static VendorInterface* get();
- size_t Send(uint8_t type, const uint8_t *data, size_t length);
+ size_t Send(uint8_t type, const uint8_t* data, size_t length);
void OnFirmwareConfigured(uint8_t result);
@@ -58,15 +58,15 @@
void HandleIncomingEvent(const hidl_vec<uint8_t>& hci_packet);
- void *lib_handle_;
- bt_vendor_interface_t *lib_interface_;
+ void* lib_handle_;
+ bt_vendor_interface_t* lib_interface_;
async::AsyncFdWatcher fd_watcher_;
InitializeCompleteCallback initialize_complete_cb_;
hci::HciProtocol* hci_;
PacketReadCallback event_cb_;
- FirmwareStartupTimer *firmware_startup_timer_;
+ FirmwareStartupTimer* firmware_startup_timer_;
};
} // namespace implementation
diff --git a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
index 439c5fb..ae84ec2 100644
--- a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
+++ b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
@@ -28,13 +28,13 @@
#include <VtsHalHidlTargetTestEnvBase.h>
#include <queue>
-using ::android::hardware::bluetooth::V1_0::IBluetoothHci;
-using ::android::hardware::bluetooth::V1_0::IBluetoothHciCallbacks;
-using ::android::hardware::bluetooth::V1_0::Status;
+using ::android::sp;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
-using ::android::sp;
+using ::android::hardware::bluetooth::V1_0::IBluetoothHci;
+using ::android::hardware::bluetooth::V1_0::IBluetoothHciCallbacks;
+using ::android::hardware::bluetooth::V1_0::Status;
#define HCI_MINIMUM_HCI_VERSION 5 // Bluetooth Core Specification 3.0 + HS
#define HCI_MINIMUM_LMP_VERSION 5 // Bluetooth Core Specification 3.0 + HS
@@ -191,12 +191,12 @@
}
virtual void TearDown() override {
- // Should not be checked in production code
- ASSERT_TRUE(bluetooth->close().isOk());
- handle_no_ops();
- EXPECT_EQ(static_cast<size_t>(0), event_queue.size());
- EXPECT_EQ(static_cast<size_t>(0), sco_queue.size());
- EXPECT_EQ(static_cast<size_t>(0), acl_queue.size());
+ // Should not be checked in production code
+ ASSERT_TRUE(bluetooth->close().isOk());
+ handle_no_ops();
+ EXPECT_EQ(static_cast<size_t>(0), event_queue.size());
+ EXPECT_EQ(static_cast<size_t>(0), sco_queue.size());
+ EXPECT_EQ(static_cast<size_t>(0), acl_queue.size());
}
void setBufferSizes();
@@ -659,10 +659,11 @@
EXPECT_LT(0, max_sco_data_packet_length);
sendAndCheckSCO(1, max_sco_data_packet_length, sco_connection_handles[0]);
int sco_packets_sent = 1;
- int completed_packets = wait_for_completed_packets_event(sco_connection_handles[0]);
+ int completed_packets =
+ wait_for_completed_packets_event(sco_connection_handles[0]);
if (sco_packets_sent != completed_packets) {
- ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__, sco_packets_sent,
- completed_packets);
+ ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__,
+ sco_packets_sent, completed_packets);
}
}
@@ -670,10 +671,11 @@
EXPECT_LT(0, max_acl_data_packet_length);
sendAndCheckACL(1, max_acl_data_packet_length, acl_connection_handles[0]);
int acl_packets_sent = 1;
- int completed_packets = wait_for_completed_packets_event(acl_connection_handles[0]);
+ int completed_packets =
+ wait_for_completed_packets_event(acl_connection_handles[0]);
if (acl_packets_sent != completed_packets) {
- ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__, acl_packets_sent,
- completed_packets);
+ ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__,
+ acl_packets_sent, completed_packets);
}
}
}
@@ -695,10 +697,11 @@
sendAndCheckSCO(NUM_SCO_PACKETS_BANDWIDTH, max_sco_data_packet_length,
sco_connection_handles[0]);
int sco_packets_sent = NUM_SCO_PACKETS_BANDWIDTH;
- int completed_packets = wait_for_completed_packets_event(sco_connection_handles[0]);
+ int completed_packets =
+ wait_for_completed_packets_event(sco_connection_handles[0]);
if (sco_packets_sent != completed_packets) {
- ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__, sco_packets_sent,
- completed_packets);
+ ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__,
+ sco_packets_sent, completed_packets);
}
}
@@ -707,10 +710,11 @@
sendAndCheckACL(NUM_ACL_PACKETS_BANDWIDTH, max_acl_data_packet_length,
acl_connection_handles[0]);
int acl_packets_sent = NUM_ACL_PACKETS_BANDWIDTH;
- int completed_packets = wait_for_completed_packets_event(acl_connection_handles[0]);
+ int completed_packets =
+ wait_for_completed_packets_event(acl_connection_handles[0]);
if (acl_packets_sent != completed_packets) {
- ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__, acl_packets_sent,
- completed_packets);
+ ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__,
+ acl_packets_sent, completed_packets);
}
}
}
diff --git a/bluetooth/a2dp/1.0/default/BluetoothAudioOffload.cpp b/bluetooth/a2dp/1.0/default/BluetoothAudioOffload.cpp
index 2a66abe..9abb88d 100644
--- a/bluetooth/a2dp/1.0/default/BluetoothAudioOffload.cpp
+++ b/bluetooth/a2dp/1.0/default/BluetoothAudioOffload.cpp
@@ -23,47 +23,52 @@
namespace V1_0 {
namespace implementation {
-IBluetoothAudioOffload* HIDL_FETCH_IBluetoothAudioOffload(const char* /* name */) {
- return new BluetoothAudioOffload();
+IBluetoothAudioOffload* HIDL_FETCH_IBluetoothAudioOffload(
+ const char* /* name */) {
+ return new BluetoothAudioOffload();
}
-// Methods from ::android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioOffload follow.
-Return<::android::hardware::bluetooth::a2dp::V1_0::Status> BluetoothAudioOffload::startSession(
- const sp<::android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioHost>& hostIf __unused,
- const ::android::hardware::bluetooth::a2dp::V1_0::CodecConfiguration& codecConfig __unused) {
- /**
- * Initialize the audio platform if codecConfiguration is supported.
- * Save the the IBluetoothAudioHost interface, so that it can be used
- * later to send stream control commands to the HAL client, based on
- * interaction with Audio framework.
- */
- return ::android::hardware::bluetooth::a2dp::V1_0::Status::FAILURE;
+// Methods from
+// ::android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioOffload follow.
+Return<::android::hardware::bluetooth::a2dp::V1_0::Status>
+BluetoothAudioOffload::startSession(
+ const sp<::android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioHost>&
+ hostIf __unused,
+ const ::android::hardware::bluetooth::a2dp::V1_0::CodecConfiguration&
+ codecConfig __unused) {
+ /**
+ * Initialize the audio platform if codecConfiguration is supported.
+ * Save the the IBluetoothAudioHost interface, so that it can be used
+ * later to send stream control commands to the HAL client, based on
+ * interaction with Audio framework.
+ */
+ return ::android::hardware::bluetooth::a2dp::V1_0::Status::FAILURE;
}
Return<void> BluetoothAudioOffload::streamStarted(
::android::hardware::bluetooth::a2dp::V1_0::Status status __unused) {
- /**
- * Streaming on control path has started,
- * HAL server should start the streaming on data path.
- */
- return Void();
+ /**
+ * Streaming on control path has started,
+ * HAL server should start the streaming on data path.
+ */
+ return Void();
}
Return<void> BluetoothAudioOffload::streamSuspended(
::android::hardware::bluetooth::a2dp::V1_0::Status status __unused) {
- /**
- * Streaming on control path has suspend,
- * HAL server should suspend the streaming on data path.
- */
- return Void();
+ /**
+ * Streaming on control path has suspend,
+ * HAL server should suspend the streaming on data path.
+ */
+ return Void();
}
Return<void> BluetoothAudioOffload::endSession() {
- /**
- * Cleanup the audio platform as remote A2DP Sink device is no
- * longer active
- */
- return Void();
+ /**
+ * Cleanup the audio platform as remote A2DP Sink device is no
+ * longer active
+ */
+ return Void();
}
} // namespace implementation
diff --git a/bluetooth/a2dp/1.0/default/BluetoothAudioOffload.h b/bluetooth/a2dp/1.0/default/BluetoothAudioOffload.h
index 5d07b5b..16a83c2 100644
--- a/bluetooth/a2dp/1.0/default/BluetoothAudioOffload.h
+++ b/bluetooth/a2dp/1.0/default/BluetoothAudioOffload.h
@@ -28,27 +28,32 @@
namespace V1_0 {
namespace implementation {
+using ::android::sp;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
-using ::android::sp;
struct BluetoothAudioOffload : public IBluetoothAudioOffload {
- BluetoothAudioOffload() {}
- // Methods from ::android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioOffload follow.
- Return<::android::hardware::bluetooth::a2dp::V1_0::Status> startSession(
- const sp<::android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioHost>& hostIf,
- const ::android::hardware::bluetooth::a2dp::V1_0::CodecConfiguration& codecConfig) override;
- Return<void> streamStarted(::android::hardware::bluetooth::a2dp::V1_0::Status status) override;
- Return<void> streamSuspended(
- ::android::hardware::bluetooth::a2dp::V1_0::Status status) override;
- Return<void> endSession() override;
+ BluetoothAudioOffload() {}
+ // Methods from
+ // ::android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioOffload follow.
+ Return<::android::hardware::bluetooth::a2dp::V1_0::Status> startSession(
+ const sp<::android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioHost>&
+ hostIf,
+ const ::android::hardware::bluetooth::a2dp::V1_0::CodecConfiguration&
+ codecConfig) override;
+ Return<void> streamStarted(
+ ::android::hardware::bluetooth::a2dp::V1_0::Status status) override;
+ Return<void> streamSuspended(
+ ::android::hardware::bluetooth::a2dp::V1_0::Status status) override;
+ Return<void> endSession() override;
};
-extern "C" IBluetoothAudioOffload* HIDL_FETCH_IBluetoothAudioOffload(const char* name);
+extern "C" IBluetoothAudioOffload* HIDL_FETCH_IBluetoothAudioOffload(
+ const char* name);
} // namespace implementation
} // namespace V1_0
diff --git a/bluetooth/a2dp/1.0/vts/functional/VtsHalBluetoothA2dpV1_0TargetTest.cpp b/bluetooth/a2dp/1.0/vts/functional/VtsHalBluetoothA2dpV1_0TargetTest.cpp
index 1a0342f..d8d0c29 100644
--- a/bluetooth/a2dp/1.0/vts/functional/VtsHalBluetoothA2dpV1_0TargetTest.cpp
+++ b/bluetooth/a2dp/1.0/vts/functional/VtsHalBluetoothA2dpV1_0TargetTest.cpp
@@ -26,85 +26,92 @@
#include <VtsHalHidlTargetTestBase.h>
#include <VtsHalHidlTargetTestEnvBase.h>
-using ::android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioHost;
-using ::android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioOffload;
-using ::android::hardware::bluetooth::a2dp::V1_0::Status;
-using ::android::hardware::bluetooth::a2dp::V1_0::CodecType;
-using ::android::hardware::bluetooth::a2dp::V1_0::SampleRate;
+using ::android::sp;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
using ::android::hardware::bluetooth::a2dp::V1_0::BitsPerSample;
using ::android::hardware::bluetooth::a2dp::V1_0::ChannelMode;
using ::android::hardware::bluetooth::a2dp::V1_0::CodecConfiguration;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::sp;
+using ::android::hardware::bluetooth::a2dp::V1_0::CodecType;
+using ::android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioHost;
+using ::android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioOffload;
+using ::android::hardware::bluetooth::a2dp::V1_0::SampleRate;
+using ::android::hardware::bluetooth::a2dp::V1_0::Status;
// Test environment for Bluetooth HIDL A2DP HAL.
-class BluetoothA2dpHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
- public:
- // get the test environment singleton
- static BluetoothA2dpHidlEnvironment* Instance() {
- static BluetoothA2dpHidlEnvironment* instance = new BluetoothA2dpHidlEnvironment;
- return instance;
- }
+class BluetoothA2dpHidlEnvironment
+ : public ::testing::VtsHalHidlTargetTestEnvBase {
+ public:
+ // get the test environment singleton
+ static BluetoothA2dpHidlEnvironment* Instance() {
+ static BluetoothA2dpHidlEnvironment* instance =
+ new BluetoothA2dpHidlEnvironment;
+ return instance;
+ }
- virtual void registerTestServices() override { registerTestService<IBluetoothAudioOffload>(); }
+ virtual void registerTestServices() override {
+ registerTestService<IBluetoothAudioOffload>();
+ }
- private:
- BluetoothA2dpHidlEnvironment() {}
+ private:
+ BluetoothA2dpHidlEnvironment() {}
};
// The main test class for Bluetooth A2DP HIDL HAL.
class BluetoothA2dpHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+ public:
+ virtual void SetUp() override {
+ // currently test passthrough mode only
+ audio_offload =
+ ::testing::VtsHalHidlTargetTestBase::getService<IBluetoothAudioOffload>(
+ BluetoothA2dpHidlEnvironment::Instance()
+ ->getServiceName<IBluetoothAudioOffload>());
+ ASSERT_NE(audio_offload, nullptr);
+
+ audio_host = new BluetoothAudioHost(*this);
+ ASSERT_NE(audio_host, nullptr);
+
+ codec.codecType = CodecType::AAC;
+ codec.sampleRate = SampleRate::RATE_44100;
+ codec.bitsPerSample = BitsPerSample::BITS_16;
+ codec.channelMode = ChannelMode::STEREO;
+ codec.encodedAudioBitrate = 320000;
+ codec.peerMtu = 1000;
+ }
+
+ virtual void TearDown() override {}
+
+ // A simple test implementation of IBluetoothAudioHost.
+ class BluetoothAudioHost
+ : public ::testing::VtsHalHidlTargetCallbackBase<BluetoothA2dpHidlTest>,
+ public IBluetoothAudioHost {
+ BluetoothA2dpHidlTest& parent_;
+
public:
- virtual void SetUp() override {
- // currently test passthrough mode only
- audio_offload = ::testing::VtsHalHidlTargetTestBase::getService<IBluetoothAudioOffload>(
- BluetoothA2dpHidlEnvironment::Instance()->getServiceName<IBluetoothAudioOffload>());
- ASSERT_NE(audio_offload, nullptr);
+ BluetoothAudioHost(BluetoothA2dpHidlTest& parent) : parent_(parent){};
+ virtual ~BluetoothAudioHost() = default;
- audio_host = new BluetoothAudioHost(*this);
- ASSERT_NE(audio_host, nullptr);
-
- codec.codecType = CodecType::AAC;
- codec.sampleRate = SampleRate::RATE_44100;
- codec.bitsPerSample = BitsPerSample::BITS_16;
- codec.channelMode = ChannelMode::STEREO;
- codec.encodedAudioBitrate = 320000;
- codec.peerMtu = 1000;
- }
-
- virtual void TearDown() override {}
-
- // A simple test implementation of IBluetoothAudioHost.
- class BluetoothAudioHost
- : public ::testing::VtsHalHidlTargetCallbackBase<BluetoothA2dpHidlTest>,
- public IBluetoothAudioHost {
- BluetoothA2dpHidlTest& parent_;
-
- public:
- BluetoothAudioHost(BluetoothA2dpHidlTest& parent) : parent_(parent){};
- virtual ~BluetoothAudioHost() = default;
-
- Return<void> startStream() override {
- parent_.audio_offload->streamStarted(Status::SUCCESS);
- return Void();
- };
-
- Return<void> suspendStream() override {
- parent_.audio_offload->streamSuspended(Status::SUCCESS);
- return Void();
- };
-
- Return<void> stopStream() override { return Void(); };
+ Return<void> startStream() override {
+ parent_.audio_offload->streamStarted(Status::SUCCESS);
+ return Void();
};
- // audio_host is for the Audio HAL to send stream start/suspend/stop commands to Bluetooth
- sp<IBluetoothAudioHost> audio_host;
- // audio_offload is for the Bluetooth HAL to report session started/ended and handled audio
- // stream started/suspended
- sp<IBluetoothAudioOffload> audio_offload;
- // codec is the currently used codec
- CodecConfiguration codec;
+ Return<void> suspendStream() override {
+ parent_.audio_offload->streamSuspended(Status::SUCCESS);
+ return Void();
+ };
+
+ Return<void> stopStream() override { return Void(); };
+ };
+
+ // audio_host is for the Audio HAL to send stream start/suspend/stop commands
+ // to Bluetooth
+ sp<IBluetoothAudioHost> audio_host;
+ // audio_offload is for the Bluetooth HAL to report session started/ended and
+ // handled audio stream started/suspended
+ sp<IBluetoothAudioOffload> audio_offload;
+ // codec is the currently used codec
+ CodecConfiguration codec;
};
// Empty test: Initialize()/Close() are called in SetUp()/TearDown().
@@ -112,15 +119,15 @@
// Test start and end session
TEST_F(BluetoothA2dpHidlTest, StartAndEndSession) {
- EXPECT_EQ(Status::SUCCESS, audio_offload->startSession(audio_host, codec));
- audio_offload->endSession();
+ EXPECT_EQ(Status::SUCCESS, audio_offload->startSession(audio_host, codec));
+ audio_offload->endSession();
}
int main(int argc, char** argv) {
- ::testing::AddGlobalTestEnvironment(BluetoothA2dpHidlEnvironment::Instance());
- ::testing::InitGoogleTest(&argc, argv);
- BluetoothA2dpHidlEnvironment::Instance()->init(&argc, argv);
- int status = RUN_ALL_TESTS();
- LOG(INFO) << "Test result = " << status;
- return status;
+ ::testing::AddGlobalTestEnvironment(BluetoothA2dpHidlEnvironment::Instance());
+ ::testing::InitGoogleTest(&argc, argv);
+ BluetoothA2dpHidlEnvironment::Instance()->init(&argc, argv);
+ int status = RUN_ALL_TESTS();
+ LOG(INFO) << "Test result = " << status;
+ return status;
}
diff --git a/current.txt b/current.txt
index a7989d4..ef83acc 100644
--- a/current.txt
+++ b/current.txt
@@ -390,7 +390,7 @@
684702a60deef03a1e8093961dc0a18c555c857ad5a77ba7340b0635ae01eb70 android.hardware.camera.device@3.4::ICameraDeviceSession
dd2436f251a90f3e5e7ed773b1aeae21e381b00ae26b10ebe3a1001c894e5980 android.hardware.camera.metadata@3.3::types
da33234403ff5d60f3473711917b9948e6484a4260b5247acdafb111193a9de2 android.hardware.configstore@1.0::ISurfaceFlingerConfigs
-78886339f2c848cf13c1edd3ebba63f89796b2620d3bf3b5c21d038a53519ba0 android.hardware.gnss@1.0::IGnssMeasurementCallback
+d702fb01dc2a0733aa820b7eb65435ee3334f75632ef880bafd2fb8803a20a58 android.hardware.gnss@1.0::IGnssMeasurementCallback
b7ecf29927055ec422ec44bf776223f07d79ad9f92ccf9becf167e62c2607e7a android.hardware.keymaster@4.0::IKeymasterDevice
574e8f1499436fb4075894dcae0b36682427956ecb114f17f1fe22d116a83c6b android.hardware.neuralnetworks@1.0::IPreparedModel
1fb32361286b938d48a55c2539c846732afce0b99fe08590f556643125bc13d3 android.hardware.neuralnetworks@1.0::types
diff --git a/drm/1.1/README.md b/drm/1.1/README.md
new file mode 100644
index 0000000..e88e6ab
--- /dev/null
+++ b/drm/1.1/README.md
@@ -0,0 +1,84 @@
+# VINTF Device Manifest
+
+In Android Pie, an `<fqname>` tag was introduced to be able to express multiple
+different versions of the same HAL in VINTF manifests (for DRM)
+in device manifest. For devices launching with previous versions of Android and
+upgrading to Android Pie, the device manifest must not use `<fqname>` to
+satisfy requirements for non-optional HALs, because older version of `libvintf`
+do not recognize it, causing errors during OTA update.
+
+Assuming that the HAL provides `@1.0::I*/default`,
+`@1.1::I*/clearkey` and `@1.1::I*/foo` instances:
+
+## Devices upgrading to Android Pie
+
+### `target-level=1` or `target-level=2`
+
+FCM (framework compatibility matrix) version 2 (released in Android Oreo MR1)
+requires DRM 1.0. If the new device manifest has Target FCM Version (i.e.
+`target-level`) 1 or 2, it should use the following snippet:
+
+```xml
+<hal format="hidl">
+ <name>android.hardware.drm</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>ICryptoFactory</name>
+ <instance>default</instance>
+ </interface>
+ <interface>
+ <name>IDrmFactory</name>
+ <instance>default</instance>
+ </interface>
+ <fqname>@1.1::ICryptoFactory/clearkey</fqname>
+ <fqname>@1.1::IDrmFactory/clearkey</fqname>
+ <fqname>@1.1::ICryptoFactory/foo</fqname>
+ <fqname>@1.1::IDrmFactory/foo</fqname>
+</hal>
+```
+
+### `target-level=3`
+
+FCM (framework compatibility matrix) version 3 (released in Android Pie)
+requires DRM 1.1. If the new device manifest has Target FCM Version (i.e.
+`target-level`) 3, it should use the following snippet:
+
+
+```xml
+<hal format="hidl">
+ <name>android.hardware.drm</name>
+ <transport>hwbinder</transport>
+ <version>1.1</version>
+ <interface>
+ <name>ICryptoFactory</name>
+ <instance>clearkey</instance>
+ <instance>foo</instance>
+ </interface>
+ <interface>
+ <name>IDrmFactory</name>
+ <instance>clearkey</instance>
+ <instance>foo</instance>
+ </interface>
+ <fqname>@1.0::ICryptoFactory/default</fqname>
+ <fqname>@1.0::IDrmFactory/default</fqname>
+</hal>
+```
+
+## Devices launching with Android Pie
+If you have a new device launched with Android Pie (no OTA), both of the
+aforementioned snippets can be used. Besides, it is recommended to use the
+new, clearer format:
+
+```xml
+<hal format="hidl">
+ <name>android.hardware.drm</name>
+ <transport>hwbinder</transport>
+ <fqname>@1.0::ICryptoFactory/default</fqname>
+ <fqname>@1.0::IDrmFactory/default</fqname>
+ <fqname>@1.1::ICryptoFactory/clearkey</fqname>
+ <fqname>@1.1::IDrmFactory/clearkey</fqname>
+ <fqname>@1.1::ICryptoFactory/foo</fqname>
+ <fqname>@1.1::IDrmFactory/foo</fqname>
+</hal>
+```
diff --git a/gnss/1.0/IGnssMeasurementCallback.hal b/gnss/1.0/IGnssMeasurementCallback.hal
index d3489e6..2d44766 100644
--- a/gnss/1.0/IGnssMeasurementCallback.hal
+++ b/gnss/1.0/IGnssMeasurementCallback.hal
@@ -436,6 +436,10 @@
* Carrier-to-noise density in dB-Hz, typically in the range [0, 63].
* It contains the measured C/N0 value for the signal at the antenna port.
*
+ * If a signal has separate components (e.g. Pilot and Data channels) and
+ * the receiver only processes one of the components, then the reported
+ * cN0DbHz reflects only the component that is processed.
+ *
* This value is mandatory.
*/
double cN0DbHz;
diff --git a/graphics/bufferqueue/2.0/Android.bp b/graphics/bufferqueue/2.0/Android.bp
new file mode 100644
index 0000000..5385f28
--- /dev/null
+++ b/graphics/bufferqueue/2.0/Android.bp
@@ -0,0 +1,27 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.graphics.bufferqueue@2.0",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "types.hal",
+ "IGraphicBufferProducer.hal",
+ "IProducerListener.hal",
+ ],
+ interfaces: [
+ "android.hardware.graphics.common@1.0",
+ "android.hardware.graphics.common@1.1",
+ "android.hardware.graphics.common@1.2",
+ "android.hidl.base@1.0",
+ ],
+ types: [
+ "ConnectionType",
+ "SlotIndex",
+ "Status",
+ ],
+ gen_java: true,
+}
+
diff --git a/graphics/bufferqueue/2.0/IGraphicBufferProducer.hal b/graphics/bufferqueue/2.0/IGraphicBufferProducer.hal
new file mode 100644
index 0000000..734c0b4
--- /dev/null
+++ b/graphics/bufferqueue/2.0/IGraphicBufferProducer.hal
@@ -0,0 +1,648 @@
+/*
+ * Copyright (C) 2018 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.graphics.bufferqueue@2.0;
+
+import android.hardware.graphics.common@1.2::HardwareBuffer;
+import android.hardware.graphics.common@1.2::HardwareBufferDescription;
+import android.hardware.graphics.common@1.2::Rect;
+
+import IProducerListener;
+
+/**
+ * Ref: frameworks/native/include/gui/IGraphicBufferProducer.h:
+ * IGraphicBufferProducer
+ * This is a wrapper/wrapped HAL interface for the actual binder interface.
+ */
+interface IGraphicBufferProducer {
+ /**
+ * Sets the maximum number of buffers that can be dequeued at one time. If
+ * this method succeeds, any new buffer slots shall be both unallocated and
+ * owned by the buffer queue, i.e., they are not owned by the producer or
+ * the consumer. Calling this may cause some buffer slots to be emptied. If
+ * the caller is caching the contents of the buffer slots, it must empty
+ * that cache after calling this method.
+ *
+ * @p maxDequeuedBuffers must not be less than the number of currently
+ * dequeued buffer slots; otherwise, the returned @p status shall be
+ * `BAD_VALUE`.
+ *
+ * @p maxDequeuedBuffers must be at least 1 (inclusive), but at most
+ * (`NUM_BUFFER_SLOTS` - the minimum undequeued buffer count) (exclusive).
+ * The minimum undequeued buffer count can be obtained by calling
+ * `query(ANATIVEWINDOW_QUERY_MIN_UNDEQUEUED_BUFFERS)`.
+ *
+ * Before calling setMaxDequeuedBufferCount(), the caller must make sure
+ * that
+ * - @p maxDequeuedBuffers is greater than or equal to 1.
+ * - @p maxDequeuedBuffers is greater than or equal to the number of
+ * currently dequeued buffer slots.
+ * If any of these conditions do not hold, or if the request to set the new
+ * maximum number of dequeued buffers cannot be accomplished for any other
+ * reasons, `BAD_VALUE` shall be returned in @p status.
+ *
+ * @param maxDequeuedBuffers The desired number of buffers that can be
+ * dequeued at one time.
+ * @return status Status of the call.
+ */
+ setMaxDequeuedBufferCount(
+ int32_t maxDequeuedBuffers
+ ) generates (
+ Status status
+ );
+
+ /**
+ * Assigns a newly created buffer to the given slot index. The client is
+ * expected to mirror the slot-to-buffer mapping so that it is not necessary
+ * to transfer a `HardwareBuffer` object for every dequeue operation.
+ *
+ * If @p slot is not a valid slot index corresponding to a dequeued buffer,
+ * the call shall fail with @p status set to `BAD_VALUE`.
+ *
+ * @param slot Slot index.
+ * @return status Status of the call.
+ * @return buffer New buffer associated to the given slot index.
+ */
+ requestBuffer(
+ int32_t slot
+ ) generates (
+ Status status,
+ HardwareBuffer buffer
+ );
+
+ /**
+ * Sets the async flag: whether the producer intends to asynchronously queue
+ * buffers without blocking. Typically this is used for triple-buffering
+ * and/or when the swap interval is set to zero.
+ *
+ * Enabling async mode may internally allocate an additional buffer to allow
+ * for the asynchronous behavior. If it is not enabled, queue/dequeue calls
+ * may block.
+ *
+ * Changing the async flag may affect the number of available slots. If the
+ * adjustment to the number of slots cannot be made, @p status shall be set
+ * to `BAD_VALUE`.
+ *
+ * @param async True if the asynchronous operation is desired; false
+ * otherwise.
+ * @return status Status of the call.
+ */
+ setAsyncMode(
+ bool async
+ ) generates (
+ Status status
+ );
+
+ /**
+ * Input data for dequeueBuffer() specifying desired attributes of a buffer
+ * to dequeue.
+ *
+ * This structure contains 4 fields from
+ * +llndk libnativewindow#AHardwareBuffer_Desc.
+ *
+ * The `width` and `height` parameters must be no greater than the minimum
+ * of `GL_MAX_VIEWPORT_DIMS` and `GL_MAX_TEXTURE_SIZE` (see:
+ * glGetIntegerv()). An error due to invalid dimensions may not be reported
+ * until updateTexImage() is called.
+ *
+ * If `width` and `height` are both zero, the default dimensions shall be
+ * used. If only one of `width` and `height` is zero, dequeueBuffer() shall
+ * return `BAD_VALUE` in `status`.
+ *
+ * If `format` is zero, the default format shall be used.
+ *
+ * `usage` shall be merged with the usage flags set from the consumer side.
+ *
+ * @sa +llndk libnativewindow#AHardwareBuffer_Desc.
+ */
+ struct DequeueBufferInput {
+ uint32_t width;
+ uint32_t height;
+ uint32_t format;
+ uint64_t usage;
+ };
+
+ /**
+ * Output data for dequeueBuffer().
+ *
+ * A `DequeueBufferOutput` object returned from dequeueBuffer() shall be
+ * valid if and only if `status` returned from the same call is `OK`.
+ */
+ struct DequeueBufferOutput {
+ /**
+ * The number of frames that have elapsed since the buffer was last
+ * queued.
+ */
+ uint64_t bufferAge;
+ /**
+ * Whether the client must call requestBuffer().
+ */
+ bool bufferNeedsReallocation;
+ /**
+ * Whether the client must discard the mirrored slot-to-buffer
+ * mapping.
+ */
+ bool releaseAllBuffers;
+ /**
+ * Fence associated with the buffer.
+ *
+ * If this is an empty fence, the buffer may be written immediately;
+ * otherwise, the buffer must not be written to until the fence signals.
+ */
+ Fence fence;
+ };
+
+ /**
+ * Requests a new buffer slot for the client to use. Ownership of the slot
+ * is transfered to the client, meaning that the server shall not use the
+ * contents of the buffer associated with that slot.
+ *
+ * On success, @p status shall be `OK`, and @p output shall contain valid
+ * information of the call. Otherwise, the contents of @p output are
+ * meaningless.
+ *
+ * The slot index returned in @p slot may or may not contain a buffer
+ * (client-side). If the slot is empty, the client must call
+ * requestBuffer() to assign a new buffer to that slot.
+ *
+ * Once the client is done filling this buffer, it is expected to transfer
+ * buffer ownership back to the server with either cancelBuffer() on
+ * the dequeued slot or to fill in the contents of its associated buffer
+ * contents and call queueBuffer().
+ *
+ * If dequeueBuffer() returns with `output.releaseAllBuffers` set to `true`,
+ * the client is expected to release all of the mirrored slot-to-buffer
+ * mappings.
+ *
+ * If dequeueBuffer() returns with `output.bufferNeedsReallocation` set to
+ * `true`, the client is expected to call requestBuffer() immediately.
+ *
+ * The returned `output.fence` shall be updated to hold the fence associated
+ * with the buffer. The contents of the buffer must not be overwritten until
+ * the fence signals. If the fence is an empty fence, the buffer may be
+ * written immediately.
+ *
+ * This call shall block until a buffer is available to be dequeued. If
+ * both the producer and consumer are controlled by the app, then this call
+ * can never block and shall return `WOULD_BLOCK` in @p status if no buffer
+ * is available.
+ *
+ * If a dequeue operation shall cause certain conditions on the number of
+ * buffers to be violated (such as the maximum number of dequeued buffers),
+ * @p status shall be set to `INVALID_OPERATION` to indicate failure.
+ *
+ * If a dequeue operation cannot be completed within the time period
+ * previously set by setDequeueTimeout(), the return @p status shall
+ * `TIMED_OUT`.
+ *
+ * See @ref DequeueBufferInput for more information on the @p input
+ * parameter.
+ *
+ * @param input See #DequeueBufferInput for more information.
+ * @param status Status of the call.
+ * @param slot Slot index.
+ * @param output See #DequeueBufferOutput for more information.
+ *
+ * @sa queueBuffer(), requestBuffer().
+ */
+ dequeueBuffer(
+ DequeueBufferInput input
+ ) generates (
+ Status status,
+ int32_t slot,
+ DequeueBufferOutput output
+ );
+
+ /**
+ * Attempts to remove all ownership of the buffer in the given slot from the
+ * buffer queue.
+ *
+ * If this call succeeds, the slot shall be freed, and there shall be no way
+ * to obtain the buffer from this interface. The freed slot shall remain
+ * unallocated until either it is selected to hold a freshly allocated
+ * buffer in dequeueBuffer() or a buffer is attached to the slot. The buffer
+ * must have already been dequeued, and the caller must already possesses
+ * the buffer (i.e., must have called requestBuffer()).
+ *
+ * @param slot Slot index.
+ * @return status Status of the call.
+ */
+ detachBuffer(
+ int32_t slot
+ ) generates (
+ Status status
+ );
+
+ /**
+ * Dequeues a buffer slot, requests the buffer associated to the slot, and
+ * detaches it from the buffer queue. This is equivalent to calling
+ * dequeueBuffer(), requestBuffer(), and detachBuffer() in succession except
+ * for two things:
+ * 1. It is unnecessary to provide a #DequeueBufferInput object.
+ * 2. The call shall not block, since if it cannot find an appropriate
+ * buffer to return, it shall return an error instead.
+ *
+ * Only slots that are free but still contain a buffer shall be considered,
+ * and the oldest of those shall be returned. @p buffer is equivalent to the
+ * buffer that would be returned from requestBuffer(), and @p fence is
+ * equivalent to the fence that would be returned from dequeueBuffer().
+ *
+ * @return status Status of the call.
+ * @return buffer Buffer just released from the buffer queue.
+ * @return fence Fence associated to @p buffer.
+ *
+ * @sa dequeueBuffer(), requestBuffer(), detachBuffer().
+ */
+ detachNextBuffer(
+ ) generates (
+ Status status,
+ HardwareBuffer buffer,
+ Fence fence
+ );
+
+ /**
+ * Attempts to transfer ownership of a buffer to the buffer queue.
+ *
+ * If this call succeeds, it shall be as if this buffer was dequeued from the
+ * returned slot index. As such, this call shall fail if attaching this
+ * buffer would cause too many buffers to be simultaneously dequeued.
+ *
+ * If the returned @p releaseAllBuffers is `true`, the caller is expected to
+ * release all of the mirrored slot-to-buffer mappings.
+ *
+ * See dequeueBuffer() for conditions that may cause the call to fail.
+ *
+ * @param buffer Buffer to attach to the buffer queue.
+ * @return status Status of the call.
+ * @return slot Slot index assigned to @p buffer.
+ * @return releaseAllBuffers Whether the caller is expected to release all
+ * of the mirrored slot-to-buffer mappings.
+ *
+ * @sa dequeueBuffer().
+ */
+ attachBuffer(
+ HardwareBuffer buffer
+ ) generates (
+ Status status,
+ int32_t slot,
+ bool releaseAllBuffers
+ );
+
+ struct QueueBufferInput {
+ /**
+ * Timestamp in nanoseconds.
+ */
+ int64_t timestamp;
+ /**
+ * Whether the timestamp was synthesized at queue time.
+ */
+ bool isAutoTimestamp;
+ /**
+ * Dataspace of the contents.
+ *
+ * @sa +ndk libnativewindow#ADataSpace.
+ */
+ int32_t dataSpace;
+ /**
+ * Crop rectangle that is used as a hint to the consumer.
+ */
+ Rect crop;
+ /**
+ * Transformation flags.
+ *
+ * @sa +ndk libnativewindow#ANativeWindowTransform.
+ */
+ int32_t transform;
+ /**
+ * The sticky transform set in Surface (only used by the LEGACY camera
+ * mode).
+ *
+ * @sa +ndk libnativewindow#ANativeWindowTransform.
+ */
+ int32_t stickyTransform;
+ /**
+ * Fence that the consumer must wait on before reading the buffer. An
+ * empty fence indicates that the buffer is ready immediately.
+ */
+ Fence fence;
+ /**
+ * List of rectangular pieces covering the damage region.
+ */
+ vec<Rect> surfaceDamage;
+ };
+
+ /**
+ * Information about the queued buffer. `QueueBufferOutput` is used in both
+ * queueBuffer() and connect().
+ */
+ struct QueueBufferOutput {
+ /**
+ * Default width of a buffer in the buffer queue.
+ */
+ uint32_t width;
+ /**
+ * Default height of a buffer in the buffer queue.
+ */
+ uint32_t height;
+ /**
+ * The transform hint of the buffer queue.
+ *
+ * @sa +ndk libnativewindow#ANativeWindowTransform.
+ */
+ int32_t transformHint;
+ /**
+ * The number of pending buffers in the buffer queue. If this is
+ * returned from queueBuffer(), the number shall include the buffer that
+ * has just been queued.
+ */
+ uint32_t numPendingBuffers;
+ /**
+ * The frame number of the next frame. The buffer queue maintains this
+ * number and makes sure that it is increasing for every successful
+ * queueBuffer() call.
+ */
+ uint64_t nextFrameNumber;
+ /**
+ * After a successful queueBuffer() call, #bufferReplaced shall be set to
+ * true if the queued buffer replaced a previously queued buffer that
+ * has not been consumed.
+ */
+ bool bufferReplaced;
+ };
+
+ /**
+ * Indicates that the client has finished filling in the contents of the
+ * buffer associated with slot and transfers ownership of that slot back to
+ * the buffer queue.
+ *
+ * @p status may be set to `BAD_VALUE` if any of the following conditions
+ * hold:
+ * - The buffer queue is operating in the asynchronous mode, and the
+ * buffer count was smaller than the maximum number of buffers that can
+ * be allocated at once.
+ * - @p slot is an invalid slot index, i.e., the slot is not owned by the
+ * client by previously calling dequeueBuffer(), requestBuffer() or
+ * attachBuffer().
+ * - The crop rectangle is not contained in the buffer.
+ *
+ * Upon success, the output shall be filled with meaningful values
+ * (refer to the documentation of @ref QueueBufferOutput).
+ *
+ * @param slot Slot index.
+ * @param input See @ref QueueBufferInput.
+ * @return status Status of the call.
+ * @return output See @ref QueueBufferOutput.
+ *
+ * @sa #QueueBufferInput, #QueueBufferOutput, dequeueBuffer().
+ */
+ queueBuffer(
+ int32_t slot,
+ QueueBufferInput input
+ ) generates (
+ Status status,
+ QueueBufferOutput output
+ );
+
+ /**
+ * Indicates that the client does not wish to fill in the buffer associated
+ * with the slot and transfers ownership of the slot back to the server. The
+ * buffer is not queued for use by the consumer.
+ *
+ * If @p fence is not an empty fence, the buffer shall not be overwritten
+ * until the fence signals. @p fence is usually obtained from
+ * dequeueBuffer().
+ *
+ * @param slot Slot index.
+ * @param fence Fence for the canceled buffer.
+ * @return status Status of the call.
+ */
+ cancelBuffer(
+ int32_t slot,
+ Fence fence
+ ) generates (
+ Status status
+ );
+
+ /**
+ * Retrieves information for this surface.
+ *
+ * @param what What to query. @p what must be one of the values in
+ * +llndk libnativewindow#ANativeWindowQuery.
+ * @return status Status of the call.
+ * @return value The value queried. The set of possible values depends on
+ * the value of @p what.
+ *
+ * @sa +llndk libnativewindow#ANativeWindowQuery.
+ */
+ query(
+ int32_t what
+ ) generates (
+ int32_t result,
+ int32_t value
+ );
+
+ /**
+ * Attempts to connect the client as a producer of the buffer queue.
+ * This method must be called before any other methods in this interface.
+ *
+ * If the buffer queue does not have a consumer ready (connected), the
+ * return @p status shall be `NO_INIT`.
+ *
+ * If any of the following conditions hold, the error code `BAD_VALUE` shall
+ * be reported in @p status:
+ * - The producer is already connected.
+ * - The number of available slots cannot be adjusted to accommodate the
+ * supplied value of @p producerControlledByApp.
+ *
+ * @param listener An optional callback object that can be provided if the
+ * client wants to be notified when the consumer releases a buffer back
+ * to the buffer queue.
+ * @param api How the client shall write to buffers.
+ * @param producerControlledByApp `true` if the producer is hosted by an
+ * untrusted process (typically application-forked processes). If both
+ * the producer and the consumer are controlled by app, the buffer queue
+ * shall operate in the asynchronous mode regardless of the async flag
+ * set by setAsyncMode().
+ * @return status Status of the call.
+ * @return output See #QueueBufferOutput for more information.
+ *
+ * @sa #QueueBufferOutput, disconnect(), setAsyncMode().
+ */
+ connect(
+ IProducerListener listener,
+ ConnectionType api,
+ bool producerControlledByApp
+ ) generates (
+ Status status,
+ QueueBufferOutput output
+ );
+
+ /**
+ * Attempts to disconnect the client from the producer end of the buffer
+ * queue.
+ *
+ * Calling this method shall cause any subsequent calls to other
+ * @ref IGraphicBufferProducer methods apart from connect() to fail.
+ * A successful connect() call afterwards may allow other methods to succeed
+ * again.
+ *
+ * Disconnecting from an abandoned buffer queue is legal and is considered a
+ * no-op.
+ *
+ * @param api The type of connection to disconnect. Supplying the value of
+ * `CURRENTLY_CONNECTED` to @p api has the same effect as supplying the
+ * current connection type. If the producer end is not connected,
+ * supplying `CURRENTLY_CONNECTED` shall result in a successful no-op
+ * call.
+ * @return status Status of the call.
+ *
+ * @sa connect().
+ */
+ disconnect(
+ ConnectionType api
+ ) generates (
+ Status status
+ );
+
+ /**
+ * Allocates buffers based on the given dimensions, format and usage.
+ *
+ * This function shall allocate up to the maximum number of buffers
+ * permitted by the current buffer queue configuration. It shall use the
+ * given format, dimensions, and usage bits, which are interpreted in the
+ * same way as for dequeueBuffer(), and the async flag must be set the same
+ * way as for dequeueBuffer() to ensure that the correct number of buffers
+ * are allocated. This is most useful to avoid an allocation delay during
+ * dequeueBuffer(). If there are already the maximum number of buffers
+ * allocated, this function has no effect.
+ *
+ * A value of 0 in @p width, @p height or @p format indicates that the
+ * buffer queue can pick the default value.
+ *
+ * @param width Width of buffers to allocate.
+ * @param height Height of buffers to allocate.
+ * @param format Format of buffers to allocate.
+ * @param usage Usage of bufferes to allocate.
+ * @return status Status of the call.
+ */
+ allocateBuffers(
+ uint32_t width,
+ uint32_t height,
+ uint32_t format,
+ uint64_t usage
+ ) generates (
+ Status status
+ );
+
+ /**
+ * Sets whether dequeueBuffer() is allowed to allocate new buffers.
+ *
+ * Normally dequeueBuffer() does not discriminate between free slots which
+ * already have an allocated buffer and those which do not, and shall
+ * allocate a new buffer if the slot doesn't have a buffer or if the slot's
+ * buffer doesn't match the requested size, format, or usage. This method
+ * allows the producer to restrict the eligible slots to those which already
+ * have an allocated buffer of the correct size, format, and usage. If no
+ * eligible slot is available, dequeueBuffer() shall block or return an
+ * error.
+ *
+ * @param allow Whether to allow new buffers to be allocated in
+ * dequeueBuffer().
+ * @return status Status of the call.
+ */
+ allowAllocation(
+ bool allow
+ ) generates (
+ Status status
+ );
+
+ /**
+ * Sets the current generation number of the buffer queue.
+ *
+ * This generation number shall be inserted into any buffers allocated by the
+ * buffer queue, and any attempts to attach a buffer with a different
+ * generation number shall fail. Buffers already in the queue are not
+ * affected and shall retain their current generation number. The generation
+ * number defaults to 0, i.e., buffers allocated before the first call to
+ * setGenerationNumber() shall be given 0 as their generation numbers.
+ *
+ * @param generationNumber New generation number. The client must make sure
+ * that @p generationNumber is different from the previous generation
+ * number if it wants to deprecate old buffers.
+ * @return status Status of the call.
+ */
+ setGenerationNumber(
+ uint32_t generationNumber
+ ) generates (
+ Status status
+ );
+
+ /**
+ * Sets how long dequeueBuffer() shall wait for a buffer to become available
+ * before returning an error `TIMED_OUT`.
+ *
+ * This timeout also affects the attachBuffer() call, which shall block if
+ * there is not a free slot available into which the attached buffer can be
+ * placed.
+ *
+ * By default, the buffer queue shall wait forever, which is equivalent to
+ * setting @p timeoutNs equal to any negative number (such as `-1`). If
+ * @p timeoutNs is non-negative, setDequeueTimeout() shall disable
+ * non-blocking mode and its corresponding spare buffer (which is used to
+ * ensure a buffer is always available).
+ *
+ * Changing the dequeue timeout may affect the number of buffers. (See
+ * setAsyncMode().) If the adjustment to the number of buffers inside the
+ * buffer queue is not feasible, @p status shall be set to `BAD_VALUE`.
+ *
+ * @param timeoutNs Amount of time dequeueBuffer() is allowed to block
+ * before returning `TIMED_OUT`. If @p timeoutNs is negative,
+ * dequeueBuffer() shall not be able to return `TIMED_OUT`. Instead, it
+ * may block forever or return `WOULD_BLOCK`.
+ * @return status Status of the call.
+ *
+ * @sa dequeueBuffer(), setAsyncMode(), query().
+ */
+ setDequeueTimeout(
+ int64_t timeoutNs
+ ) generates (
+ Status status
+ );
+
+ /**
+ * Returns a unique id for this buffer queue.
+ *
+ * @return id System-wide unique id of the buffer queue.
+ */
+ getUniqueId(
+ ) generates (
+ uint64_t id
+ );
+
+ /**
+ * Returns the name of the connected consumer.
+ *
+ * \note This is used for debugging only.
+ *
+ * @return name Name of the consumer.
+ */
+ getConsumerName(
+ ) generates (
+ string name
+ );
+
+};
+
diff --git a/graphics/bufferqueue/2.0/IProducerListener.hal b/graphics/bufferqueue/2.0/IProducerListener.hal
new file mode 100644
index 0000000..bc478ed
--- /dev/null
+++ b/graphics/bufferqueue/2.0/IProducerListener.hal
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2018 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.graphics.bufferqueue@2.0;
+
+/**
+ * Listener interface.
+ */
+interface IProducerListener {
+ /**
+ * Notifies the listener when buffers are released.
+ *
+ * This function is usually called by the consumer.
+ *
+ * @param count The number of buffers released (since the last call to
+ * onBufferReleased()).
+ */
+ oneway onBuffersReleased(uint32_t count);
+};
+
diff --git a/graphics/bufferqueue/2.0/types.hal b/graphics/bufferqueue/2.0/types.hal
new file mode 100644
index 0000000..f6bc2d9
--- /dev/null
+++ b/graphics/bufferqueue/2.0/types.hal
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2018 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.graphics.bufferqueue@2.0;
+
+/**
+ * Possible return values from a function call.
+ */
+enum Status : int32_t {
+ /**
+ * The call succeeds.
+ */
+ OK = 0,
+ /**
+ * The function fails allocate memory.
+ */
+ NO_MEMORY = -12,
+ /**
+ * The buffer queue has been abandoned, no consumer is connected, or no
+ * producer is connected at the time of the call.
+ */
+ NO_INIT = -19,
+ /**
+ * Some of the provided input arguments are invalid.
+ */
+ BAD_VALUE = -22,
+ /**
+ * An unexpected death of some object prevents the operation from
+ * continuing.
+ *
+ * @note This status value is different from a transaction failure, which
+ * should be detected by isOk().
+ */
+ DEAD_OBJECT = -32,
+ /**
+ * The internal state of the buffer queue does not permit the operation.
+ */
+ INVALID_OPERATION = -38,
+ /**
+ * The call fails to finish within the specified time limit.
+ */
+ TIMED_OUT = -110,
+ /**
+ * The buffer queue is operating in a non-blocking mode, but the call cannot
+ * be completed without blocking.
+ */
+ WOULD_BLOCK = 0xfffffffb,
+ /**
+ * The call fails because of a reason not listed above.
+ */
+ UNKNOWN_ERROR = 0xffffffff,
+};
+
+/**
+ * Special values for a slot index.
+ */
+enum SlotIndex : int32_t {
+ /**
+ * Invalid/unspecified slot index. This may be returned from a function that
+ * returns a slot index if the call is unsuccessful.
+ */
+ INVALID = -1,
+ UNSPECIFIED = -1,
+};
+
+/**
+ * An "empty" fence can be an empty handle (containing no fds and no ints) or a
+ * fence with one fd that is equal to -1 and no ints.
+ *
+ * A valid fence is an empty fence or a native handle with exactly one fd and no
+ * ints.
+ */
+typedef handle Fence;
+
+/**
+ * How buffers shall be produced. One of these values must be provided in a call
+ * to IGraphicBufferProducer::connect() and
+ * IGraphicBufferProducer::disconnect().
+ */
+enum ConnectionType : int32_t {
+ /**
+ * This value can be used only as an input to
+ * IGraphicBufferProducer::disconnect().
+ */
+ CURRENTLY_CONNECTED = -1,
+ /**
+ * Buffers shall be queued by EGL via `eglSwapBuffers()` after being filled
+ * using OpenGL ES.
+ */
+ EGL = 1,
+ /**
+ * Buffers shall be queued after being filled using the CPU.
+ */
+ CPU = 2,
+ /**
+ * Buffers shall be queued by Stagefright after being filled by a video
+ * decoder. The video decoder can either be a software or hardware decoder.
+ */
+ MEDIA = 3,
+ /**
+ * Buffers shall be queued by the camera HAL.
+ */
+ CAMERA = 4,
+};
+
+
diff --git a/graphics/common/1.2/Android.bp b/graphics/common/1.2/Android.bp
index a86f3b5..a3ebdbf 100644
--- a/graphics/common/1.2/Android.bp
+++ b/graphics/common/1.2/Android.bp
@@ -15,7 +15,9 @@
"android.hardware.graphics.common@1.1",
],
types: [
+ "ColorMode",
"Dataspace",
+ "HardwareBuffer",
],
gen_java: true,
gen_java_constants: true,
diff --git a/graphics/common/1.2/types.hal b/graphics/common/1.2/types.hal
index cf4e34a..15f2c14 100644
--- a/graphics/common/1.2/types.hal
+++ b/graphics/common/1.2/types.hal
@@ -51,3 +51,39 @@
*/
DISPLAY_BT2020 = 13,
};
+
+/**
+ * HIDL counterpart of `AHardwareBuffer_Desc`.
+ *
+ * An `AHardwareBuffer_Desc` object can be converted to and from a
+ * `HardwareBufferDescription` object by `memcpy()`.
+ *
+ * @sa +ndk libnativewindow#AHardwareBuffer_Desc.
+ */
+typedef uint32_t[10] HardwareBufferDescription;
+
+/**
+ * HIDL counterpart of `AHardwareBuffer`.
+ *
+ * AHardwareBuffer_createFromHandle() can be used to convert a `HardwareBuffer`
+ * object to an `AHardwareBuffer` object.
+ *
+ * Conversely, AHardwareBuffer_getNativeHandle() can be used to extract a native
+ * handle from an `AHardwareBuffer` object. Paired with `AHardwareBuffer_Desc`,
+ * AHardwareBuffer_getNativeHandle() can be used to convert between
+ * `HardwareBuffer` and `AHardwareBuffer`.
+ *
+ * @sa +ndk libnativewindow#AHardwareBuffer".
+ */
+struct HardwareBuffer {
+ HardwareBufferDescription description;
+ handle nativeHandle;
+};
+
+/**
+ * HIDL counterpart of `ARect`.
+ *
+ * @sa +ndk libarect_headers#ARect.
+ */
+typedef int32_t[4] Rect;
+
diff --git a/neuralnetworks/1.0/vts/functional/Android.bp b/neuralnetworks/1.0/vts/functional/Android.bp
index 18f35c1..ffba45c 100644
--- a/neuralnetworks/1.0/vts/functional/Android.bp
+++ b/neuralnetworks/1.0/vts/functional/Android.bp
@@ -28,6 +28,7 @@
"android.hardware.neuralnetworks@1.2",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
+ "libgmock",
"libhidlmemory",
"libneuralnetworks_utils",
],
@@ -55,6 +56,7 @@
"android.hardware.neuralnetworks@1.2",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
+ "libgmock",
"libhidlmemory",
"libneuralnetworks_utils",
"VtsHalNeuralnetworksTest_utils",
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
index b8046c7..cc19978 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
@@ -36,16 +36,17 @@
namespace generated_tests {
using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::test_helper::compare;
+using ::test_helper::expectMultinomialDistributionWithinTolerance;
using ::test_helper::filter;
+using ::test_helper::Float32Operands;
using ::test_helper::for_all;
using ::test_helper::for_each;
-using ::test_helper::resize_accordingly;
-using ::test_helper::MixedTyped;
-using ::test_helper::MixedTypedExampleType;
-using ::test_helper::Float32Operands;
using ::test_helper::Int32Operands;
+using ::test_helper::MixedTyped;
+using ::test_helper::MixedTypedExample;
using ::test_helper::Quant8Operands;
-using ::test_helper::compare;
+using ::test_helper::resize_accordingly;
template <typename T>
void copy_back_(MixedTyped* dst, const std::vector<RequestArgument>& ra, char* src) {
@@ -66,7 +67,7 @@
// Top level driver for models and examples generated by test_generator.py
// Test driver for those generated from ml/nn/runtime/test/spec
void EvaluatePreparedModel(sp<IPreparedModel>& preparedModel, std::function<bool(int)> is_ignored,
- const std::vector<MixedTypedExampleType>& examples, float fpAtol = 1e-5f,
+ const std::vector<MixedTypedExample>& examples, float fpAtol = 1e-5f,
float fpRtol = 1e-5f) {
const uint32_t INPUT = 0;
const uint32_t OUTPUT = 1;
@@ -75,8 +76,8 @@
for (auto& example : examples) {
SCOPED_TRACE(example_no++);
- const MixedTyped& inputs = example.first;
- const MixedTyped& golden = example.second;
+ const MixedTyped& inputs = example.operands.first;
+ const MixedTyped& golden = example.operands.second;
std::vector<RequestArgument> inputs_info, outputs_info;
uint32_t inputSize = 0, outputSize = 0;
@@ -176,12 +177,15 @@
// We want "close-enough" results for float
compare(filtered_golden, filtered_test, fpAtol, fpRtol);
+
+ if (example.expectedMultinomialDistributionTolerance > 0) {
+ expectMultinomialDistributionWithinTolerance(test, example);
+ }
}
}
void Execute(const sp<V1_0::IDevice>& device, std::function<V1_0::Model(void)> create_model,
- std::function<bool(int)> is_ignored,
- const std::vector<MixedTypedExampleType>& examples) {
+ std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples) {
V1_0::Model model = create_model();
// see if service can handle model
@@ -225,8 +229,7 @@
}
void Execute(const sp<V1_1::IDevice>& device, std::function<V1_1::Model(void)> create_model,
- std::function<bool(int)> is_ignored,
- const std::vector<MixedTypedExampleType>& examples) {
+ std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples) {
V1_1::Model model = create_model();
// see if service can handle model
@@ -277,8 +280,7 @@
// TODO: Reduce code duplication.
void Execute(const sp<V1_2::IDevice>& device, std::function<V1_2::Model(void)> create_model,
- std::function<bool(int)> is_ignored,
- const std::vector<MixedTypedExampleType>& examples) {
+ std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples) {
V1_2::Model model = create_model();
// see if service can handle model
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp
index d84479c..ac1ae60 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp
@@ -31,9 +31,9 @@
namespace neuralnetworks {
namespace generated_tests {
-using ::test_helper::MixedTypedExampleType;
+using ::test_helper::MixedTypedExample;
extern void Execute(const sp<V1_0::IDevice>&, std::function<V1_0::Model(void)>,
- std::function<bool(int)>, const std::vector<MixedTypedExampleType>&);
+ std::function<bool(int)>, const std::vector<MixedTypedExample>&);
} // namespace generated_tests
namespace V1_0 {
@@ -43,9 +43,7 @@
using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
using ::android::nn::allocateSharedMemory;
-
-// Mixed-typed examples
-typedef test_helper::MixedTypedExampleType MixedTypedExample;
+using ::test_helper::MixedTypedExample;
// in frameworks/ml/nn/runtime/tests/generated/
#include "all_generated_V1_0_vts_tests.cpp"
diff --git a/neuralnetworks/1.0/vts/functional/Models.h b/neuralnetworks/1.0/vts/functional/Models.h
index 751ab32..268e671 100644
--- a/neuralnetworks/1.0/vts/functional/Models.h
+++ b/neuralnetworks/1.0/vts/functional/Models.h
@@ -30,7 +30,7 @@
namespace vts {
namespace functional {
-using MixedTypedExample = test_helper::MixedTypedExampleType;
+using MixedTypedExample = test_helper::MixedTypedExample;
#define FOR_EACH_TEST_MODEL(FN) \
FN(add_broadcast_quant8) \
diff --git a/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp
index 09c1878..1d3dee3 100644
--- a/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp
@@ -36,9 +36,9 @@
using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
using ::android::hidl::memory::V1_0::IMemory;
-using test_helper::MixedTyped;
-using test_helper::MixedTypedExampleType;
using test_helper::for_all;
+using test_helper::MixedTyped;
+using test_helper::MixedTypedExample;
///////////////////////// UTILITY FUNCTIONS /////////////////////////
@@ -151,15 +151,15 @@
///////////////////////////// ENTRY POINT //////////////////////////////////
-std::vector<Request> createRequests(const std::vector<MixedTypedExampleType>& examples) {
+std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples) {
const uint32_t INPUT = 0;
const uint32_t OUTPUT = 1;
std::vector<Request> requests;
- for (auto& example : examples) {
- const MixedTyped& inputs = example.first;
- const MixedTyped& outputs = example.second;
+ for (const MixedTypedExample& example : examples) {
+ const MixedTyped& inputs = example.operands.first;
+ const MixedTyped& outputs = example.operands.second;
std::vector<RequestArgument> inputs_info, outputs_info;
uint32_t inputSize = 0, outputSize = 0;
diff --git a/neuralnetworks/1.0/vts/functional/ValidationTests.cpp b/neuralnetworks/1.0/vts/functional/ValidationTests.cpp
index 98fc1c5..d3cbcff 100644
--- a/neuralnetworks/1.0/vts/functional/ValidationTests.cpp
+++ b/neuralnetworks/1.0/vts/functional/ValidationTests.cpp
@@ -27,7 +27,7 @@
namespace functional {
// forward declarations
-std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples);
+std::vector<Request> createRequests(const std::vector<::test_helper::MixedTypedExample>& examples);
// generate validation tests
#define VTS_CURRENT_TEST_CASE(TestName) \
diff --git a/neuralnetworks/1.1/vts/functional/Android.bp b/neuralnetworks/1.1/vts/functional/Android.bp
index 52a804a..a1c0f1f 100644
--- a/neuralnetworks/1.1/vts/functional/Android.bp
+++ b/neuralnetworks/1.1/vts/functional/Android.bp
@@ -31,6 +31,7 @@
"android.hardware.neuralnetworks@1.2",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
+ "libgmock",
"libhidlmemory",
"libneuralnetworks_utils",
"VtsHalNeuralnetworksTest_utils",
diff --git a/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp b/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp
index 95c2b1a..1f49904 100644
--- a/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp
+++ b/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp
@@ -31,9 +31,9 @@
namespace neuralnetworks {
namespace generated_tests {
-using ::test_helper::MixedTypedExampleType;
+using ::test_helper::MixedTypedExample;
extern void Execute(const sp<V1_1::IDevice>&, std::function<V1_1::Model(void)>,
- std::function<bool(int)>, const std::vector<MixedTypedExampleType>&);
+ std::function<bool(int)>, const std::vector<MixedTypedExample>&);
} // namespace generated_tests
namespace V1_1 {
@@ -43,9 +43,7 @@
using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
using ::android::nn::allocateSharedMemory;
-
-// Mixed-typed examples
-typedef generated_tests::MixedTypedExampleType MixedTypedExample;
+using ::test_helper::MixedTypedExample;
// in frameworks/ml/nn/runtime/tests/generated/
#include "all_generated_V1_0_vts_tests.cpp"
diff --git a/neuralnetworks/1.1/vts/functional/Models.h b/neuralnetworks/1.1/vts/functional/Models.h
index cc0fac1..62bc95e 100644
--- a/neuralnetworks/1.1/vts/functional/Models.h
+++ b/neuralnetworks/1.1/vts/functional/Models.h
@@ -31,7 +31,7 @@
namespace vts {
namespace functional {
-using MixedTypedExample = test_helper::MixedTypedExampleType;
+using MixedTypedExample = test_helper::MixedTypedExample;
#define FOR_EACH_TEST_MODEL(FN) \
FN(add) \
diff --git a/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp
index 687b760..e7d96c7 100644
--- a/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp
@@ -36,9 +36,9 @@
using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
using ::android::hidl::memory::V1_0::IMemory;
-using test_helper::MixedTyped;
-using test_helper::MixedTypedExampleType;
using test_helper::for_all;
+using test_helper::MixedTyped;
+using test_helper::MixedTypedExample;
///////////////////////// UTILITY FUNCTIONS /////////////////////////
@@ -152,15 +152,15 @@
///////////////////////////// ENTRY POINT //////////////////////////////////
-std::vector<Request> createRequests(const std::vector<MixedTypedExampleType>& examples) {
+std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples) {
const uint32_t INPUT = 0;
const uint32_t OUTPUT = 1;
std::vector<Request> requests;
for (auto& example : examples) {
- const MixedTyped& inputs = example.first;
- const MixedTyped& outputs = example.second;
+ const MixedTyped& inputs = example.operands.first;
+ const MixedTyped& outputs = example.operands.second;
std::vector<RequestArgument> inputs_info, outputs_info;
uint32_t inputSize = 0, outputSize = 0;
diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp
index 2dc19cc..09d0dc3 100644
--- a/neuralnetworks/1.2/vts/functional/Android.bp
+++ b/neuralnetworks/1.2/vts/functional/Android.bp
@@ -31,6 +31,7 @@
"android.hardware.neuralnetworks@1.2",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
+ "libgmock",
"libhidlmemory",
"libneuralnetworks_utils",
"VtsHalNeuralnetworksTest_utils",
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp
index 662c531..e87fa6b 100644
--- a/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp
@@ -31,9 +31,9 @@
namespace neuralnetworks {
namespace generated_tests {
-using ::test_helper::MixedTypedExampleType;
+using ::test_helper::MixedTypedExample;
extern void Execute(const sp<V1_2::IDevice>&, std::function<V1_2::Model(void)>,
- std::function<bool(int)>, const std::vector<MixedTypedExampleType>&);
+ std::function<bool(int)>, const std::vector<MixedTypedExample>&);
} // namespace generated_tests
namespace V1_2 {
@@ -43,9 +43,7 @@
using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
using ::android::nn::allocateSharedMemory;
-
-// Mixed-typed examples
-typedef generated_tests::MixedTypedExampleType MixedTypedExample;
+using ::test_helper::MixedTypedExample;
// in frameworks/ml/nn/runtime/tests/generated/
#include "all_generated_V1_0_vts_tests.cpp"
diff --git a/neuralnetworks/1.2/vts/functional/Models.h b/neuralnetworks/1.2/vts/functional/Models.h
index f3769bc..2d512fe 100644
--- a/neuralnetworks/1.2/vts/functional/Models.h
+++ b/neuralnetworks/1.2/vts/functional/Models.h
@@ -32,7 +32,7 @@
namespace vts {
namespace functional {
-using MixedTypedExample = test_helper::MixedTypedExampleType;
+using MixedTypedExample = test_helper::MixedTypedExample;
#define FOR_EACH_TEST_MODEL(FN) \
FN(add) \
@@ -243,6 +243,7 @@
FN(pad_float_1) \
FN(pad_float_1_relaxed) \
FN(pad_relaxed) \
+ FN(random_multinomial) \
FN(relu1_float_1) \
FN(relu1_float_1_relaxed) \
FN(relu1_float_2) \
diff --git a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
index b840199..c1c6e55 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
@@ -479,8 +479,22 @@
///////////////////////// ADD OPERATION INPUT /////////////////////////
+static bool addOperationInputSkip(const Operation& operation) {
+ // Skip addOperationInputTest for the following operations.
+ // L2_NORMALIZATION, LOCAL_RESPONSE_NORMALIZATION, SOFTMAX can have an optional axis parameter.
+ if (operation.type == OperationType::L2_NORMALIZATION ||
+ operation.type == OperationType::LOCAL_RESPONSE_NORMALIZATION ||
+ operation.type == OperationType::SOFTMAX) {
+ return true;
+ }
+ return false;
+}
+
static void addOperationInputTest(const sp<IDevice>& device, const Model& model) {
for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+ if (addOperationInputSkip(model.operations[operation])) {
+ continue;
+ }
const std::string message = "addOperationInputTest: operation " + std::to_string(operation);
validate(device, message, model, [operation](Model* model) {
uint32_t index = addOperand(model, OperandLifeTime::MODEL_INPUT);
diff --git a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
index f4476fa..b663535 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
@@ -38,7 +38,7 @@
using ::android::hidl::memory::V1_0::IMemory;
using test_helper::for_all;
using test_helper::MixedTyped;
-using test_helper::MixedTypedExampleType;
+using test_helper::MixedTypedExample;
///////////////////////// UTILITY FUNCTIONS /////////////////////////
@@ -152,15 +152,15 @@
///////////////////////////// ENTRY POINT //////////////////////////////////
-std::vector<Request> createRequests(const std::vector<MixedTypedExampleType>& examples) {
+std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples) {
const uint32_t INPUT = 0;
const uint32_t OUTPUT = 1;
std::vector<Request> requests;
for (auto& example : examples) {
- const MixedTyped& inputs = example.first;
- const MixedTyped& outputs = example.second;
+ const MixedTyped& inputs = example.operands.first;
+ const MixedTyped& outputs = example.operands.second;
std::vector<RequestArgument> inputs_info, outputs_info;
uint32_t inputSize = 0, outputSize = 0;
diff --git a/power/stats/1.0/IPowerStats.hal b/power/stats/1.0/IPowerStats.hal
index d75e170..b5b3cc9 100644
--- a/power/stats/1.0/IPowerStats.hal
+++ b/power/stats/1.0/IPowerStats.hal
@@ -50,10 +50,13 @@
* asynchronous.
*
* @param timeMs Time(in ms) for which energyData should be streamed
- * @return mqDesc Unsynchronous Fast Message Queue descriptor - One
- * writer(power.stats HAL) multiple readers are supported. Reader
- * should read faster than writer otherwise data might be
- * overwritten. Data is present in following format in the queue:
+ * @param samplingRate Frequency(in Hz) at which samples should be
+ * captured. If the requested sampling rate is not supported then
+ * SUCCESS is returned and numSamples are reported back according
+ * to the supported sampling rate.
+ * @return mqDesc Blocking Synchronous Fast Message Queue descriptor - One
+ * writer(power.stats HAL) and one reader are supported. Data is
+ * present in the following format in the queue:
* +-----------------------+ <--
* | EnergyData for rail 1 | |
* +-----------------------+ |
@@ -87,9 +90,10 @@
* @return numSamples Number of samples which will be generated in timeMs.
* @return railsPerSample Number of rails measured per sample.
* @return status SUCCESS on success or FILESYSTEM_ERROR on filesystem
- * nodes access or NOT_SUPPORTED if feature is not enabled.
+ * nodes access or NOT_SUPPORTED if feature is not enabled or
+ * INSUFFICIENT_RESOURCES if there are not enough resources.
*/
- streamEnergyData(uint32_t timeMs)
- generates(fmq_unsync<EnergyData> mqDesc, uint32_t numSamples,
+ streamEnergyData(uint32_t timeMs, uint32_t samplingRate)
+ generates(fmq_sync<EnergyData> mqDesc, uint32_t numSamples,
uint32_t railsPerSample, Status status);
};
diff --git a/power/stats/1.0/types.hal b/power/stats/1.0/types.hal
index 826c29b..703e542 100644
--- a/power/stats/1.0/types.hal
+++ b/power/stats/1.0/types.hal
@@ -20,6 +20,7 @@
NOT_SUPPORTED = 1,
INVALID_INPUT = 2,
FILESYSTEM_ERROR = 3,
+ INSUFFICIENT_RESOURCES = 4,
};
struct RailInfo {
diff --git a/sensors/2.0/default/Android.bp b/sensors/2.0/default/Android.bp
new file mode 100644
index 0000000..11612d3
--- /dev/null
+++ b/sensors/2.0/default/Android.bp
@@ -0,0 +1,37 @@
+//
+// Copyright (C) 2018 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.sensors@2.0-service",
+ defaults: ["hidl_defaults"],
+ vendor: true,
+ relative_install_path: "hw",
+ srcs: [
+ "service.cpp",
+ "Sensor.cpp",
+ "Sensors.cpp",
+ ],
+ init_rc: ["android.hardware.sensors@2.0-service.rc"],
+ shared_libs: [
+ "android.hardware.sensors@1.0",
+ "android.hardware.sensors@2.0",
+ "libcutils",
+ "libfmq",
+ "libhidlbase",
+ "libhidltransport",
+ "liblog",
+ "libutils",
+ ],
+}
diff --git a/sensors/2.0/default/OWNERS b/sensors/2.0/default/OWNERS
new file mode 100644
index 0000000..2031d84
--- /dev/null
+++ b/sensors/2.0/default/OWNERS
@@ -0,0 +1,2 @@
+bduddie@google.com
+bstack@google.com
diff --git a/sensors/2.0/default/Sensor.cpp b/sensors/2.0/default/Sensor.cpp
new file mode 100644
index 0000000..21c1591
--- /dev/null
+++ b/sensors/2.0/default/Sensor.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2018 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 "Sensor.h"
+
+#include <utils/SystemClock.h>
+
+namespace android {
+namespace hardware {
+namespace sensors {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::sensors::V1_0::SensorFlagBits;
+using ::android::hardware::sensors::V1_0::SensorStatus;
+
+Sensor::Sensor(ISensorsEventCallback* callback)
+ : mIsEnabled(false), mSamplingPeriodNs(0), mLastSampleTimeNs(0), mCallback(callback) {
+ mRunThread = std::thread(startThread, this);
+}
+
+Sensor::~Sensor() {
+ mStopThread = true;
+ mIsEnabled = false;
+ mWaitCV.notify_all();
+ mRunThread.join();
+}
+
+const SensorInfo& Sensor::getSensorInfo() const {
+ return mSensorInfo;
+}
+
+void Sensor::batch(int32_t samplingPeriodNs) {
+ if (samplingPeriodNs < mSensorInfo.minDelay * 1000) {
+ samplingPeriodNs = mSensorInfo.minDelay * 1000;
+ } else if (samplingPeriodNs > mSensorInfo.maxDelay * 1000) {
+ samplingPeriodNs = mSensorInfo.maxDelay * 1000;
+ }
+
+ if (mSamplingPeriodNs != samplingPeriodNs) {
+ mSamplingPeriodNs = samplingPeriodNs;
+ // Wake up the 'run' thread to check if a new event should be generated now
+ mWaitCV.notify_all();
+ }
+}
+
+void Sensor::activate(bool enable) {
+ if (mIsEnabled != enable) {
+ mIsEnabled = enable;
+ mWaitCV.notify_all();
+ }
+}
+
+void Sensor::startThread(Sensor* sensor) {
+ sensor->run();
+}
+
+void Sensor::run() {
+ std::mutex runMutex;
+ std::unique_lock<std::mutex> runLock(runMutex);
+ constexpr int64_t kNanosecondsInSeconds = 1000 * 1000 * 1000;
+
+ while (!mStopThread) {
+ if (!mIsEnabled) {
+ mWaitCV.wait(runLock, [&] { return mIsEnabled || mStopThread; });
+ } else {
+ timespec curTime;
+ clock_gettime(CLOCK_REALTIME, &curTime);
+ int64_t now = (curTime.tv_sec * kNanosecondsInSeconds) + curTime.tv_nsec;
+ int64_t nextSampleTime = mLastSampleTimeNs + mSamplingPeriodNs;
+
+ if (now >= nextSampleTime) {
+ mLastSampleTimeNs = now;
+ nextSampleTime = mLastSampleTimeNs + mSamplingPeriodNs;
+ mCallback->postEvents(readEvents());
+ }
+
+ mWaitCV.wait_for(runLock, std::chrono::nanoseconds(nextSampleTime - now));
+ }
+ }
+}
+
+std::vector<Event> Sensor::readEvents() {
+ std::vector<Event> events;
+ Event event;
+ event.sensorHandle = mSensorInfo.sensorHandle;
+ event.sensorType = mSensorInfo.type;
+ event.timestamp = ::android::elapsedRealtimeNano();
+ event.u.vec3.x = 1;
+ event.u.vec3.y = 2;
+ event.u.vec3.z = 3;
+ event.u.vec3.status = SensorStatus::ACCURACY_HIGH;
+ events.push_back(event);
+ return events;
+}
+
+AccelSensor::AccelSensor(int32_t sensorHandle, ISensorsEventCallback* callback) : Sensor(callback) {
+ mSensorInfo.sensorHandle = sensorHandle;
+ mSensorInfo.name = "Accel Sensor";
+ mSensorInfo.vendor = "Vendor String";
+ mSensorInfo.version = 1;
+ mSensorInfo.type = SensorType::ACCELEROMETER;
+ mSensorInfo.typeAsString = "";
+ mSensorInfo.maxRange = 78.4f; // +/- 8g
+ mSensorInfo.resolution = 1.52e-5;
+ mSensorInfo.power = 0.001f; // mA
+ mSensorInfo.minDelay = 20 * 1000; // microseconds
+ mSensorInfo.maxDelay = 1000 * 1000; // microseconds
+ mSensorInfo.fifoReservedEventCount = 0;
+ mSensorInfo.fifoMaxEventCount = 0;
+ mSensorInfo.requiredPermission = "";
+ mSensorInfo.flags = static_cast<uint32_t>(SensorFlagBits::WAKE_UP);
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace sensors
+} // namespace hardware
+} // namespace android
diff --git a/sensors/2.0/default/Sensor.h b/sensors/2.0/default/Sensor.h
new file mode 100644
index 0000000..e467b56
--- /dev/null
+++ b/sensors/2.0/default/Sensor.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_SENSORS_V2_0_SENSOR_H
+#define ANDROID_HARDWARE_SENSORS_V2_0_SENSOR_H
+
+#include <android/hardware/sensors/1.0/types.h>
+
+#include <condition_variable>
+#include <memory>
+#include <thread>
+#include <vector>
+
+using ::android::hardware::sensors::V1_0::Event;
+using ::android::hardware::sensors::V1_0::SensorInfo;
+using ::android::hardware::sensors::V1_0::SensorType;
+
+namespace android {
+namespace hardware {
+namespace sensors {
+namespace V2_0 {
+namespace implementation {
+
+class ISensorsEventCallback {
+ public:
+ virtual ~ISensorsEventCallback(){};
+ virtual void postEvents(const std::vector<Event>& events) = 0;
+};
+
+class Sensor {
+ public:
+ Sensor(ISensorsEventCallback* callback);
+ virtual ~Sensor();
+
+ const SensorInfo& getSensorInfo() const;
+ void batch(int32_t samplingPeriodNs);
+ void activate(bool enable);
+
+ protected:
+ void run();
+ virtual std::vector<Event> readEvents();
+ static void startThread(Sensor* sensor);
+
+ bool mIsEnabled;
+ int64_t mSamplingPeriodNs;
+ int64_t mLastSampleTimeNs;
+ SensorInfo mSensorInfo;
+
+ std::atomic_bool mStopThread;
+ std::condition_variable mWaitCV;
+ std::thread mRunThread;
+
+ ISensorsEventCallback* mCallback;
+};
+
+class AccelSensor : public Sensor {
+ public:
+ AccelSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace sensors
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_SENSORS_V2_0_SENSOR_H
diff --git a/sensors/2.0/default/Sensors.cpp b/sensors/2.0/default/Sensors.cpp
new file mode 100644
index 0000000..39c1ded
--- /dev/null
+++ b/sensors/2.0/default/Sensors.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2018 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 "Sensors.h"
+
+#include <android/hardware/sensors/2.0/types.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace sensors {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::sensors::V1_0::Event;
+using ::android::hardware::sensors::V1_0::OperationMode;
+using ::android::hardware::sensors::V1_0::RateLevel;
+using ::android::hardware::sensors::V1_0::Result;
+using ::android::hardware::sensors::V1_0::SharedMemInfo;
+
+Sensors::Sensors() : mEventQueueFlag(nullptr) {
+ std::shared_ptr<AccelSensor> accel =
+ std::make_shared<AccelSensor>(1 /* sensorHandle */, this /* callback */);
+ mSensors[accel->getSensorInfo().sensorHandle] = accel;
+}
+
+Sensors::~Sensors() {
+ deleteEventFlag();
+}
+
+// Methods from ::android::hardware::sensors::V2_0::ISensors follow.
+Return<void> Sensors::getSensorsList(getSensorsList_cb _hidl_cb) {
+ std::vector<SensorInfo> sensors;
+ for (const auto& sensor : mSensors) {
+ sensors.push_back(sensor.second->getSensorInfo());
+ }
+
+ // Call the HIDL callback with the SensorInfo
+ _hidl_cb(sensors);
+
+ return Void();
+}
+
+Return<Result> Sensors::setOperationMode(OperationMode /* mode */) {
+ // TODO implement
+ return Result{};
+}
+
+Return<Result> Sensors::activate(int32_t sensorHandle, bool enabled) {
+ auto sensor = mSensors.find(sensorHandle);
+ if (sensor != mSensors.end()) {
+ sensor->second->activate(enabled);
+ return Result::OK;
+ }
+ return Result::BAD_VALUE;
+}
+
+Return<Result> Sensors::initialize(
+ const ::android::hardware::MQDescriptorSync<Event>& eventQueueDescriptor,
+ const ::android::hardware::MQDescriptorSync<uint32_t>& wakeLockDescriptor,
+ const sp<ISensorsCallback>& sensorsCallback) {
+ Result result = Result::OK;
+
+ // Save a reference to the callback
+ mCallback = sensorsCallback;
+
+ // Create the Event FMQ from the eventQueueDescriptor. Reset the read/write positions.
+ mEventQueue =
+ std::make_unique<EventMessageQueue>(eventQueueDescriptor, true /* resetPointers */);
+
+ // Ensure that any existing EventFlag is properly deleted
+ deleteEventFlag();
+
+ // Create the EventFlag that is used to signal to the framework that sensor events have been
+ // written to the Event FMQ
+ if (EventFlag::createEventFlag(mEventQueue->getEventFlagWord(), &mEventQueueFlag) != OK) {
+ result = Result::BAD_VALUE;
+ }
+
+ // Create the Wake Lock FMQ that is used by the framework to communicate whenever WAKE_UP
+ // events have been successfully read and handled by the framework.
+ mWakeLockQueue =
+ std::make_unique<WakeLockMessageQueue>(wakeLockDescriptor, true /* resetPointers */);
+
+ if (!mCallback || !mEventQueue || !mWakeLockQueue || mEventQueueFlag == nullptr) {
+ result = Result::BAD_VALUE;
+ }
+
+ return result;
+}
+
+Return<Result> Sensors::batch(int32_t sensorHandle, int64_t samplingPeriodNs,
+ int64_t /* maxReportLatencyNs */) {
+ auto sensor = mSensors.find(sensorHandle);
+ if (sensor != mSensors.end()) {
+ sensor->second->batch(samplingPeriodNs);
+ return Result::OK;
+ }
+ return Result::BAD_VALUE;
+}
+
+Return<Result> Sensors::flush(int32_t /* sensorHandle */) {
+ // TODO implement
+ return Result{};
+}
+
+Return<Result> Sensors::injectSensorData(const Event& /* event */) {
+ // TODO implement
+ return Result{};
+}
+
+Return<void> Sensors::registerDirectChannel(const SharedMemInfo& /* mem */,
+ registerDirectChannel_cb _hidl_cb) {
+ _hidl_cb(Result::INVALID_OPERATION, 0 /* channelHandle */);
+ return Return<void>();
+}
+
+Return<Result> Sensors::unregisterDirectChannel(int32_t /* channelHandle */) {
+ return Result::INVALID_OPERATION;
+}
+
+Return<void> Sensors::configDirectReport(int32_t /* sensorHandle */, int32_t /* channelHandle */,
+ RateLevel /* rate */, configDirectReport_cb _hidl_cb) {
+ _hidl_cb(Result::INVALID_OPERATION, 0 /* reportToken */);
+ return Return<void>();
+}
+
+void Sensors::postEvents(const std::vector<Event>& events) {
+ std::lock_guard<std::mutex> l(mLock);
+
+ // TODO: read events from the Wake Lock FMQ in the right place
+ std::vector<uint32_t> tmp(mWakeLockQueue->availableToRead());
+ mWakeLockQueue->read(tmp.data(), mWakeLockQueue->availableToRead());
+
+ mEventQueue->write(events.data(), events.size());
+ mEventQueueFlag->wake(static_cast<uint32_t>(EventQueueFlagBits::READ_AND_PROCESS));
+}
+
+void Sensors::deleteEventFlag() {
+ status_t status = EventFlag::deleteEventFlag(&mEventQueueFlag);
+ if (status != OK) {
+ ALOGI("Failed to delete event flag: %d", status);
+ }
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace sensors
+} // namespace hardware
+} // namespace android
diff --git a/sensors/2.0/default/Sensors.h b/sensors/2.0/default/Sensors.h
new file mode 100644
index 0000000..f543935
--- /dev/null
+++ b/sensors/2.0/default/Sensors.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_SENSORS_V2_0_SENSORS_H
+#define ANDROID_HARDWARE_SENSORS_V2_0_SENSORS_H
+
+#include "Sensor.h"
+
+#include <android/hardware/sensors/2.0/ISensors.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include <memory>
+
+namespace android {
+namespace hardware {
+namespace sensors {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::hardware::EventFlag;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::MessageQueue;
+using ::android::hardware::MQDescriptor;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+struct Sensors : public ISensors, public ISensorsEventCallback {
+ using Event = ::android::hardware::sensors::V1_0::Event;
+ using OperationMode = ::android::hardware::sensors::V1_0::OperationMode;
+ using RateLevel = ::android::hardware::sensors::V1_0::RateLevel;
+ using Result = ::android::hardware::sensors::V1_0::Result;
+ using SharedMemInfo = ::android::hardware::sensors::V1_0::SharedMemInfo;
+
+ Sensors();
+ virtual ~Sensors();
+
+ // Methods from ::android::hardware::sensors::V2_0::ISensors follow.
+ Return<void> getSensorsList(getSensorsList_cb _hidl_cb) override;
+
+ Return<Result> setOperationMode(OperationMode mode) override;
+
+ Return<Result> activate(int32_t sensorHandle, bool enabled) override;
+
+ Return<Result> initialize(
+ const ::android::hardware::MQDescriptorSync<Event>& eventQueueDescriptor,
+ const ::android::hardware::MQDescriptorSync<uint32_t>& wakeLockDescriptor,
+ const sp<ISensorsCallback>& sensorsCallback) override;
+
+ Return<Result> batch(int32_t sensorHandle, int64_t samplingPeriodNs,
+ int64_t maxReportLatencyNs) override;
+
+ Return<Result> flush(int32_t sensorHandle) override;
+
+ Return<Result> injectSensorData(const Event& event) override;
+
+ Return<void> registerDirectChannel(const SharedMemInfo& mem,
+ registerDirectChannel_cb _hidl_cb) override;
+
+ Return<Result> unregisterDirectChannel(int32_t channelHandle) override;
+
+ Return<void> configDirectReport(int32_t sensorHandle, int32_t channelHandle, RateLevel rate,
+ configDirectReport_cb _hidl_cb) override;
+
+ void postEvents(const std::vector<Event>& events) override;
+
+ private:
+ /**
+ * Utility function to delete the Event Flag
+ */
+ void deleteEventFlag();
+
+ using EventMessageQueue = MessageQueue<Event, kSynchronizedReadWrite>;
+ using WakeLockMessageQueue = MessageQueue<uint32_t, kSynchronizedReadWrite>;
+
+ /**
+ * The Event FMQ where sensor events are written
+ */
+ std::unique_ptr<EventMessageQueue> mEventQueue;
+
+ /**
+ * The Wake Lock FMQ that is read to determine when the framework has handled WAKE_UP events
+ */
+ std::unique_ptr<WakeLockMessageQueue> mWakeLockQueue;
+
+ /**
+ * Event Flag to signal to the framework when sensor events are available to be read
+ */
+ EventFlag* mEventQueueFlag;
+
+ /**
+ * Callback for asynchronous events, such as dynamic sensor connections.
+ */
+ sp<ISensorsCallback> mCallback;
+
+ /**
+ * A map of the available sensors
+ */
+ std::map<int32_t, std::shared_ptr<Sensor>> mSensors;
+
+ /**
+ * Lock to protect writes and reads to the FMQs
+ */
+ std::mutex mLock;
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace sensors
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_SENSORS_V2_0_SENSORS_H
diff --git a/sensors/2.0/default/android.hardware.sensors@2.0-service.rc b/sensors/2.0/default/android.hardware.sensors@2.0-service.rc
new file mode 100644
index 0000000..321d760
--- /dev/null
+++ b/sensors/2.0/default/android.hardware.sensors@2.0-service.rc
@@ -0,0 +1,5 @@
+service vendor.sensors-hal-2-0 /vendor/bin/hw/android.hardware.sensors@2.0-service
+ class hal
+ user system
+ group system
+ rlimit rtprio 10 10
diff --git a/sensors/2.0/default/service.cpp b/sensors/2.0/default/service.cpp
new file mode 100644
index 0000000..5c13e33
--- /dev/null
+++ b/sensors/2.0/default/service.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#define LOG_TAG "android.hardware.sensors@2.0-service"
+
+#include <android/hardware/sensors/2.0/ISensors.h>
+#include <hidl/HidlTransportSupport.h>
+#include <log/log.h>
+#include <utils/StrongPointer.h>
+#include "Sensors.h"
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::sensors::V2_0::ISensors;
+using android::hardware::sensors::V2_0::implementation::Sensors;
+
+int main(int /* argc */, char** /* argv */) {
+ configureRpcThreadpool(1, true);
+
+ android::sp<ISensors> sensors = new Sensors();
+ if (sensors->registerAsService() != ::android::OK) {
+ ALOGE("Failed to register Sensors HAL instance");
+ return -1;
+ }
+
+ joinRpcThreadpool();
+ return 1; // joinRpcThreadpool shouldn't exit
+}
diff --git a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h
index 7241923..5e54530 100644
--- a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h
+++ b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h
@@ -47,7 +47,7 @@
virtual void HidlTearDown() override;
- private:
+ protected:
friend SensorsHidlTest;
SensorsHidlEnvironmentV2_0() : mEventQueueFlag(nullptr) {}
diff --git a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
index 7c6f010..94cd6e5 100644
--- a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
+++ b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
@@ -79,6 +79,9 @@
SensorsHidlEnvironmentBase* getEnvironment() override {
return SensorsHidlEnvironmentV2_0::Instance();
}
+
+ // Helper functions
+ void activateAllSensors(bool enable);
};
Return<Result> SensorsHidlTest::activate(int32_t sensorHandle, bool enabled) {
@@ -437,6 +440,54 @@
RateLevel::VERY_FAST, NullChecker());
}
+void SensorsHidlTest::activateAllSensors(bool enable) {
+ for (const SensorInfo& sensorInfo : getSensorsList()) {
+ if (isValidType(sensorInfo.type)) {
+ batch(sensorInfo.sensorHandle, sensorInfo.minDelay, 0 /* maxReportLatencyNs */);
+ activate(sensorInfo.sensorHandle, enable);
+ }
+ }
+}
+
+// Test that if initialize is called twice, then the HAL writes events to the FMQs from the second
+// call to the function.
+TEST_F(SensorsHidlTest, CallInitializeTwice) {
+ // Create a helper class so that a second environment is able to be instantiated
+ class SensorsHidlEnvironmentTest : public SensorsHidlEnvironmentV2_0 {};
+
+ if (getSensorsList().size() == 0) {
+ // No sensors
+ return;
+ }
+
+ constexpr useconds_t kCollectionTimeoutUs = 1000 * 1000; // 1s
+ constexpr int32_t kNumEvents = 1;
+
+ // Create a new environment that calls initialize()
+ std::unique_ptr<SensorsHidlEnvironmentTest> newEnv =
+ std::make_unique<SensorsHidlEnvironmentTest>();
+ newEnv->HidlSetUp();
+
+ activateAllSensors(true);
+ // Verify that the old environment does not receive any events
+ ASSERT_EQ(collectEvents(kCollectionTimeoutUs, kNumEvents, getEnvironment()).size(), 0);
+ // Verify that the new event queue receives sensor events
+ ASSERT_GE(collectEvents(kCollectionTimeoutUs, kNumEvents, newEnv.get()).size(), kNumEvents);
+ activateAllSensors(false);
+
+ // Cleanup the test environment
+ newEnv->HidlTearDown();
+
+ // Restore the test environment for future tests
+ SensorsHidlEnvironmentV2_0::Instance()->HidlTearDown();
+ SensorsHidlEnvironmentV2_0::Instance()->HidlSetUp();
+
+ // Ensure that the original environment is receiving events
+ activateAllSensors(true);
+ ASSERT_GE(collectEvents(kCollectionTimeoutUs, kNumEvents).size(), kNumEvents);
+ activateAllSensors(false);
+}
+
int main(int argc, char** argv) {
::testing::AddGlobalTestEnvironment(SensorsHidlEnvironmentV2_0::Instance());
::testing::InitGoogleTest(&argc, argv);
diff --git a/sensors/common/vts/utils/SensorsHidlTestBase.cpp b/sensors/common/vts/utils/SensorsHidlTestBase.cpp
index b72fdfd..18549df 100644
--- a/sensors/common/vts/utils/SensorsHidlTestBase.cpp
+++ b/sensors/common/vts/utils/SensorsHidlTestBase.cpp
@@ -40,6 +40,14 @@
std::vector<Event> SensorsHidlTestBase::collectEvents(useconds_t timeLimitUs, size_t nEventLimit,
bool clearBeforeStart,
bool changeCollection) {
+ return collectEvents(timeLimitUs, nEventLimit, getEnvironment(), clearBeforeStart,
+ changeCollection);
+}
+
+std::vector<Event> SensorsHidlTestBase::collectEvents(useconds_t timeLimitUs, size_t nEventLimit,
+ SensorsHidlEnvironmentBase* environment,
+ bool clearBeforeStart,
+ bool changeCollection) {
std::vector<Event> events;
constexpr useconds_t SLEEP_GRANULARITY = 100 * 1000; // granularity 100 ms
@@ -47,10 +55,10 @@
clearBeforeStart);
if (changeCollection) {
- getEnvironment()->setCollection(true);
+ environment->setCollection(true);
}
if (clearBeforeStart) {
- getEnvironment()->catEvents(nullptr);
+ environment->catEvents(nullptr);
}
while (timeLimitUs > 0) {
@@ -58,7 +66,7 @@
usleep(duration);
timeLimitUs -= duration;
- getEnvironment()->catEvents(&events);
+ environment->catEvents(&events);
if (events.size() >= nEventLimit) {
break;
}
@@ -67,7 +75,7 @@
}
if (changeCollection) {
- getEnvironment()->setCollection(false);
+ environment->setCollection(false);
}
return events;
}
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
index f4b259f..6fd9a2b 100644
--- a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
@@ -85,6 +85,10 @@
std::vector<Event> collectEvents(useconds_t timeLimitUs, size_t nEventLimit,
bool clearBeforeStart = true, bool changeCollection = true);
+ static std::vector<Event> collectEvents(useconds_t timeLimitUs, size_t nEventLimit,
+ SensorsHidlEnvironmentBase* environment,
+ bool clearBeforeStart = true,
+ bool changeCollection = true);
inline static SensorFlagBits extractReportMode(uint64_t flag) {
return (SensorFlagBits)(flag & ((uint64_t)SensorFlagBits::CONTINUOUS_MODE |
diff --git a/soundtrigger/2.2/Android.bp b/soundtrigger/2.2/Android.bp
new file mode 100644
index 0000000..0a7c2d8
--- /dev/null
+++ b/soundtrigger/2.2/Android.bp
@@ -0,0 +1,20 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.soundtrigger@2.2",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "ISoundTriggerHw.hal",
+ ],
+ interfaces: [
+ "android.hardware.audio.common@2.0",
+ "android.hardware.soundtrigger@2.0",
+ "android.hardware.soundtrigger@2.1",
+ "android.hidl.base@1.0",
+ ],
+ gen_java: false,
+}
+
diff --git a/soundtrigger/2.2/ISoundTriggerHw.hal b/soundtrigger/2.2/ISoundTriggerHw.hal
new file mode 100644
index 0000000..fcb5087
--- /dev/null
+++ b/soundtrigger/2.2/ISoundTriggerHw.hal
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2018 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.soundtrigger@2.2;
+
+import @2.0::ISoundTriggerHwCallback.RecognitionEvent;
+import @2.0::SoundModelHandle;
+import @2.1::ISoundTriggerHw;
+
+/**
+ * SoundTrigger HAL interface. Used for hardware recognition of hotwords.
+ */
+interface ISoundTriggerHw extends @2.1::ISoundTriggerHw {
+
+ /**
+ * Get the state of a given model.
+ * The model state is returned as a RecognitionEvent.
+ * @param modelHandle The handle of the sound model to use for recognition
+ * @return retval Operation completion status: 0 in case of success,
+ * -ENOSYS in case of invalid model handle,
+ * -ENOMEM in case of memory allocation failure,
+ * -ENODEV in case of initialization error.
+ * @return state RecognitionEvent in case of success
+ */
+ getModelState(SoundModelHandle modelHandle)
+ generates (int32_t retval, @2.0::ISoundTriggerHwCallback.RecognitionEvent state);
+};
diff --git a/soundtrigger/2.2/default/Android.bp b/soundtrigger/2.2/default/Android.bp
new file mode 100644
index 0000000..78bb69f
--- /dev/null
+++ b/soundtrigger/2.2/default/Android.bp
@@ -0,0 +1,37 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_library_shared {
+ name: "android.hardware.soundtrigger@2.2-impl",
+ relative_install_path: "hw",
+ vendor: true,
+ srcs: [
+ "SoundTriggerHw.cpp",
+ ],
+ shared_libs: [
+ "libhidlbase",
+ "libhidltransport",
+ "liblog",
+ "libhidlmemory",
+ "libutils",
+ "libhardware",
+ "android.hardware.soundtrigger@2.0",
+ "android.hardware.soundtrigger@2.0-core",
+ "android.hardware.soundtrigger@2.1",
+ "android.hardware.soundtrigger@2.2",
+ "android.hidl.allocator@1.0",
+ "android.hidl.memory@1.0",
+ ],
+}
diff --git a/soundtrigger/2.2/default/SoundTriggerHw.cpp b/soundtrigger/2.2/default/SoundTriggerHw.cpp
new file mode 100644
index 0000000..ffdf9fb
--- /dev/null
+++ b/soundtrigger/2.2/default/SoundTriggerHw.cpp
@@ -0,0 +1,744 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#define LOG_TAG "SoundTriggerHw"
+
+#include "SoundTriggerHw.h"
+
+#include <android/hidl/allocator/1.0/IAllocator.h>
+#include <android/log.h>
+#include <hidlmemory/mapping.h>
+#include <utility>
+
+using android::hardware::hidl_memory;
+using android::hidl::allocator::V1_0::IAllocator;
+using android::hidl::memory::V1_0::IMemory;
+
+namespace android {
+namespace hardware {
+namespace soundtrigger {
+namespace V2_2 {
+namespace implementation {
+
+/**
+ * According to the HIDL C++ Users Guide: client and server implementations
+ * should never directly refer to anything other than the interface header
+ * generated from the HIDL definition file (ie. ISoundTriggerHw.hal), so
+ * this V2_2 implementation copies the V2_0 and V2_1 implementations and
+ * then adds the new V2_2 implementation.
+ */
+
+// Begin V2_0 implementation, copied from
+// hardware/interfaces/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp
+
+// static
+void soundModelCallback_(struct sound_trigger_model_event* halEvent, void* cookie) {
+ if (halEvent == NULL) {
+ ALOGW("soundModelCallback called with NULL event");
+ return;
+ }
+ sp<SoundTriggerHw::SoundModelClient> client =
+ wp<SoundTriggerHw::SoundModelClient>(static_cast<SoundTriggerHw::SoundModelClient*>(cookie))
+ .promote();
+ if (client == 0) {
+ ALOGW("soundModelCallback called on stale client");
+ return;
+ }
+ if (halEvent->model != client->getHalHandle()) {
+ ALOGW("soundModelCallback call with wrong handle %d on client with handle %d",
+ (int)halEvent->model, (int)client->getHalHandle());
+ return;
+ }
+
+ client->soundModelCallback(halEvent);
+}
+
+// static
+void recognitionCallback_(struct sound_trigger_recognition_event* halEvent, void* cookie) {
+ if (halEvent == NULL) {
+ ALOGW("recognitionCallback call NULL event");
+ return;
+ }
+ sp<SoundTriggerHw::SoundModelClient> client =
+ wp<SoundTriggerHw::SoundModelClient>(static_cast<SoundTriggerHw::SoundModelClient*>(cookie))
+ .promote();
+ if (client == 0) {
+ ALOGW("recognitionCallback called on stale client");
+ return;
+ }
+
+ client->recognitionCallback(halEvent);
+}
+
+Return<void> SoundTriggerHw::getProperties(ISoundTriggerHw::getProperties_cb _hidl_cb) {
+ ALOGV("getProperties() mHwDevice %p", mHwDevice);
+ int ret;
+ struct sound_trigger_properties halProperties;
+ ISoundTriggerHw::Properties properties;
+
+ if (mHwDevice == NULL) {
+ ret = -ENODEV;
+ goto exit;
+ }
+
+ ret = mHwDevice->get_properties(mHwDevice, &halProperties);
+
+ convertPropertiesFromHal(&properties, &halProperties);
+
+ ALOGV("getProperties implementor %s recognitionModes %08x", properties.implementor.c_str(),
+ properties.recognitionModes);
+
+exit:
+ _hidl_cb(ret, properties);
+ return Void();
+}
+
+int SoundTriggerHw::doLoadSoundModel(const V2_0::ISoundTriggerHw::SoundModel& soundModel,
+ sp<SoundTriggerHw::SoundModelClient> client) {
+ int32_t ret = 0;
+ struct sound_trigger_sound_model* halSoundModel;
+
+ ALOGV("doLoadSoundModel() data size %zu", soundModel.data.size());
+
+ if (mHwDevice == NULL) {
+ ret = -ENODEV;
+ goto exit;
+ }
+
+ halSoundModel = convertSoundModelToHal(&soundModel);
+ if (halSoundModel == NULL) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ sound_model_handle_t halHandle;
+ ret = mHwDevice->load_sound_model(mHwDevice, halSoundModel, soundModelCallback_, client.get(),
+ &halHandle);
+
+ free(halSoundModel);
+
+ if (ret != 0) {
+ goto exit;
+ }
+
+ client->setHalHandle(halHandle);
+ {
+ AutoMutex lock(mLock);
+ mClients.add(client->getId(), client);
+ }
+
+exit:
+ return ret;
+}
+
+Return<void> SoundTriggerHw::loadSoundModel(const V2_0::ISoundTriggerHw::SoundModel& soundModel,
+ const sp<V2_0::ISoundTriggerHwCallback>& callback,
+ V2_0::ISoundTriggerHwCallback::CallbackCookie cookie,
+ ISoundTriggerHw::loadSoundModel_cb _hidl_cb) {
+ sp<SoundTriggerHw::SoundModelClient> client =
+ new SoundModelClient_2_0(nextUniqueModelId(), cookie, callback);
+ _hidl_cb(doLoadSoundModel(soundModel, client), client->getId());
+ return Void();
+}
+
+Return<void> SoundTriggerHw::loadPhraseSoundModel(
+ const V2_0::ISoundTriggerHw::PhraseSoundModel& soundModel,
+ const sp<V2_0::ISoundTriggerHwCallback>& callback,
+ V2_0::ISoundTriggerHwCallback::CallbackCookie cookie,
+ ISoundTriggerHw::loadPhraseSoundModel_cb _hidl_cb) {
+ sp<SoundTriggerHw::SoundModelClient> client =
+ new SoundModelClient_2_0(nextUniqueModelId(), cookie, callback);
+ _hidl_cb(doLoadSoundModel((const V2_0::ISoundTriggerHw::SoundModel&)soundModel, client),
+ client->getId());
+ return Void();
+}
+
+Return<int32_t> SoundTriggerHw::unloadSoundModel(int32_t modelHandle) {
+ int32_t ret;
+ sp<SoundTriggerHw::SoundModelClient> client;
+
+ if (mHwDevice == NULL) {
+ ret = -ENODEV;
+ goto exit;
+ }
+
+ {
+ AutoMutex lock(mLock);
+ client = mClients.valueFor(modelHandle);
+ if (client == 0) {
+ ret = -ENOSYS;
+ goto exit;
+ }
+ }
+
+ ret = mHwDevice->unload_sound_model(mHwDevice, client->getHalHandle());
+
+ mClients.removeItem(modelHandle);
+
+exit:
+ return ret;
+}
+
+Return<int32_t> SoundTriggerHw::startRecognition(
+ int32_t modelHandle, const V2_0::ISoundTriggerHw::RecognitionConfig& config,
+ const sp<V2_0::ISoundTriggerHwCallback>& /* callback */, int32_t /* cookie */) {
+ int32_t ret;
+ sp<SoundTriggerHw::SoundModelClient> client;
+ struct sound_trigger_recognition_config* halConfig;
+
+ if (mHwDevice == NULL) {
+ ret = -ENODEV;
+ goto exit;
+ }
+
+ {
+ AutoMutex lock(mLock);
+ client = mClients.valueFor(modelHandle);
+ if (client == 0) {
+ ret = -ENOSYS;
+ goto exit;
+ }
+ }
+
+ halConfig =
+ convertRecognitionConfigToHal((const V2_0::ISoundTriggerHw::RecognitionConfig*)&config);
+
+ if (halConfig == NULL) {
+ ret = -EINVAL;
+ goto exit;
+ }
+ ret = mHwDevice->start_recognition(mHwDevice, client->getHalHandle(), halConfig,
+ recognitionCallback_, client.get());
+
+ free(halConfig);
+
+exit:
+ return ret;
+}
+
+Return<int32_t> SoundTriggerHw::stopRecognition(int32_t modelHandle) {
+ int32_t ret;
+ sp<SoundTriggerHw::SoundModelClient> client;
+ if (mHwDevice == NULL) {
+ ret = -ENODEV;
+ goto exit;
+ }
+
+ {
+ AutoMutex lock(mLock);
+ client = mClients.valueFor(modelHandle);
+ if (client == 0) {
+ ret = -ENOSYS;
+ goto exit;
+ }
+ }
+
+ ret = mHwDevice->stop_recognition(mHwDevice, client->getHalHandle());
+
+exit:
+ return ret;
+}
+
+Return<int32_t> SoundTriggerHw::stopAllRecognitions() {
+ int32_t ret;
+ if (mHwDevice == NULL) {
+ ret = -ENODEV;
+ goto exit;
+ }
+
+ if (mHwDevice->common.version >= SOUND_TRIGGER_DEVICE_API_VERSION_1_1 &&
+ mHwDevice->stop_all_recognitions) {
+ ret = mHwDevice->stop_all_recognitions(mHwDevice);
+ } else {
+ ret = -ENOSYS;
+ }
+exit:
+ return ret;
+}
+
+SoundTriggerHw::SoundTriggerHw() : mModuleName("primary"), mHwDevice(NULL), mNextModelId(1) {}
+
+void SoundTriggerHw::onFirstRef() {
+ const hw_module_t* mod;
+ int rc;
+
+ rc = hw_get_module_by_class(SOUND_TRIGGER_HARDWARE_MODULE_ID, mModuleName, &mod);
+ if (rc != 0) {
+ ALOGE("couldn't load sound trigger module %s.%s (%s)", SOUND_TRIGGER_HARDWARE_MODULE_ID,
+ mModuleName, strerror(-rc));
+ return;
+ }
+ rc = sound_trigger_hw_device_open(mod, &mHwDevice);
+ if (rc != 0) {
+ ALOGE("couldn't open sound trigger hw device in %s.%s (%s)",
+ SOUND_TRIGGER_HARDWARE_MODULE_ID, mModuleName, strerror(-rc));
+ mHwDevice = NULL;
+ return;
+ }
+ if (mHwDevice->common.version < SOUND_TRIGGER_DEVICE_API_VERSION_1_0 ||
+ mHwDevice->common.version > SOUND_TRIGGER_DEVICE_API_VERSION_CURRENT) {
+ ALOGE("wrong sound trigger hw device version %04x", mHwDevice->common.version);
+ sound_trigger_hw_device_close(mHwDevice);
+ mHwDevice = NULL;
+ return;
+ }
+
+ ALOGI("onFirstRef() mModuleName %s mHwDevice %p", mModuleName, mHwDevice);
+}
+
+SoundTriggerHw::~SoundTriggerHw() {
+ if (mHwDevice != NULL) {
+ sound_trigger_hw_device_close(mHwDevice);
+ }
+}
+
+uint32_t SoundTriggerHw::nextUniqueModelId() {
+ uint32_t modelId = 0;
+ {
+ AutoMutex lock(mLock);
+ do {
+ modelId =
+ atomic_fetch_add_explicit(&mNextModelId, (uint_fast32_t)1, memory_order_acq_rel);
+ } while (mClients.valueFor(modelId) != 0 && modelId != 0);
+ }
+ LOG_ALWAYS_FATAL_IF(modelId == 0, "wrap around in sound model IDs, num loaded models %zu",
+ mClients.size());
+ return modelId;
+}
+
+void SoundTriggerHw::convertUuidFromHal(Uuid* uuid, const sound_trigger_uuid_t* halUuid) {
+ uuid->timeLow = halUuid->timeLow;
+ uuid->timeMid = halUuid->timeMid;
+ uuid->versionAndTimeHigh = halUuid->timeHiAndVersion;
+ uuid->variantAndClockSeqHigh = halUuid->clockSeq;
+ memcpy(&uuid->node[0], &halUuid->node[0], 6);
+}
+
+void SoundTriggerHw::convertUuidToHal(sound_trigger_uuid_t* halUuid, const Uuid* uuid) {
+ halUuid->timeLow = uuid->timeLow;
+ halUuid->timeMid = uuid->timeMid;
+ halUuid->timeHiAndVersion = uuid->versionAndTimeHigh;
+ halUuid->clockSeq = uuid->variantAndClockSeqHigh;
+ memcpy(&halUuid->node[0], &uuid->node[0], 6);
+}
+
+void SoundTriggerHw::convertPropertiesFromHal(
+ ISoundTriggerHw::Properties* properties, const struct sound_trigger_properties* halProperties) {
+ properties->implementor = halProperties->implementor;
+ properties->description = halProperties->description;
+ properties->version = halProperties->version;
+ convertUuidFromHal(&properties->uuid, &halProperties->uuid);
+ properties->maxSoundModels = halProperties->max_sound_models;
+ properties->maxKeyPhrases = halProperties->max_key_phrases;
+ properties->maxUsers = halProperties->max_users;
+ properties->recognitionModes = halProperties->recognition_modes;
+ properties->captureTransition = halProperties->capture_transition;
+ properties->maxBufferMs = halProperties->max_buffer_ms;
+ properties->concurrentCapture = halProperties->concurrent_capture;
+ properties->triggerInEvent = halProperties->trigger_in_event;
+ properties->powerConsumptionMw = halProperties->power_consumption_mw;
+}
+
+void SoundTriggerHw::convertTriggerPhraseToHal(struct sound_trigger_phrase* halTriggerPhrase,
+ const ISoundTriggerHw::Phrase* triggerPhrase) {
+ halTriggerPhrase->id = triggerPhrase->id;
+ halTriggerPhrase->recognition_mode = triggerPhrase->recognitionModes;
+ unsigned int i;
+
+ halTriggerPhrase->num_users =
+ std::min((int)triggerPhrase->users.size(), SOUND_TRIGGER_MAX_USERS);
+ for (i = 0; i < halTriggerPhrase->num_users; i++) {
+ halTriggerPhrase->users[i] = triggerPhrase->users[i];
+ }
+
+ strlcpy(halTriggerPhrase->locale, triggerPhrase->locale.c_str(), SOUND_TRIGGER_MAX_LOCALE_LEN);
+ strlcpy(halTriggerPhrase->text, triggerPhrase->text.c_str(), SOUND_TRIGGER_MAX_STRING_LEN);
+}
+
+struct sound_trigger_sound_model* SoundTriggerHw::convertSoundModelToHal(
+ const V2_0::ISoundTriggerHw::SoundModel* soundModel) {
+ struct sound_trigger_sound_model* halModel = NULL;
+ if (soundModel->type == V2_0::SoundModelType::KEYPHRASE) {
+ size_t allocSize =
+ sizeof(struct sound_trigger_phrase_sound_model) + soundModel->data.size();
+ struct sound_trigger_phrase_sound_model* halKeyPhraseModel =
+ static_cast<struct sound_trigger_phrase_sound_model*>(malloc(allocSize));
+ LOG_ALWAYS_FATAL_IF(halKeyPhraseModel == NULL,
+ "malloc failed for size %zu in convertSoundModelToHal PHRASE",
+ allocSize);
+
+ const ISoundTriggerHw::PhraseSoundModel* keyPhraseModel =
+ reinterpret_cast<const ISoundTriggerHw::PhraseSoundModel*>(soundModel);
+
+ size_t i;
+ for (i = 0; i < keyPhraseModel->phrases.size() && i < SOUND_TRIGGER_MAX_PHRASES; i++) {
+ convertTriggerPhraseToHal(&halKeyPhraseModel->phrases[i], &keyPhraseModel->phrases[i]);
+ }
+ halKeyPhraseModel->num_phrases = (unsigned int)i;
+ halModel = reinterpret_cast<struct sound_trigger_sound_model*>(halKeyPhraseModel);
+ halModel->data_offset = sizeof(struct sound_trigger_phrase_sound_model);
+ } else {
+ size_t allocSize = sizeof(struct sound_trigger_sound_model) + soundModel->data.size();
+ halModel = static_cast<struct sound_trigger_sound_model*>(malloc(allocSize));
+ LOG_ALWAYS_FATAL_IF(halModel == NULL,
+ "malloc failed for size %zu in convertSoundModelToHal GENERIC",
+ allocSize);
+
+ halModel->data_offset = sizeof(struct sound_trigger_sound_model);
+ }
+ halModel->type = (sound_trigger_sound_model_type_t)soundModel->type;
+ convertUuidToHal(&halModel->uuid, &soundModel->uuid);
+ convertUuidToHal(&halModel->vendor_uuid, &soundModel->vendorUuid);
+ halModel->data_size = soundModel->data.size();
+ uint8_t* dst = reinterpret_cast<uint8_t*>(halModel) + halModel->data_offset;
+ const uint8_t* src = reinterpret_cast<const uint8_t*>(&soundModel->data[0]);
+ memcpy(dst, src, soundModel->data.size());
+
+ return halModel;
+}
+
+void SoundTriggerHw::convertPhraseRecognitionExtraToHal(
+ struct sound_trigger_phrase_recognition_extra* halExtra,
+ const V2_0::PhraseRecognitionExtra* extra) {
+ halExtra->id = extra->id;
+ halExtra->recognition_modes = extra->recognitionModes;
+ halExtra->confidence_level = extra->confidenceLevel;
+
+ unsigned int i;
+ for (i = 0; i < extra->levels.size() && i < SOUND_TRIGGER_MAX_USERS; i++) {
+ halExtra->levels[i].user_id = extra->levels[i].userId;
+ halExtra->levels[i].level = extra->levels[i].levelPercent;
+ }
+ halExtra->num_levels = i;
+}
+
+struct sound_trigger_recognition_config* SoundTriggerHw::convertRecognitionConfigToHal(
+ const V2_0::ISoundTriggerHw::RecognitionConfig* config) {
+ size_t allocSize = sizeof(struct sound_trigger_recognition_config) + config->data.size();
+ struct sound_trigger_recognition_config* halConfig =
+ static_cast<struct sound_trigger_recognition_config*>(malloc(allocSize));
+
+ LOG_ALWAYS_FATAL_IF(halConfig == NULL,
+ "malloc failed for size %zu in convertRecognitionConfigToHal", allocSize);
+
+ halConfig->capture_handle = (audio_io_handle_t)config->captureHandle;
+ halConfig->capture_device = (audio_devices_t)config->captureDevice;
+ halConfig->capture_requested = config->captureRequested;
+
+ unsigned int i;
+ for (i = 0; i < config->phrases.size() && i < SOUND_TRIGGER_MAX_PHRASES; i++) {
+ convertPhraseRecognitionExtraToHal(&halConfig->phrases[i], &config->phrases[i]);
+ }
+ halConfig->num_phrases = i;
+
+ halConfig->data_offset = sizeof(struct sound_trigger_recognition_config);
+ halConfig->data_size = config->data.size();
+ uint8_t* dst = reinterpret_cast<uint8_t*>(halConfig) + halConfig->data_offset;
+ const uint8_t* src = reinterpret_cast<const uint8_t*>(&config->data[0]);
+ memcpy(dst, src, config->data.size());
+ return halConfig;
+}
+
+// static
+void SoundTriggerHw::convertSoundModelEventFromHal(
+ V2_0::ISoundTriggerHwCallback::ModelEvent* event,
+ const struct sound_trigger_model_event* halEvent) {
+ event->status = (V2_0::ISoundTriggerHwCallback::SoundModelStatus)halEvent->status;
+ // event->model to be remapped by called
+ event->data.setToExternal(
+ const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(halEvent)) + halEvent->data_offset,
+ halEvent->data_size);
+}
+
+// static
+void SoundTriggerHw::convertPhaseRecognitionEventFromHal(
+ V2_0::ISoundTriggerHwCallback::PhraseRecognitionEvent* event,
+ const struct sound_trigger_phrase_recognition_event* halEvent) {
+ event->phraseExtras.resize(halEvent->num_phrases);
+ for (unsigned int i = 0; i < halEvent->num_phrases; i++) {
+ convertPhraseRecognitionExtraFromHal(&event->phraseExtras[i], &halEvent->phrase_extras[i]);
+ }
+ convertRecognitionEventFromHal(&event->common, &halEvent->common);
+}
+
+// static
+void SoundTriggerHw::convertRecognitionEventFromHal(
+ V2_0::ISoundTriggerHwCallback::RecognitionEvent* event,
+ const struct sound_trigger_recognition_event* halEvent) {
+ event->status = static_cast<V2_0::ISoundTriggerHwCallback::RecognitionStatus>(halEvent->status);
+ event->type = static_cast<V2_0::SoundModelType>(halEvent->type);
+ // event->model to be remapped by called
+ event->captureAvailable = halEvent->capture_available;
+ event->captureSession = halEvent->capture_session;
+ event->captureDelayMs = halEvent->capture_delay_ms;
+ event->capturePreambleMs = halEvent->capture_preamble_ms;
+ event->triggerInData = halEvent->trigger_in_data;
+ event->audioConfig.sampleRateHz = halEvent->audio_config.sample_rate;
+ event->audioConfig.channelMask =
+ (audio::common::V2_0::AudioChannelMask)halEvent->audio_config.channel_mask;
+ event->audioConfig.format = (audio::common::V2_0::AudioFormat)halEvent->audio_config.format;
+ event->data.setToExternal(
+ const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(halEvent)) + halEvent->data_offset,
+ halEvent->data_size);
+}
+
+// static
+void SoundTriggerHw::convertPhraseRecognitionExtraFromHal(
+ V2_0::PhraseRecognitionExtra* extra,
+ const struct sound_trigger_phrase_recognition_extra* halExtra) {
+ extra->id = halExtra->id;
+ extra->recognitionModes = halExtra->recognition_modes;
+ extra->confidenceLevel = halExtra->confidence_level;
+
+ extra->levels.resize(halExtra->num_levels);
+ for (unsigned int i = 0; i < halExtra->num_levels; i++) {
+ extra->levels[i].userId = halExtra->levels[i].user_id;
+ extra->levels[i].levelPercent = halExtra->levels[i].level;
+ }
+}
+
+void SoundTriggerHw::SoundModelClient_2_0::recognitionCallback(
+ struct sound_trigger_recognition_event* halEvent) {
+ if (halEvent->type == SOUND_MODEL_TYPE_KEYPHRASE) {
+ V2_0::ISoundTriggerHwCallback::PhraseRecognitionEvent event;
+ convertPhaseRecognitionEventFromHal(
+ &event, reinterpret_cast<sound_trigger_phrase_recognition_event*>(halEvent));
+ event.common.model = mId;
+ mCallback->phraseRecognitionCallback(event, mCookie);
+ } else {
+ V2_0::ISoundTriggerHwCallback::RecognitionEvent event;
+ convertRecognitionEventFromHal(&event, halEvent);
+ event.model = mId;
+ mCallback->recognitionCallback(event, mCookie);
+ }
+}
+
+void SoundTriggerHw::SoundModelClient_2_0::soundModelCallback(
+ struct sound_trigger_model_event* halEvent) {
+ V2_0::ISoundTriggerHwCallback::ModelEvent event;
+ convertSoundModelEventFromHal(&event, halEvent);
+ event.model = mId;
+ mCallback->soundModelCallback(event, mCookie);
+}
+
+// Begin V2_1 implementation, copied from
+// hardware/interfaces/soundtrigger/2.1/default/SoundTriggerHw.cpp
+
+namespace {
+
+// Backs up by the vector with the contents of shared memory.
+// It is assumed that the passed hidl_vector is empty, so it's
+// not cleared if the memory is a null object.
+// The caller needs to keep the returned sp<IMemory> as long as
+// the data is needed.
+std::pair<bool, sp<IMemory>> memoryAsVector(const hidl_memory& m, hidl_vec<uint8_t>* vec) {
+ sp<IMemory> memory;
+ if (m.size() == 0) {
+ return std::make_pair(true, memory);
+ }
+ memory = mapMemory(m);
+ if (memory != nullptr) {
+ memory->read();
+ vec->setToExternal(static_cast<uint8_t*>(static_cast<void*>(memory->getPointer())),
+ memory->getSize());
+ return std::make_pair(true, memory);
+ }
+ ALOGE("%s: Could not map HIDL memory to IMemory", __func__);
+ return std::make_pair(false, memory);
+}
+
+// Moves the data from the vector into allocated shared memory,
+// emptying the vector.
+// It is assumed that the passed hidl_memory is a null object, so it's
+// not reset if the vector is empty.
+// The caller needs to keep the returned sp<IMemory> as long as
+// the data is needed.
+std::pair<bool, sp<IMemory>> moveVectorToMemory(hidl_vec<uint8_t>* v, hidl_memory* mem) {
+ sp<IMemory> memory;
+ if (v->size() == 0) {
+ return std::make_pair(true, memory);
+ }
+ sp<IAllocator> ashmem = IAllocator::getService("ashmem");
+ if (ashmem == 0) {
+ ALOGE("Failed to retrieve ashmem allocator service");
+ return std::make_pair(false, memory);
+ }
+ bool success = false;
+ Return<void> r = ashmem->allocate(v->size(), [&](bool s, const hidl_memory& m) {
+ success = s;
+ if (success) *mem = m;
+ });
+ if (r.isOk() && success) {
+ memory = hardware::mapMemory(*mem);
+ if (memory != 0) {
+ memory->update();
+ memcpy(memory->getPointer(), v->data(), v->size());
+ memory->commit();
+ v->resize(0);
+ return std::make_pair(true, memory);
+ } else {
+ ALOGE("Failed to map allocated ashmem");
+ }
+ } else {
+ ALOGE("Failed to allocate %llu bytes from ashmem", (unsigned long long)v->size());
+ }
+ return std::make_pair(false, memory);
+}
+
+} // namespace
+
+Return<void> SoundTriggerHw::loadSoundModel_2_1(
+ const V2_1::ISoundTriggerHw::SoundModel& soundModel,
+ const sp<V2_1::ISoundTriggerHwCallback>& callback, int32_t cookie,
+ V2_1::ISoundTriggerHw::loadSoundModel_2_1_cb _hidl_cb) {
+ // It is assumed that legacy data vector is empty, thus making copy is cheap.
+ V2_0::ISoundTriggerHw::SoundModel soundModel_2_0(soundModel.header);
+ auto result = memoryAsVector(soundModel.data, &soundModel_2_0.data);
+ if (result.first) {
+ sp<SoundModelClient> client =
+ new SoundModelClient_2_1(nextUniqueModelId(), cookie, callback);
+ _hidl_cb(doLoadSoundModel(soundModel_2_0, client), client->getId());
+ return Void();
+ }
+ _hidl_cb(-ENOMEM, 0);
+ return Void();
+}
+
+Return<void> SoundTriggerHw::loadPhraseSoundModel_2_1(
+ const V2_1::ISoundTriggerHw::PhraseSoundModel& soundModel,
+ const sp<V2_1::ISoundTriggerHwCallback>& callback, int32_t cookie,
+ V2_1::ISoundTriggerHw::loadPhraseSoundModel_2_1_cb _hidl_cb) {
+ V2_0::ISoundTriggerHw::PhraseSoundModel soundModel_2_0;
+ // It is assumed that legacy data vector is empty, thus making copy is cheap.
+ soundModel_2_0.common = soundModel.common.header;
+ // Avoid copying phrases data.
+ soundModel_2_0.phrases.setToExternal(
+ const_cast<V2_0::ISoundTriggerHw::Phrase*>(soundModel.phrases.data()),
+ soundModel.phrases.size());
+ auto result = memoryAsVector(soundModel.common.data, &soundModel_2_0.common.data);
+ if (result.first) {
+ sp<SoundModelClient> client =
+ new SoundModelClient_2_1(nextUniqueModelId(), cookie, callback);
+ _hidl_cb(doLoadSoundModel((const V2_0::ISoundTriggerHw::SoundModel&)soundModel_2_0, client),
+ client->getId());
+ return Void();
+ }
+ _hidl_cb(-ENOMEM, 0);
+ return Void();
+}
+
+Return<int32_t> SoundTriggerHw::startRecognition_2_1(
+ int32_t modelHandle, const V2_1::ISoundTriggerHw::RecognitionConfig& config,
+ const sp<V2_1::ISoundTriggerHwCallback>& callback, int32_t cookie) {
+ // It is assumed that legacy data vector is empty, thus making copy is cheap.
+ V2_0::ISoundTriggerHw::RecognitionConfig config_2_0(config.header);
+ auto result = memoryAsVector(config.data, &config_2_0.data);
+ return result.first ? startRecognition(modelHandle, config_2_0, callback, cookie)
+ : Return<int32_t>(-ENOMEM);
+}
+
+void SoundTriggerHw::SoundModelClient_2_1::recognitionCallback(
+ struct sound_trigger_recognition_event* halEvent) {
+ if (halEvent->type == SOUND_MODEL_TYPE_KEYPHRASE) {
+ V2_0::ISoundTriggerHwCallback::PhraseRecognitionEvent event_2_0;
+ convertPhaseRecognitionEventFromHal(
+ &event_2_0, reinterpret_cast<sound_trigger_phrase_recognition_event*>(halEvent));
+ event_2_0.common.model = mId;
+ V2_1::ISoundTriggerHwCallback::PhraseRecognitionEvent event;
+ event.phraseExtras.setToExternal(event_2_0.phraseExtras.data(),
+ event_2_0.phraseExtras.size());
+ auto result = moveVectorToMemory(&event_2_0.common.data, &event.common.data);
+ if (result.first) {
+ // The data vector is now empty, thus copying is cheap.
+ event.common.header = event_2_0.common;
+ mCallback->phraseRecognitionCallback_2_1(event, mCookie);
+ }
+ } else {
+ V2_1::ISoundTriggerHwCallback::RecognitionEvent event;
+ convertRecognitionEventFromHal(&event.header, halEvent);
+ event.header.model = mId;
+ auto result = moveVectorToMemory(&event.header.data, &event.data);
+ if (result.first) {
+ mCallback->recognitionCallback_2_1(event, mCookie);
+ }
+ }
+}
+
+void SoundTriggerHw::SoundModelClient_2_1::soundModelCallback(
+ struct sound_trigger_model_event* halEvent) {
+ V2_1::ISoundTriggerHwCallback::ModelEvent event;
+ convertSoundModelEventFromHal(&event.header, halEvent);
+ event.header.model = mId;
+ auto result = moveVectorToMemory(&event.header.data, &event.data);
+ if (result.first) {
+ mCallback->soundModelCallback_2_1(event, mCookie);
+ }
+}
+
+// Begin V2_2 implementation
+
+Return<void> SoundTriggerHw::getModelState(int32_t modelHandle, getModelState_cb hidl_cb) {
+ int ret = 0;
+ V2_0::ISoundTriggerHwCallback::RecognitionEvent event;
+ struct sound_trigger_recognition_event* halEvent = NULL;
+ sp<SoundModelClient> client;
+ if (mHwDevice == NULL) {
+ ret = -ENODEV;
+ goto exit;
+ }
+
+ {
+ AutoMutex lock(mLock);
+ client = mClients.valueFor(modelHandle);
+ if (client == 0) {
+ ret = -ENOSYS;
+ goto exit;
+ }
+ }
+
+ if (mHwDevice->get_model_state == NULL) {
+ ALOGE("Failed to get model state from device, no such method");
+ ret = -ENODEV;
+ goto exit;
+ }
+
+ // Get the state from the device (as a recognition event)
+ halEvent = mHwDevice->get_model_state(mHwDevice, client->getHalHandle());
+ if (halEvent == NULL) {
+ ALOGE("Failed to get model state from device");
+ ret = -ENODEV;
+ goto exit;
+ }
+
+ convertRecognitionEventFromHal(&event, halEvent);
+
+exit:
+ hidl_cb(ret, event);
+ free(halEvent);
+ return Void();
+}
+
+// Methods from ::android::hidl::base::V1_0::IBase follow.
+
+ISoundTriggerHw* HIDL_FETCH_ISoundTriggerHw(const char* /* name */) {
+ return new SoundTriggerHw();
+}
+
+} // namespace implementation
+} // namespace V2_2
+} // namespace soundtrigger
+} // namespace hardware
+} // namespace android
diff --git a/soundtrigger/2.2/default/SoundTriggerHw.h b/soundtrigger/2.2/default/SoundTriggerHw.h
new file mode 100644
index 0000000..876b990
--- /dev/null
+++ b/soundtrigger/2.2/default/SoundTriggerHw.h
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_SOUNDTRIGGER_V2_2_SOUNDTRIGGERHW_H
+#define ANDROID_HARDWARE_SOUNDTRIGGER_V2_2_SOUNDTRIGGERHW_H
+
+#include <android/hardware/soundtrigger/2.0/ISoundTriggerHw.h>
+#include <android/hardware/soundtrigger/2.0/ISoundTriggerHwCallback.h>
+#include <android/hardware/soundtrigger/2.2/ISoundTriggerHw.h>
+#include <hardware/sound_trigger.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <stdatomic.h>
+#include <system/sound_trigger.h>
+#include <utils/KeyedVector.h>
+#include <utils/threads.h>
+
+namespace android {
+namespace hardware {
+namespace soundtrigger {
+namespace V2_2 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::audio::common::V2_0::Uuid;
+using ::android::hardware::soundtrigger::V2_0::ISoundTriggerHwCallback;
+
+/**
+ * According to the HIDL C++ Users Guide: client and server implementations
+ * should never directly refer to anything other than the interface header
+ * generated from the HIDL definition file (ie. ISoundTriggerHw.hal), so
+ * this V2_2 implementation copies the V2_0 and V2_1 implementations and
+ * then adds the new V2_2 implementation.
+ */
+struct SoundTriggerHw : public ISoundTriggerHw {
+ // Methods from V2_0::ISoundTriggerHw follow.
+ Return<void> getProperties(getProperties_cb _hidl_cb) override;
+ Return<void> loadSoundModel(const V2_0::ISoundTriggerHw::SoundModel& soundModel,
+ const sp<V2_0::ISoundTriggerHwCallback>& callback, int32_t cookie,
+ loadSoundModel_cb _hidl_cb) override;
+ Return<void> loadPhraseSoundModel(const V2_0::ISoundTriggerHw::PhraseSoundModel& soundModel,
+ const sp<V2_0::ISoundTriggerHwCallback>& callback,
+ int32_t cookie, loadPhraseSoundModel_cb _hidl_cb) override;
+ Return<int32_t> unloadSoundModel(int32_t modelHandle) override;
+ Return<int32_t> startRecognition(int32_t modelHandle,
+ const V2_0::ISoundTriggerHw::RecognitionConfig& config,
+ const sp<V2_0::ISoundTriggerHwCallback>& callback,
+ int32_t cookie) override;
+ Return<int32_t> stopRecognition(int32_t modelHandle) override;
+ Return<int32_t> stopAllRecognitions() override;
+
+ // Methods from V2_1::ISoundTriggerHw follow.
+ Return<void> loadSoundModel_2_1(const V2_1::ISoundTriggerHw::SoundModel& soundModel,
+ const sp<V2_1::ISoundTriggerHwCallback>& callback,
+ int32_t cookie, loadSoundModel_2_1_cb _hidl_cb) override;
+ Return<void> loadPhraseSoundModel_2_1(const V2_1::ISoundTriggerHw::PhraseSoundModel& soundModel,
+ const sp<V2_1::ISoundTriggerHwCallback>& callback,
+ int32_t cookie,
+ loadPhraseSoundModel_2_1_cb _hidl_cb) override;
+ Return<int32_t> startRecognition_2_1(int32_t modelHandle,
+ const V2_1::ISoundTriggerHw::RecognitionConfig& config,
+ const sp<V2_1::ISoundTriggerHwCallback>& callback,
+ int32_t cookie) override;
+
+ // Methods from V2_2::ISoundTriggerHw follow.
+ Return<void> getModelState(int32_t modelHandle, getModelState_cb _hidl_cb) override;
+
+ SoundTriggerHw();
+
+ // Copied from hardware/interfaces/soundtrigger/2.0/default/SoundTriggerHalImpl.h
+ class SoundModelClient : public RefBase {
+ public:
+ SoundModelClient(uint32_t id, V2_0::ISoundTriggerHwCallback::CallbackCookie cookie)
+ : mId(id), mCookie(cookie) {}
+ virtual ~SoundModelClient() {}
+
+ uint32_t getId() const { return mId; }
+ sound_model_handle_t getHalHandle() const { return mHalHandle; }
+ void setHalHandle(sound_model_handle_t handle) { mHalHandle = handle; }
+
+ virtual void recognitionCallback(struct sound_trigger_recognition_event* halEvent) = 0;
+ virtual void soundModelCallback(struct sound_trigger_model_event* halEvent) = 0;
+
+ protected:
+ const uint32_t mId;
+ sound_model_handle_t mHalHandle;
+ V2_0::ISoundTriggerHwCallback::CallbackCookie mCookie;
+ };
+
+ protected:
+ static void convertPhaseRecognitionEventFromHal(
+ V2_0::ISoundTriggerHwCallback::PhraseRecognitionEvent* event,
+ const struct sound_trigger_phrase_recognition_event* halEvent);
+ static void convertRecognitionEventFromHal(
+ V2_0::ISoundTriggerHwCallback::RecognitionEvent* event,
+ const struct sound_trigger_recognition_event* halEvent);
+ static void convertSoundModelEventFromHal(V2_0::ISoundTriggerHwCallback::ModelEvent* event,
+ const struct sound_trigger_model_event* halEvent);
+
+ virtual ~SoundTriggerHw();
+
+ uint32_t nextUniqueModelId();
+ int doLoadSoundModel(const V2_0::ISoundTriggerHw::SoundModel& soundModel,
+ sp<SoundModelClient> client);
+
+ // RefBase
+ void onFirstRef() override;
+
+ private:
+ class SoundModelClient_2_0 : public SoundModelClient {
+ public:
+ SoundModelClient_2_0(uint32_t id, V2_0::ISoundTriggerHwCallback::CallbackCookie cookie,
+ sp<V2_0::ISoundTriggerHwCallback> callback)
+ : SoundModelClient(id, cookie), mCallback(callback) {}
+
+ void recognitionCallback(struct sound_trigger_recognition_event* halEvent) override;
+ void soundModelCallback(struct sound_trigger_model_event* halEvent) override;
+
+ private:
+ sp<V2_0::ISoundTriggerHwCallback> mCallback;
+ };
+
+ void convertUuidFromHal(Uuid* uuid, const sound_trigger_uuid_t* halUuid);
+ void convertUuidToHal(sound_trigger_uuid_t* halUuid, const Uuid* uuid);
+ void convertPropertiesFromHal(V2_0::ISoundTriggerHw::Properties* properties,
+ const struct sound_trigger_properties* halProperties);
+ void convertTriggerPhraseToHal(struct sound_trigger_phrase* halTriggerPhrase,
+ const V2_0::ISoundTriggerHw::Phrase* triggerPhrase);
+ // returned HAL sound model must be freed by caller
+ struct sound_trigger_sound_model* convertSoundModelToHal(
+ const V2_0::ISoundTriggerHw::SoundModel* soundModel);
+ void convertPhraseRecognitionExtraToHal(struct sound_trigger_phrase_recognition_extra* halExtra,
+ const V2_0::PhraseRecognitionExtra* extra);
+ // returned recognition config must be freed by caller
+ struct sound_trigger_recognition_config* convertRecognitionConfigToHal(
+ const V2_0::ISoundTriggerHw::RecognitionConfig* config);
+
+ static void convertPhraseRecognitionExtraFromHal(
+ V2_0::PhraseRecognitionExtra* extra,
+ const struct sound_trigger_phrase_recognition_extra* halExtra);
+
+ static void soundModelCallback(struct sound_trigger_model_event* halEvent, void* cookie);
+ static void recognitionCallback(struct sound_trigger_recognition_event* halEvent, void* cookie);
+
+ const char* mModuleName;
+ struct sound_trigger_hw_device* mHwDevice;
+ volatile atomic_uint_fast32_t mNextModelId;
+ DefaultKeyedVector<int32_t, sp<SoundModelClient> > mClients;
+ Mutex mLock;
+
+ // Copied from hardware/interfaces/soundtrigger/2.1/default/SoundTriggerHw.h
+ class SoundModelClient_2_1 : public SoundModelClient {
+ public:
+ SoundModelClient_2_1(uint32_t id, V2_1::ISoundTriggerHwCallback::CallbackCookie cookie,
+ sp<V2_1::ISoundTriggerHwCallback> callback)
+ : SoundModelClient(id, cookie), mCallback(callback) {}
+
+ void recognitionCallback(struct sound_trigger_recognition_event* halEvent) override;
+ void soundModelCallback(struct sound_trigger_model_event* halEvent) override;
+
+ private:
+ sp<V2_1::ISoundTriggerHwCallback> mCallback;
+ };
+};
+
+extern "C" ISoundTriggerHw* HIDL_FETCH_ISoundTriggerHw(const char* name);
+
+} // namespace implementation
+} // namespace V2_2
+} // namespace soundtrigger
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_SOUNDTRIGGER_V2_2_SOUNDTRIGGERHW_H
diff --git a/soundtrigger/2.2/vts/functional/VtsHalSoundtriggerV2_2TargetTest.cpp b/soundtrigger/2.2/vts/functional/VtsHalSoundtriggerV2_2TargetTest.cpp
new file mode 100644
index 0000000..a473c37
--- /dev/null
+++ b/soundtrigger/2.2/vts/functional/VtsHalSoundtriggerV2_2TargetTest.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#define LOG_TAG "SoundTriggerHidlHalTest"
+#include <stdlib.h>
+#include <time.h>
+
+#include <condition_variable>
+#include <mutex>
+
+#include <android/log.h>
+#include <cutils/native_handle.h>
+#include <log/log.h>
+
+#include <android/hardware/audio/common/2.0/types.h>
+#include <android/hardware/soundtrigger/2.0/ISoundTriggerHw.h>
+#include <android/hardware/soundtrigger/2.2/ISoundTriggerHw.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+
+using ::android::sp;
+using ::android::hardware::Return;
+using ::android::hardware::soundtrigger::V2_0::ISoundTriggerHwCallback;
+using ::android::hardware::soundtrigger::V2_0::SoundModelHandle;
+using ::android::hardware::soundtrigger::V2_2::ISoundTriggerHw;
+
+// Test environment for SoundTrigger HIDL HAL.
+class SoundTriggerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+ public:
+ // get the test environment singleton
+ static SoundTriggerHidlEnvironment* Instance() {
+ static SoundTriggerHidlEnvironment* instance = new SoundTriggerHidlEnvironment;
+ return instance;
+ }
+
+ void registerTestServices() override { registerTestService<ISoundTriggerHw>(); }
+
+ private:
+ SoundTriggerHidlEnvironment() {}
+};
+
+// The main test class for Sound Trigger HIDL HAL.
+class SoundTriggerHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+ public:
+ void SetUp() override {
+ mSoundTriggerHal = ::testing::VtsHalHidlTargetTestBase::getService<ISoundTriggerHw>(
+ SoundTriggerHidlEnvironment::Instance()->getServiceName<ISoundTriggerHw>());
+ ASSERT_NE(nullptr, mSoundTriggerHal.get());
+ }
+
+ static void SetUpTestCase() { srand(1234); }
+
+ void TearDown() override {}
+
+ protected:
+ sp<ISoundTriggerHw> mSoundTriggerHal;
+};
+
+/**
+ * Test ISoundTriggerHw::getModelState() method
+ *
+ * Verifies that:
+ * - the implementation returns -EINVAL with invalid model handle
+ *
+ */
+TEST_F(SoundTriggerHidlTest, GetModelStateInvalidModel) {
+ int ret = android::OK;
+ ::android::hardware::soundtrigger::V2_0::ISoundTriggerHwCallback::RecognitionEvent event;
+ SoundModelHandle handle = 0;
+ Return<void> hidlReturn =
+ mSoundTriggerHal->getModelState(handle, [&](int32_t retval, auto res) {
+ ret = retval;
+ event = res;
+ });
+
+ EXPECT_TRUE(hidlReturn.isOk());
+ EXPECT_EQ(-ENOSYS, ret);
+}
+
+int main(int argc, char** argv) {
+ ::testing::AddGlobalTestEnvironment(SoundTriggerHidlEnvironment::Instance());
+ ::testing::InitGoogleTest(&argc, argv);
+ SoundTriggerHidlEnvironment::Instance()->init(&argc, argv);
+ int status = RUN_ALL_TESTS();
+ ALOGI("Test result = %d", status);
+ return status;
+}
diff --git a/thermal/2.0/IThermal.hal b/thermal/2.0/IThermal.hal
index 548ac9d..f890694 100644
--- a/thermal/2.0/IThermal.hal
+++ b/thermal/2.0/IThermal.hal
@@ -42,7 +42,7 @@
generates (ThermalStatus status, vec<Temperature> temperatures);
/**
- * Retrieves temperature thresholds in Celsius.
+ * Retrieves static temperature thresholds in Celsius.
*
* @param filterType whether to filter the result for a given type.
* @param type the TemperatureType such as battery or skin.
@@ -54,7 +54,11 @@
* devices (such as CPUs, GPUs and etc.) in the list must be kept
* the same regardless of the number of calls to this method even if
* they go offline, if these devices exist on boot. The method
- * always returns and never removes such temperatures.
+ * always returns and never removes such temperatures. The thresholds
+ * are returned as static values and must not change across calls. The actual
+ * throttling state is determined in driver and HAL and must not be simply
+ * compared with these thresholds. To get accurate throttling status, use
+ * getCurrentTemperatures or registerThermalChangedCallback and listen.
*/
getTemperatureThresholds(bool filterType, TemperatureType type)
generates (ThermalStatus status, vec<TemperatureThreshold> temperatureThresholds);
diff --git a/thermal/2.0/default/android.hardware.thermal@2.0-service.xml b/thermal/2.0/default/android.hardware.thermal@2.0-service.xml
index c4c7d4d..bcd6344 100644
--- a/thermal/2.0/default/android.hardware.thermal@2.0-service.xml
+++ b/thermal/2.0/default/android.hardware.thermal@2.0-service.xml
@@ -2,6 +2,7 @@
<hal format="hidl">
<name>android.hardware.thermal</name>
<transport>hwbinder</transport>
+ <version>1.0</version>
<version>2.0</version>
<interface>
<name>IThermal</name>
diff --git a/thermal/2.0/types.hal b/thermal/2.0/types.hal
index 7b60d00..4929e44 100644
--- a/thermal/2.0/types.hal
+++ b/thermal/2.0/types.hal
@@ -22,6 +22,12 @@
enum TemperatureType : @1.0::TemperatureType {
USB_PORT = 4,
POWER_AMPLIFIER = 5,
+ /**
+ * Battery Charge Limit - virtual thermal sensors
+ */
+ BCL_VOLTAGE = 6,
+ BCL_CURRENT = 7,
+ BCL_PERCENTAGE = 8,
};
@@ -88,6 +94,7 @@
* Hot throttling temperature constant for this temperature sensor in
* level defined in ThrottlingSeverity including shutdown. Throttling
* happens when temperature >= threshold. If not available, set to NAN.
+ * Unit is same as Temperature's value.
*/
float[ThrottlingSeverityCount:NUM_THROTTLING_LEVELS] hotThrottlingThresholds;
@@ -95,13 +102,14 @@
* Cold throttling temperature constant for this temperature sensor in
* level defined in ThrottlingSeverity including shutdown. Throttling
* happens when temperature <= threshold. If not available, set to NAN.
+ * Unit is same as Temperature's value.
*/
float[ThrottlingSeverityCount:NUM_THROTTLING_LEVELS] coldThrottlingThresholds;
/**
* Threshold temperature above which the VR mode clockrate minimums cannot
- * be maintained for this device.
- * If not available, set by HAL to NAN.
+ * be maintained for this device. If not available, set by HAL to NAN.
+ * Unit is same as Temperature's value.
*/
float vrThrottlingThreshold;
};
@@ -121,7 +129,10 @@
string name;
/**
- * Current temperature in Celsius. If not available set by HAL to NAN.
+ * For BCL, this is the current reading of the virtual sensor and the unit is
+ * millivolt, milliamp, percentage for BCL_VOLTAGE, BCL_CURRENT and BCL_PERCENTAGE
+ * respectively. For everything else, this is the current temperature in Celsius.
+ * If not available set by HAL to NAN.
*/
float value;
diff --git a/thermal/2.0/vts/functional/VtsHalThermalV2_0TargetTest.cpp b/thermal/2.0/vts/functional/VtsHalThermalV2_0TargetTest.cpp
index 535f618..cf1956d 100644
--- a/thermal/2.0/vts/functional/VtsHalThermalV2_0TargetTest.cpp
+++ b/thermal/2.0/vts/functional/VtsHalThermalV2_0TargetTest.cpp
@@ -23,6 +23,7 @@
#include <VtsHalHidlTargetTestEnvBase.h>
using ::android::sp;
+using ::android::hardware::hidl_enum_range;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
@@ -183,9 +184,8 @@
EXPECT_NE(ThermalStatusCode::SUCCESS, status.code);
}
});
- for (int i = static_cast<int>(TemperatureType::UNKNOWN);
- i <= static_cast<int>(TemperatureType::POWER_AMPLIFIER); ++i) {
- auto type = static_cast<TemperatureType>(i);
+ auto types = hidl_enum_range<TemperatureType>();
+ for (const auto& type : types) {
mThermal->getCurrentTemperatures(
true, type, [&type](ThermalStatus status, hidl_vec<Temperature> temperatures) {
if (temperatures.size()) {
diff --git a/wifi/supplicant/1.2/Android.bp b/wifi/supplicant/1.2/Android.bp
new file mode 100644
index 0000000..bafd148
--- /dev/null
+++ b/wifi/supplicant/1.2/Android.bp
@@ -0,0 +1,19 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.wifi.supplicant@1.2",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "ISupplicantStaNetwork.hal",
+ ],
+ interfaces: [
+ "android.hardware.wifi.supplicant@1.0",
+ "android.hardware.wifi.supplicant@1.1",
+ "android.hidl.base@1.0",
+ ],
+ gen_java: true,
+}
+
diff --git a/wifi/supplicant/1.2/ISupplicantStaNetwork.hal b/wifi/supplicant/1.2/ISupplicantStaNetwork.hal
new file mode 100644
index 0000000..0bba096
--- /dev/null
+++ b/wifi/supplicant/1.2/ISupplicantStaNetwork.hal
@@ -0,0 +1,232 @@
+/*
+ * Copyright 2018 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.wifi.supplicant@1.2;
+
+import @1.0::ISupplicantStaNetworkCallback;
+import @1.0::ISupplicantStaNetwork;
+import @1.0::SupplicantStatus;
+import @1.1::ISupplicantStaNetwork;
+
+/**
+ * Interface exposed by the supplicant for each station mode network
+ * configuration it controls.
+ */
+interface ISupplicantStaNetwork extends @1.1::ISupplicantStaNetwork {
+ /** Possble mask of values for KeyMgmt param. */
+ enum KeyMgmtMask : @1.0::ISupplicantStaNetwork.KeyMgmtMask {
+ /** WPA3-Personal SAE Key management */
+ SAE = 1 << 10,
+
+ /** WPA3-Enterprise Suite-B Key management */
+ SUITE_B_192 = 1 << 17,
+
+ /** Enhacned Open (OWE) Key management */
+ OWE = 1 << 22,
+ };
+
+ /** Possble mask of values for PairwiseCipher param. */
+ enum PairwiseCipherMask : @1.0::ISupplicantStaNetwork.PairwiseCipherMask {
+ /** GCMP-256 Pairwise Cipher */
+ GCMP_256 = 1 << 8,
+ };
+
+ /** Possble mask of values for GroupCipher param. */
+ enum GroupCipherMask : @1.0::ISupplicantStaNetwork.GroupCipherMask {
+ /** GCMP-256 Group Cipher */
+ GCMP_256 = 1 << 8,
+ };
+
+ /**
+ * Set key management mask for the network.
+ *
+ * @param keyMgmtMask value to set.
+ * Combination of |KeyMgmtMask| values.
+ * @return status Status of the operation.
+ * Possible status codes:
+ * |SupplicantStatusCode.SUCCESS|,
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ setKeyMgmt_1_2(bitfield<KeyMgmtMask> keyMgmtMask) generates (SupplicantStatus status);
+
+ /**
+ * Get the key mgmt mask set for the network.
+ *
+ * @return status Status of the operation.
+ * Possible status codes:
+ * |SupplicantStatusCode.SUCCESS|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ * @return keyMgmtMask Combination of |KeyMgmtMask| values.
+ */
+ getKeyMgmt_1_2()
+ generates (SupplicantStatus status, bitfield<KeyMgmtMask> keyMgmtMask);
+
+ /**
+ * Set pairwise cipher mask for the network.
+ *
+ * @param pairwiseCipherMask value to set.
+ * Combination of |PairwiseCipherMask| values.
+ * @return status Status of the operation.
+ * Possible status codes:
+ * |SupplicantStatusCode.SUCCESS|,
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ setPairwiseCipher_1_2(bitfield<PairwiseCipherMask> pairwiseCipherMask)
+ generates (SupplicantStatus status);
+
+ /**
+ * Get the pairwise cipher mask set for the network.
+ *
+ * @return status Status of the operation.
+ * Possible status codes:
+ * |SupplicantStatusCode.SUCCESS|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ * @return pairwiseCipherMask Combination of |PairwiseCipherMask| values.
+ */
+ getPairwiseCipher_1_2()
+ generates (SupplicantStatus status,
+ bitfield<PairwiseCipherMask> pairwiseCipherMask);
+
+ /**
+ * Set group cipher mask for the network.
+ *
+ * @param groupCipherMask value to set.
+ * Combination of |GroupCipherMask| values.
+ * @return status Status of the operation.
+ * Possible status codes:
+ * |SupplicantStatusCode.SUCCESS|,
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ setGroupCipher_1_2(bitfield<GroupCipherMask> groupCipherMask)
+ generates (SupplicantStatus status);
+
+ /**
+ * Get the group cipher mask set for the network.
+ *
+ * @return status Status of the operation.
+ * Possible status codes:
+ * |SupplicantStatusCode.SUCCESS|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ * @return groupCipherMask Combination of |GroupCipherMask| values.
+ */
+ getGroupCipher_1_2()
+ generates (SupplicantStatus status,
+ bitfield<GroupCipherMask> groupCipherMask);
+
+ /**
+ * Enable TLS Suite-B in EAP Phase1
+ *
+ * @param enable Set to true to enable TLS Suite-B in EAP phase1
+ *
+ * @return status Status of the operation.
+ * Possible status codes:
+ * |SupplicantStatusCode.SUCCESS|,
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ enableTlsSuiteBEapPhase1Param(bool enable)
+ generates (SupplicantStatus status);
+
+ /**
+ * Set EAP OpenSSL Suite-B-192 ciphers for WPA3-Enterprise
+ * Supported option:
+ *
+ * @return status Status of the operation.
+ * Possible status codes:
+ * |SupplicantStatusCode.SUCCESS|,
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ enableSuiteBEapOpenSslCiphers()
+ generates (SupplicantStatus status);
+
+ /**
+ * Get SAE password for WPA3-Personal
+ *
+ * @return status Status of the operation, and a string.
+ * Possible status codes:
+ * |SupplicantStatusCode.SUCCESS|,
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ getSaePassword()
+ generates (SupplicantStatus status, string saePassword);
+
+ /**
+ * Get SAE password ID for WPA3-Personal
+ *
+ * @return status Status of the operation, and a string.
+ * Possible status codes:
+ * |SupplicantStatusCode.SUCCESS|,
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ getSaePasswordId()
+ generates (SupplicantStatus status, string saePasswordId);
+
+ /**
+ * Set SAE password for WPA3-Personal
+ *
+ * @param saePassword string with the above option
+ *
+ * @return status Status of the operation.
+ * Possible status codes:
+ * |SupplicantStatusCode.SUCCESS|,
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ setSaePassword(string saePassword)
+ generates (SupplicantStatus status);
+
+ /**
+ * Set SAE password ID for WPA3-Personal
+ *
+ * @param sae_password_id string with the above option
+ *
+ * @return status Status of the operation.
+ * Possible status codes:
+ * |SupplicantStatusCode.SUCCESS|,
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ setSaePasswordId(string saePasswordId)
+ generates (SupplicantStatus status);
+
+ /**
+ * Get Key management capabilities of the device
+ *
+ * @return status Status of the operation, and a string.
+ * Possible status codes:
+ * |SupplicantStatusCode.SUCCESS|,
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ getKeyMgmtCapabilities()
+ generates (SupplicantStatus status, bitfield<KeyMgmtMask> keyMgmtMask);
+};