Merge "Adjustments to composer apis for HDR:"
diff --git a/audio/policy/1.0/xml/api/current.txt b/audio/policy/1.0/xml/api/current.txt
index 29a9cd4..1478381 100644
--- a/audio/policy/1.0/xml/api/current.txt
+++ b/audio/policy/1.0/xml/api/current.txt
@@ -232,8 +232,10 @@
public class ValueType {
ctor public ValueType();
+ method public int getAndroid_type();
method public String getLiteral();
method public int getNumerical();
+ method public void setAndroid_type(int);
method public void setLiteral(String);
method public void setNumerical(int);
}
diff --git a/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd b/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd
index 842e724..852ea77 100644
--- a/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd
+++ b/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd
@@ -190,6 +190,7 @@
<xs:complexType name="valueType">
<xs:attribute name="literal" type="xs:string" use="required"/>
<xs:attribute name="numerical" type="xs:int" use="required"/>
+ <xs:attribute name="android_type" type="xs:int" use="optional"/>
</xs:complexType>
<xs:complexType name="attributesRefType">
diff --git a/automotive/can/1.0/tools/libprotocan/Android.bp b/automotive/can/1.0/tools/libprotocan/Android.bp
new file mode 100644
index 0000000..4c23fad
--- /dev/null
+++ b/automotive/can/1.0/tools/libprotocan/Android.bp
@@ -0,0 +1,42 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_library_static {
+ name: "libprotocan",
+ defaults: ["android.hardware.automotive.can@defaults"],
+ vendor: true,
+ srcs: [
+ "Checksum.cpp",
+ "MessageCounter.cpp",
+ "MessageDef.cpp",
+ "MessageInjector.cpp",
+ "Signal.cpp",
+ ],
+ export_include_dirs: ["include"],
+
+ shared_libs: [
+ "android.hardware.automotive.can@1.0",
+ ],
+}
diff --git a/automotive/can/1.0/tools/libprotocan/Checksum.cpp b/automotive/can/1.0/tools/libprotocan/Checksum.cpp
new file mode 100644
index 0000000..72fb0af
--- /dev/null
+++ b/automotive/can/1.0/tools/libprotocan/Checksum.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libprotocan/Checksum.h>
+
+namespace android::hardware::automotive::protocan {
+
+Checksum::Checksum(Signal signal, formula f) : mSignal(signal), mFormula(f) {}
+
+void Checksum::update(can::V1_0::CanMessage& msg) const {
+ mSignal.set(msg, 0);
+ mSignal.set(msg, mFormula(msg) % (mSignal.maxValue + 1));
+}
+
+} // namespace android::hardware::automotive::protocan
diff --git a/automotive/can/1.0/tools/libprotocan/MessageCounter.cpp b/automotive/can/1.0/tools/libprotocan/MessageCounter.cpp
new file mode 100644
index 0000000..ef9882f
--- /dev/null
+++ b/automotive/can/1.0/tools/libprotocan/MessageCounter.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libprotocan/MessageCounter.h>
+
+#include <android-base/logging.h>
+
+namespace android::hardware::automotive::protocan {
+
+/** Whether to log counter state messages. */
+static constexpr bool kSuperVerbose = false;
+
+MessageCounter::MessageCounter(Signal signal) : upperBound(signal.maxValue + 1), mSignal(signal) {}
+
+Signal::value MessageCounter::next() const {
+ CHECK(mCurrent.has_value()) << "Counter not initialized. Did you call isReady?";
+ return (*mCurrent + 1) % upperBound;
+}
+
+void MessageCounter::read(const can::V1_0::CanMessage& msg) {
+ auto val = mSignal.get(msg);
+
+ if (!mCurrent.has_value()) {
+ LOG(VERBOSE) << "Got first counter val of " << val;
+ mCurrent = val;
+ return;
+ }
+
+ auto nextVal = next();
+ if (nextVal == val) {
+ if constexpr (kSuperVerbose) {
+ LOG(VERBOSE) << "Got next counter val of " << nextVal;
+ }
+ mCurrent = nextVal;
+ } else {
+ LOG(DEBUG) << "Ignoring next counter val of " << val << ", waiting for " << nextVal;
+ }
+}
+
+bool MessageCounter::isReady() const { return mCurrent.has_value(); }
+
+void MessageCounter::increment(can::V1_0::CanMessage& msg) {
+ auto newVal = next();
+ mCurrent = newVal;
+ mSignal.set(msg, newVal);
+}
+
+} // namespace android::hardware::automotive::protocan
diff --git a/automotive/can/1.0/tools/libprotocan/MessageDef.cpp b/automotive/can/1.0/tools/libprotocan/MessageDef.cpp
new file mode 100644
index 0000000..23ce1df
--- /dev/null
+++ b/automotive/can/1.0/tools/libprotocan/MessageDef.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libprotocan/MessageDef.h>
+
+#include <android-base/logging.h>
+
+namespace android::hardware::automotive::protocan {
+
+using can::V1_0::CanMessage;
+using can::V1_0::CanMessageId;
+
+MessageDef::MessageDef(CanMessageId id, uint16_t len, std::map<std::string, Signal> signals,
+ std::optional<Signal> counter, std::optional<Checksum> checksum)
+ : id(id), kLen(len), kSignals(std::move(signals)), kCounter(counter), kChecksum(checksum) {}
+
+const Signal& MessageDef::operator[](const std::string& signalName) const {
+ auto it = kSignals.find(signalName);
+ CHECK(it != kSignals.end()) << "Signal " << signalName << " doesn't exist";
+ return it->second;
+}
+
+CanMessage MessageDef::makeDefault() const {
+ CanMessage msg = {};
+ msg.id = id;
+ msg.payload.resize(kLen);
+
+ for (auto const& [name, signal] : kSignals) {
+ signal.setDefault(msg);
+ }
+
+ return msg;
+}
+
+MessageCounter MessageDef::makeCounter() const {
+ CHECK(kCounter.has_value()) << "Can't build a counter for message without such signal";
+ return MessageCounter(*kCounter);
+}
+
+void MessageDef::updateChecksum(can::V1_0::CanMessage& msg) const {
+ if (!kChecksum.has_value()) return;
+ kChecksum->update(msg);
+}
+
+bool MessageDef::validate(const can::V1_0::CanMessage& msg) const {
+ return msg.payload.size() >= kLen;
+}
+
+} // namespace android::hardware::automotive::protocan
diff --git a/automotive/can/1.0/tools/libprotocan/MessageInjector.cpp b/automotive/can/1.0/tools/libprotocan/MessageInjector.cpp
new file mode 100644
index 0000000..7c45eaa
--- /dev/null
+++ b/automotive/can/1.0/tools/libprotocan/MessageInjector.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libprotocan/MessageInjector.h>
+
+#include <android-base/logging.h>
+
+#include <thread>
+
+namespace android::hardware::automotive::protocan {
+
+/** Whether to log injected messages. */
+static constexpr bool kSuperVerbose = true;
+
+using namespace std::literals::chrono_literals;
+
+using can::V1_0::CanMessage;
+using can::V1_0::CanMessageId;
+using can::V1_0::ICanBus;
+using can::V1_0::Result;
+
+MessageInjector::MessageInjector(MessageDef msgDef,
+ std::optional<std::chrono::milliseconds> interMessageDelay)
+ : kMsgDef(std::move(msgDef)),
+ kInterMessageDelay(interMessageDelay),
+ mCounter(msgDef.makeCounter()) {}
+
+void MessageInjector::inject(const CanMessage& msg) { inject({msg}); }
+
+void MessageInjector::inject(const std::initializer_list<can::V1_0::CanMessage> msgs) {
+ std::lock_guard<std::mutex> lock(mMessagesGuard);
+ for (const auto& msg : msgs) {
+ if constexpr (kSuperVerbose) {
+ LOG(VERBOSE) << "Message scheduled for injection: " << toString(msg);
+ }
+
+ mMessages.push(msg);
+ }
+}
+
+void MessageInjector::processQueueLocked(can::V1_0::ICanBus& bus) {
+ if (mMessages.empty() || !mCounter.isReady()) return;
+
+ auto paddingMessagesCount = mCounter.upperBound - (mMessages.size() % mCounter.upperBound);
+ auto padMessage = kMsgDef.makeDefault();
+ for (unsigned i = 0; i < paddingMessagesCount; i++) {
+ mMessages.push(padMessage);
+ }
+
+ while (!mMessages.empty()) {
+ auto&& outMsg = mMessages.front();
+
+ mCounter.increment(outMsg);
+ kMsgDef.updateChecksum(outMsg);
+
+ if constexpr (kSuperVerbose) {
+ LOG(VERBOSE) << "Injecting message: " << toString(outMsg);
+ }
+ auto result = bus.send(outMsg);
+ if (result != Result::OK) {
+ LOG(ERROR) << "Message injection failed: " << toString(result);
+ }
+
+ mMessages.pop();
+
+ // This would block onReceive, but the class is not supposed to be used in production anyway
+ // (see MessageInjector docstring).
+ if (kInterMessageDelay.has_value()) {
+ std::this_thread::sleep_for(*kInterMessageDelay);
+ }
+ }
+}
+
+void MessageInjector::onReceive(ICanBus& bus, const CanMessage& msg) {
+ if (!kMsgDef.validate(msg)) return;
+
+ std::lock_guard<std::mutex> lock(mMessagesGuard);
+
+ mCounter.read(msg);
+ processQueueLocked(bus);
+}
+
+MessageInjectorManager::MessageInjectorManager(
+ std::initializer_list<std::shared_ptr<MessageInjector>> injectors) {
+ std::transform(injectors.begin(), injectors.end(), std::inserter(mInjectors, mInjectors.end()),
+ [](const std::shared_ptr<MessageInjector>& injector) {
+ return std::make_pair(injector->kMsgDef.id, std::move(injector));
+ });
+}
+
+void MessageInjectorManager::onReceive(sp<ICanBus> bus, const CanMessage& msg) {
+ auto it = mInjectors.find(msg.id);
+ if (it == mInjectors.end()) return;
+ it->second->onReceive(*bus, msg);
+}
+
+} // namespace android::hardware::automotive::protocan
diff --git a/automotive/can/1.0/tools/libprotocan/Signal.cpp b/automotive/can/1.0/tools/libprotocan/Signal.cpp
new file mode 100644
index 0000000..bc3e070
--- /dev/null
+++ b/automotive/can/1.0/tools/libprotocan/Signal.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libprotocan/Signal.h>
+
+#include <android-base/logging.h>
+
+namespace android::hardware::automotive::protocan {
+
+static uint8_t calculateLastByteMask(uint16_t start, uint8_t length) {
+ unsigned lastByteBits = (start + length) % 8;
+ unsigned lastBytePadding = (8 - lastByteBits) % 8;
+ return 0xFF >> lastBytePadding;
+}
+
+static uint8_t calculateFirstByteMask(uint16_t firstByte, uint8_t firstBit, uint16_t lastByte,
+ uint8_t lastMask) {
+ uint8_t firstMask = 0xFF << firstBit;
+ if (firstByte == lastByte) firstMask &= lastMask;
+ return firstMask;
+}
+
+Signal::Signal(uint16_t start, uint8_t length, value defVal)
+ : maxValue((1u << length) - 1),
+ kFirstByte(start / 8),
+ kFirstBit(start % 8),
+ kFirstByteBits(8 - kFirstBit),
+ kLastByte((start + length - 1) / 8),
+ kLastMask(calculateLastByteMask(start, length)),
+ kFirstMask(calculateFirstByteMask(kFirstByte, kFirstBit, kLastByte, kLastMask)),
+ kDefVal(defVal) {
+ CHECK(length > 0) << "Signal length must not be zero";
+}
+
+Signal::value Signal::get(const can::V1_0::CanMessage& msg) const {
+ CHECK(msg.payload.size() > kLastByte)
+ << "Message is too short. Did you call MessageDef::validate?";
+
+ Signal::value v = 0;
+ if (kLastByte != kFirstByte) v = kLastMask & msg.payload[kLastByte];
+
+ for (int i = kLastByte - 1; i > kFirstByte; i--) {
+ v = (v << 8) | msg.payload[i];
+ }
+
+ return (v << kFirstByteBits) | ((msg.payload[kFirstByte] & kFirstMask) >> kFirstBit);
+}
+
+void Signal::set(can::V1_0::CanMessage& msg, Signal::value val) const {
+ CHECK(msg.payload.size() > kLastByte)
+ << "Signal requires message of length " << (kLastByte + 1)
+ << " which is beyond message length of " << msg.payload.size();
+
+ uint8_t firstByte = val << kFirstBit;
+ val >>= kFirstByteBits;
+
+ msg.payload[kFirstByte] = (msg.payload[kFirstByte] & ~kFirstMask) | (firstByte & kFirstMask);
+
+ for (int i = kFirstByte + 1; i < kLastByte; i++) {
+ msg.payload[i] = val & 0xFF;
+ val >>= 8;
+ }
+
+ if (kLastByte != kFirstByte) {
+ msg.payload[kLastByte] = (msg.payload[kLastByte] & ~kLastMask) | (val & kLastMask);
+ }
+}
+
+void Signal::setDefault(can::V1_0::CanMessage& msg) const { set(msg, kDefVal); }
+
+} // namespace android::hardware::automotive::protocan
diff --git a/automotive/can/1.0/tools/libprotocan/include/libprotocan/Checksum.h b/automotive/can/1.0/tools/libprotocan/include/libprotocan/Checksum.h
new file mode 100644
index 0000000..ff1dc91
--- /dev/null
+++ b/automotive/can/1.0/tools/libprotocan/include/libprotocan/Checksum.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hardware/automotive/can/1.0/types.h>
+#include <libprotocan/Signal.h>
+
+namespace android::hardware::automotive::protocan {
+
+class Checksum {
+ public:
+ using formula = std::function<Signal::value(const can::V1_0::CanMessage&)>;
+
+ Checksum(Signal signal, formula f);
+
+ void update(can::V1_0::CanMessage& msg) const;
+
+ private:
+ const Signal mSignal;
+ const formula mFormula;
+};
+
+} // namespace android::hardware::automotive::protocan
diff --git a/automotive/can/1.0/tools/libprotocan/include/libprotocan/MessageCounter.h b/automotive/can/1.0/tools/libprotocan/include/libprotocan/MessageCounter.h
new file mode 100644
index 0000000..56113be
--- /dev/null
+++ b/automotive/can/1.0/tools/libprotocan/include/libprotocan/MessageCounter.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hardware/automotive/can/1.0/types.h>
+#include <libprotocan/Signal.h>
+
+namespace android::hardware::automotive::protocan {
+
+class MessageCounter {
+ public:
+ const Signal::value upperBound;
+
+ MessageCounter(Signal signal);
+
+ /**
+ * Parse CAN message sent by external ECU to determine current counter value.
+ */
+ void read(const can::V1_0::CanMessage& msg);
+
+ /**
+ * States whether current counter value is determined.
+ */
+ bool isReady() const;
+
+ /**
+ * Increment current counter value and set it in a new message.
+ *
+ * Caller must check isReady() at least once before calling this method.
+ */
+ void increment(can::V1_0::CanMessage& msg);
+
+ private:
+ const Signal mSignal;
+
+ std::optional<Signal::value> mCurrent = std::nullopt;
+
+ Signal::value next() const;
+};
+
+} // namespace android::hardware::automotive::protocan
diff --git a/automotive/can/1.0/tools/libprotocan/include/libprotocan/MessageDef.h b/automotive/can/1.0/tools/libprotocan/include/libprotocan/MessageDef.h
new file mode 100644
index 0000000..79b21e1
--- /dev/null
+++ b/automotive/can/1.0/tools/libprotocan/include/libprotocan/MessageDef.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hardware/automotive/can/1.0/types.h>
+#include <libprotocan/Checksum.h>
+#include <libprotocan/MessageCounter.h>
+#include <libprotocan/Signal.h>
+
+namespace android::hardware::automotive::protocan {
+
+/**
+ * CAN message definition (not the actual message data).
+ *
+ * Describes static message properties (message ID, signals etc).
+ */
+class MessageDef {
+ public:
+ const can::V1_0::CanMessageId id;
+
+ /**
+ * Create message definition.
+ *
+ * Currently only constant length messages are supported.
+ *
+ * \param id CAN message ID
+ * \param len CAN message length
+ * \param signals CAN signal definitions
+ * \param counter Designated CAN signal definition for message counter, if the message has one
+ * \param checksum Designated CAN signal definition for payload checksum, if the message has one
+ */
+ MessageDef(can::V1_0::CanMessageId id, uint16_t len, std::map<std::string, Signal> signals,
+ std::optional<Signal> counter = std::nullopt,
+ std::optional<Checksum> checksum = std::nullopt);
+
+ const Signal& operator[](const std::string& signalName) const;
+
+ can::V1_0::CanMessage makeDefault() const;
+ MessageCounter makeCounter() const;
+
+ void updateChecksum(can::V1_0::CanMessage& msg) const;
+
+ /**
+ * Validate the message payload is large enough to hold all the signals.
+ */
+ bool validate(const can::V1_0::CanMessage& msg) const;
+
+private:
+ const uint16_t kLen;
+ const std::map<std::string, Signal> kSignals;
+ const std::optional<Signal> kCounter;
+ const std::optional<Checksum> kChecksum;
+};
+
+} // namespace android::hardware::automotive::protocan
diff --git a/automotive/can/1.0/tools/libprotocan/include/libprotocan/MessageInjector.h b/automotive/can/1.0/tools/libprotocan/include/libprotocan/MessageInjector.h
new file mode 100644
index 0000000..b0ea260
--- /dev/null
+++ b/automotive/can/1.0/tools/libprotocan/include/libprotocan/MessageInjector.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/macros.h>
+#include <android/hardware/automotive/can/1.0/ICanBus.h>
+#include <libprotocan/MessageCounter.h>
+#include <libprotocan/MessageDef.h>
+#include <utils/Mutex.h>
+
+#include <queue>
+
+namespace android::hardware::automotive::protocan {
+
+class MessageInjectorManager;
+
+/**
+ * Injects CAN messages with a counter to an existing system.
+ *
+ * This class is NOT meant to use in production - there should be no need to inject counted CAN
+ * messages where the other sender is also broadcasting them. If this is the case, it may be a sign
+ * your CAN network needs a redesign. This tool is intended for use for testing and demo purposes.
+ */
+class MessageInjector {
+ public:
+ MessageInjector(MessageDef msgDef, std::optional<std::chrono::milliseconds> interMessageDelay);
+
+ void inject(const can::V1_0::CanMessage& msg);
+ void inject(const std::initializer_list<can::V1_0::CanMessage> msgs);
+
+ private:
+ const MessageDef kMsgDef;
+ const std::optional<std::chrono::milliseconds> kInterMessageDelay;
+ MessageCounter mCounter;
+
+ mutable std::mutex mMessagesGuard;
+ std::queue<can::V1_0::CanMessage> mMessages GUARDED_BY(mMessagesGuard);
+
+ void onReceive(can::V1_0::ICanBus& bus, const can::V1_0::CanMessage& msg);
+ void processQueueLocked(can::V1_0::ICanBus& bus);
+
+ friend class MessageInjectorManager;
+
+ DISALLOW_COPY_AND_ASSIGN(MessageInjector);
+};
+
+/**
+ * Routes intercepted messages to MessageInjector instances configured to handle specific CAN
+ * message (CAN message ID). Intercepted messages from other nodes in CAN network are used to read
+ * current counter value in order to spoof the next packet.
+ */
+class MessageInjectorManager {
+ public:
+ MessageInjectorManager(std::initializer_list<std::shared_ptr<MessageInjector>> injectors);
+
+ void onReceive(sp<can::V1_0::ICanBus> bus, const can::V1_0::CanMessage& msg);
+
+ private:
+ std::map<can::V1_0::CanMessageId, std::shared_ptr<MessageInjector>> mInjectors;
+
+ DISALLOW_COPY_AND_ASSIGN(MessageInjectorManager);
+};
+
+} // namespace android::hardware::automotive::protocan
diff --git a/automotive/can/1.0/tools/libprotocan/include/libprotocan/Signal.h b/automotive/can/1.0/tools/libprotocan/include/libprotocan/Signal.h
new file mode 100644
index 0000000..7c0f119
--- /dev/null
+++ b/automotive/can/1.0/tools/libprotocan/include/libprotocan/Signal.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/macros.h>
+#include <android/hardware/automotive/can/1.0/types.h>
+
+namespace android::hardware::automotive::protocan {
+
+/**
+ * TODO(twasilczyk): right now, only Little Endian signals are supported.
+ */
+class Signal {
+ public:
+ using value = uint64_t;
+
+ const value maxValue;
+
+ Signal(uint16_t start, uint8_t length, value defVal = 0);
+
+ value get(const can::V1_0::CanMessage& msg) const;
+ void set(can::V1_0::CanMessage& msg, value val) const;
+ void setDefault(can::V1_0::CanMessage& msg) const;
+
+ private:
+ const uint16_t kFirstByte; ///< Index of first byte that holds the signal
+ const uint8_t kFirstBit; ///< Index of first bit within first byte
+ const uint8_t kFirstByteBits; ///< How many bits of the first byte belong to the signal
+ const uint16_t kLastByte; ///< Index of last byte that holds the signal
+ const uint8_t kLastMask; ///< Bits of the last byte that belong to the signal
+ const uint8_t kFirstMask; ///< Bits of the first byte that belong to the signal
+
+ const value kDefVal;
+};
+
+} // namespace android::hardware::automotive::protocan
diff --git a/automotive/can/1.0/tools/libprotocan/tests/Android.bp b/automotive/can/1.0/tools/libprotocan/tests/Android.bp
new file mode 100644
index 0000000..251cc06
--- /dev/null
+++ b/automotive/can/1.0/tools/libprotocan/tests/Android.bp
@@ -0,0 +1,39 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+ name: "libprotocan_signal_test",
+ defaults: ["android.hardware.automotive.can@defaults"],
+ vendor: true,
+ gtest: true,
+ srcs: ["libprotocan_signal_test.cpp"],
+ static_libs: [
+ "libprotocan",
+ ],
+ shared_libs: [
+ "android.hardware.automotive.can@1.0",
+ "libhidlbase",
+ ],
+}
diff --git a/automotive/can/1.0/tools/libprotocan/tests/libprotocan_signal_test.cpp b/automotive/can/1.0/tools/libprotocan/tests/libprotocan_signal_test.cpp
new file mode 100644
index 0000000..19c1209
--- /dev/null
+++ b/automotive/can/1.0/tools/libprotocan/tests/libprotocan_signal_test.cpp
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libprotocan/Signal.h>
+
+#include <gtest/gtest.h>
+
+namespace android::hardware::automotive::protocan::unittest {
+
+TEST(SignalTest, TestGetSingleBytes) {
+ can::V1_0::CanMessage msg = {};
+ msg.payload = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ for (unsigned i = 0; i < msg.payload.size(); i++) {
+ Signal signal(8 * i, 8);
+ ASSERT_EQ(i, signal.get(msg));
+ }
+}
+
+TEST(SignalTest, TestSetSingleBytes) {
+ std::vector<can::V1_0::CanMessage> msgs = {{}, {}, {}};
+ msgs[0].payload = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+ msgs[1].payload = {0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB};
+ msgs[2].payload = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ for (unsigned i = 0; i < msgs[0].payload.size(); i++) {
+ Signal signal(8 * i, 8);
+
+ for (auto&& msgOriginal : msgs) {
+ auto msgModified = msgOriginal;
+ signal.set(msgModified, 0xBA);
+
+ auto msgExpected = msgOriginal;
+ msgExpected.payload[i] = 0xBA;
+
+ ASSERT_EQ(msgExpected, msgModified) << "i=" << i;
+ }
+ }
+}
+
+TEST(SignalTest, TestGetStart4) {
+ /* Data generated with Python3:
+ *
+ * from cantools.database.can import *
+ * hex(Message(1, 'm', 4, [Signal('s', 4, 16, byte_order='little_endian')]).
+ * decode(b'\xde\xad\xbe\xef')['s'])
+ */
+
+ can::V1_0::CanMessage msg = {};
+ msg.payload = {0xDE, 0xAD, 0xBE, 0xEF};
+ can::V1_0::CanMessage msg2 = {};
+ msg2.payload = {0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD};
+
+ Signal s0_4(0, 4);
+ Signal s4_4(4, 4);
+ Signal s4_8(4, 8);
+ Signal s4_16(4, 16);
+ Signal s4_28(4, 28);
+ Signal s12_8(12, 8);
+ Signal s12_12(12, 12);
+ Signal s12_16(12, 16);
+ Signal s12_20(12, 20);
+ Signal s12_32(12, 32);
+
+ ASSERT_EQ(0xEu, s0_4.get(msg));
+ ASSERT_EQ(0xDu, s4_4.get(msg));
+ ASSERT_EQ(0xDDu, s4_8.get(msg));
+ ASSERT_EQ(0xEADDu, s4_16.get(msg));
+ ASSERT_EQ(0xEFBEADDu, s4_28.get(msg));
+ ASSERT_EQ(0xEAu, s12_8.get(msg));
+ ASSERT_EQ(0xBEAu, s12_12.get(msg));
+ ASSERT_EQ(0xFBEAu, s12_16.get(msg));
+ ASSERT_EQ(0xEFBEAu, s12_20.get(msg));
+ ASSERT_EQ(0xDDEEFBEAu, s12_32.get(msg2));
+}
+
+TEST(SignalTest, TestGet64) {
+ /* Data generated with Python3:
+ *
+ * from cantools.database.can import *
+ * hex(Message(1, 'm', 9, [Signal('s', 4, 64, byte_order='little_endian')]).
+ * decode(b'\xde\xad\xbe\xef\xab\xbc\xcd\xde\xef')['s'])
+ */
+
+ can::V1_0::CanMessage msg = {};
+ msg.payload = {0xDE, 0xAD, 0xBE, 0xEF, 0xAB, 0xBC, 0xCD, 0xDE, 0xEF};
+
+ Signal s0_64(0, 64);
+ Signal s8_64(8, 64);
+ Signal s4_64(4, 64);
+ Signal s1_64(1, 64);
+
+ ASSERT_EQ(0xDECDBCABEFBEADDEu, s0_64.get(msg));
+ ASSERT_EQ(0xEFDECDBCABEFBEADu, s8_64.get(msg));
+ ASSERT_EQ(0xFDECDBCABEFBEADDu, s4_64.get(msg));
+ ASSERT_EQ(0xEF66DE55F7DF56EFu, s1_64.get(msg));
+}
+
+TEST(SignalTest, TestGetAllStarts) {
+ /* Data generated with Python3:
+ *
+ * from cantools.database.can import *
+ * hex(Message(1, 'm', 6, [Signal('s', 0, 20, byte_order='little_endian')]).
+ * decode(b'\xde\xad\xbe\xef\xde\xad')['s'])
+ */
+
+ std::map<int, Signal::value> shifts = {
+ {0, 0xEADDEu}, {1, 0xF56EFu}, {2, 0xFAB77u}, {3, 0x7D5BBu}, {4, 0xBEADDu}, {5, 0xDF56Eu},
+ {6, 0xEFAB7u}, {7, 0xF7D5Bu}, {8, 0xFBEADu}, {9, 0x7DF56u}, {10, 0xBEFABu}, {11, 0xDF7D5u},
+ };
+
+ can::V1_0::CanMessage msg = {};
+ msg.payload = {0xDE, 0xAD, 0xBE, 0xEF, 0xCC, 0xCC};
+
+ for (auto const& [start, expected] : shifts) {
+ Signal s(start, 20);
+ ASSERT_EQ(expected, s.get(msg)) << "shift of " << start << " failed";
+ }
+}
+
+TEST(SignalTest, TestSetStart4) {
+ /* Data generated with Python3:
+ *
+ * from cantools.database.can import *
+ * so=4 ; sl=8
+ * md = Message(1, 'm', 4, [Signal('a1', 0, so), Signal('a2', so+sl, 32-so-sl),
+ * Signal('s', so, sl, byte_order='little_endian')])
+ * m = md.decode(b'\xcc\xcc\xcc\xcc')
+ * m['s'] = 0xDE
+ * binascii.hexlify(md.encode(m)).upper()
+ */
+ typedef struct {
+ int start;
+ int length;
+ Signal::value setValue;
+ hidl_vec<uint8_t> payload;
+ } case_t;
+
+ std::vector<case_t> cases = {
+ {0, 4, 0xDu, {0xCD, 0xCC, 0xCC, 0xCC}}, {4, 4, 0xDu, {0xDC, 0xCC, 0xCC, 0xCC}},
+ {4, 8, 0xDEu, {0xEC, 0xCD, 0xCC, 0xCC}}, {4, 16, 0xDEADu, {0xDC, 0xEA, 0xCD, 0xCC}},
+ {4, 24, 0xDEADBEu, {0xEC, 0xDB, 0xEA, 0xCD}}, {4, 28, 0xDEADBEEu, {0xEC, 0xBE, 0xAD, 0xDE}},
+ {12, 8, 0xDEu, {0xCC, 0xEC, 0xCD, 0xCC}}, {12, 12, 0xDEAu, {0xCC, 0xAC, 0xDE, 0xCC}},
+ {12, 16, 0xDEADu, {0xCC, 0xDC, 0xEA, 0xCD}}, {12, 20, 0xDEADBu, {0xCC, 0xBC, 0xAD, 0xDE}},
+ };
+
+ can::V1_0::CanMessage msg = {};
+ msg.payload = {0xCC, 0xCC, 0xCC, 0xCC};
+
+ for (auto const& tcase : cases) {
+ Signal s(tcase.start, tcase.length);
+
+ can::V1_0::CanMessage expectedMsg = {};
+ expectedMsg.payload = tcase.payload;
+
+ can::V1_0::CanMessage editedMsg = msg;
+ s.set(editedMsg, tcase.setValue);
+
+ ASSERT_EQ(expectedMsg, editedMsg) << " set(" << tcase.start << ", " << tcase.length << ")";
+ }
+}
+
+TEST(SignalTest, TestSetAllStarts) {
+ /* Data generated with Python3:
+ * from cantools.database.can import *
+ * import binascii
+ * import textwrap
+ *
+ * length = 20
+ * for start in range(0, 32 - length):
+ * signals = [Signal('s', start, length, byte_order='little_endian')]
+ * if start > 0: signals.append(Signal('a', 0, start, byte_order='little_endian'))
+ * signals.append(Signal('b', start + length, 32 - start - length,
+ * byte_order='little_endian'))
+ *
+ * md = Message(1, 'm', 4, signals)
+ * m = md.decode(b'\xcc\xcc\xcc\xcc')
+ * m['s'] = 0xDEADB
+ * out = binascii.hexlify(md.encode(m)).decode('ascii').upper()
+ * out = ', '.join(['0x{}'.format(v) for v in textwrap.wrap(out, 2)])
+ * print('{{ {:d}, {{ {:s} }}}},'.format(start, out))
+ */
+
+ std::map<int, hidl_vec<uint8_t>> shifts = {
+ {0, {0xDB, 0xEA, 0xCD, 0xCC}}, {1, {0xB6, 0xD5, 0xDB, 0xCC}}, {2, {0x6C, 0xAB, 0xF7, 0xCC}},
+ {3, {0xDC, 0x56, 0xEF, 0xCC}}, {4, {0xBC, 0xAD, 0xDE, 0xCC}}, {5, {0x6C, 0x5B, 0xBD, 0xCD}},
+ {6, {0xCC, 0xB6, 0x7A, 0xCF}}, {7, {0xCC, 0x6D, 0xF5, 0xCE}}, {8, {0xCC, 0xDB, 0xEA, 0xCD}},
+ {9, {0xCC, 0xB6, 0xD5, 0xDB}}, {10, {0xCC, 0x6C, 0xAB, 0xF7}}, {11, {0xCC, 0xDC, 0x56, 0xEF}},
+ };
+
+ can::V1_0::CanMessage msg = {};
+ msg.payload = {0xCC, 0xCC, 0xCC, 0xCC};
+
+ for (auto const& [start, expectedPayload] : shifts) {
+ Signal s(start, 20);
+
+ can::V1_0::CanMessage expectedMsg = {};
+ expectedMsg.payload = expectedPayload;
+
+ can::V1_0::CanMessage editedMsg = msg;
+ s.set(editedMsg, 0xDEADB);
+
+ ASSERT_EQ(expectedMsg, editedMsg) << "shift of " << start << " failed";
+ }
+}
+
+} // namespace android::hardware::automotive::protocan::unittest
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
index 63eb747..49b33d5 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
@@ -213,7 +213,7 @@
::ndk::ScopedAStatus toScopedAStatus(
const ::android::base::Result<T>& result,
::aidl::android::hardware::automotive::vehicle::StatusCode status,
- std::string additionalErrorMsg) {
+ const std::string& additionalErrorMsg) {
if (result.ok()) {
return ::ndk::ScopedAStatus::ok();
}
@@ -236,10 +236,50 @@
template <class T>
::ndk::ScopedAStatus toScopedAStatus(const ::android::base::Result<T>& result,
- std::string additionalErrorMsg) {
+ const std::string& additionalErrorMsg) {
return toScopedAStatus(result, getErrorCode(result), additionalErrorMsg);
}
+// Check whether the value is valid according to config.
+// We check for the following:
+// * If the type is INT32, {@code value.int32Values} must contain one element.
+// * If the type is INT32_VEC, {@code value.int32Values} must contain at least one element.
+// * If the type is INT64, {@code value.int64Values} must contain one element.
+// * If the type is INT64_VEC, {@code value.int64Values} must contain at least one element.
+// * If the type is FLOAT, {@code value.floatValues} must contain one element.
+// * If the type is FLOAT_VEC, {@code value.floatValues} must contain at least one element.
+// * If the type is MIXED, see checkVendorMixedPropValue.
+::android::base::Result<void> checkPropValue(
+ const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& value,
+ const ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig* config);
+
+// Check whether the Mixed type value is valid according to config.
+// We check for the following:
+// * configArray[1] + configArray[2] + configArray[3] must be equal to the number of
+// {@code value.int32Values} elements.
+// * configArray[4] + configArray[5] must be equal to the number of {@code value.int64Values}
+// elements.
+// * configArray[6] + configArray[7] must be equal to the number of {@code value.floatValues}
+// elements.
+// * configArray[8] must be equal to the number of {@code value.byteValues} elements.
+::android::base::Result<void> checkVendorMixedPropValue(
+ const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& value,
+ const ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig* config);
+
+// Check whether the value is within the configured range.
+// We check for the following types:
+// * If type is INT32 or INT32_VEC, all {@code value.int32Values} elements must be within
+// {@code minInt32Value} and {@code maxInt32Value} if either of them is not 0.
+// * If type is INT64 or INT64_VEC, all {@code value.int64Values} elements must be within
+// {@code minInt64Value} and {@code maxInt64Value} if either of them is not 0.
+// * If type is FLOAT or FLOAT_VEC, all {@code value.floatValues} elements must be within
+// {@code minFloatValues} and {@code maxFloatValues} if either of them is not 0.
+// We don't check other types. If more checks are required, they should be added in VehicleHardware
+// implementation.
+::android::base::Result<void> checkValueRange(
+ const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& value,
+ const ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig* config);
+
} // namespace vehicle
} // namespace automotive
} // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/VehicleUtils.cpp b/automotive/vehicle/aidl/impl/utils/common/src/VehicleUtils.cpp
new file mode 100644
index 0000000..5abde8d
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/utils/common/src/VehicleUtils.cpp
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "VehicleUtils.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+using ::android::base::Error;
+using ::android::base::Result;
+using ::ndk::ScopedAStatus;
+
+Result<void> checkPropValue(const VehiclePropValue& value, const VehiclePropConfig* config) {
+ int32_t property = value.prop;
+ VehiclePropertyType type = getPropType(property);
+ switch (type) {
+ case VehiclePropertyType::BOOLEAN:
+ [[fallthrough]];
+ case VehiclePropertyType::INT32:
+ if (value.value.int32Values.size() != 1) {
+ return Error() << "expect 1 int32Values for INT32 type";
+ }
+ break;
+ case VehiclePropertyType::INT32_VEC:
+ if (value.value.int32Values.size() < 1) {
+ return Error() << "expect >=1 int32Values for INT32_VEC type";
+ }
+ break;
+ case VehiclePropertyType::INT64:
+ if (value.value.int64Values.size() != 1) {
+ return Error() << "expect 1 int64Values for INT64 type";
+ }
+ break;
+ case VehiclePropertyType::INT64_VEC:
+ if (value.value.int64Values.size() < 1) {
+ return Error() << "expect >=1 int64Values for INT64_VEC type";
+ }
+ break;
+ case VehiclePropertyType::FLOAT:
+ if (value.value.floatValues.size() != 1) {
+ return Error() << "expect 1 floatValues for FLOAT type";
+ }
+ break;
+ case VehiclePropertyType::FLOAT_VEC:
+ if (value.value.floatValues.size() < 1) {
+ return Error() << "expect >=1 floatValues for FLOAT_VEC type";
+ }
+ break;
+ case VehiclePropertyType::BYTES:
+ // We allow setting an empty bytes array.
+ break;
+ case VehiclePropertyType::STRING:
+ // We allow setting an empty string.
+ break;
+ case VehiclePropertyType::MIXED:
+ if (getPropGroup(property) == VehiclePropertyGroup::VENDOR) {
+ // We only checks vendor mixed properties.
+ return checkVendorMixedPropValue(value, config);
+ }
+ break;
+ default:
+ return Error() << "unknown property type: " << toInt(type);
+ }
+ return {};
+}
+
+Result<void> checkVendorMixedPropValue(const VehiclePropValue& value,
+ const VehiclePropConfig* config) {
+ auto configArray = config->configArray;
+ // configArray[0], 1 indicates the property has a String value, we allow the string value to
+ // be empty.
+
+ size_t int32Count = 0;
+ // configArray[1], 1 indicates the property has a Boolean value.
+ if (configArray[1] == 1) {
+ int32Count++;
+ }
+ // configArray[2], 1 indicates the property has an Integer value.
+ if (configArray[2] == 1) {
+ int32Count++;
+ }
+ // configArray[3], the number indicates the size of Integer[] in the property.
+ int32Count += static_cast<size_t>(configArray[3]);
+ size_t int32Size = value.value.int32Values.size();
+ if (int32Size != int32Count) {
+ return Error() << "invalid mixed property, got " << int32Size << " int32Values, expect "
+ << int32Count;
+ }
+
+ size_t int64Count = 0;
+ // configArray[4], 1 indicates the property has a Long value.
+ if (configArray[4] == 1) {
+ int64Count++;
+ }
+ // configArray[5], the number indicates the size of Long[] in the property.
+ int64Count += static_cast<size_t>(configArray[5]);
+ size_t int64Size = value.value.int64Values.size();
+ if (int64Size != int64Count) {
+ return Error() << "invalid mixed property, got " << int64Size << " int64Values, expect "
+ << int64Count;
+ }
+
+ size_t floatCount = 0;
+ // configArray[6], 1 indicates the property has a Float value.
+ if (configArray[6] == 1) {
+ floatCount++;
+ }
+ // configArray[7], the number indicates the size of Float[] in the property.
+ floatCount += static_cast<size_t>(configArray[7]);
+ size_t floatSize = value.value.floatValues.size();
+ if (floatSize != floatCount) {
+ return Error() << "invalid mixed property, got " << floatSize << " floatValues, expect "
+ << floatCount;
+ }
+
+ // configArray[8], the number indicates the size of byte[] in the property.
+ size_t byteSize = value.value.byteValues.size();
+ size_t byteCount = static_cast<size_t>(configArray[8]);
+ if (byteCount != 0 && byteSize != byteCount) {
+ return Error() << "invalid mixed property, got " << byteSize << " byteValues, expect "
+ << byteCount;
+ }
+ return {};
+}
+
+Result<void> checkValueRange(const VehiclePropValue& value, const VehicleAreaConfig* areaConfig) {
+ if (areaConfig == nullptr) {
+ return {};
+ }
+ int32_t property = value.prop;
+ VehiclePropertyType type = getPropType(property);
+ switch (type) {
+ case VehiclePropertyType::INT32:
+ [[fallthrough]];
+ case VehiclePropertyType::INT32_VEC:
+ if (areaConfig->minInt32Value == 0 && areaConfig->maxInt32Value == 0) {
+ break;
+ }
+ for (int32_t int32Value : value.value.int32Values) {
+ if (int32Value < areaConfig->minInt32Value ||
+ int32Value > areaConfig->maxInt32Value) {
+ return Error() << "int32Value: " << int32Value
+ << " out of range, min: " << areaConfig->minInt32Value
+ << " max: " << areaConfig->maxInt32Value;
+ }
+ }
+ break;
+ case VehiclePropertyType::INT64:
+ [[fallthrough]];
+ case VehiclePropertyType::INT64_VEC:
+ if (areaConfig->minInt64Value == 0 && areaConfig->maxInt64Value == 0) {
+ break;
+ }
+ for (int64_t int64Value : value.value.int64Values) {
+ if (int64Value < areaConfig->minInt64Value ||
+ int64Value > areaConfig->maxInt64Value) {
+ return Error() << "int64Value: " << int64Value
+ << " out of range, min: " << areaConfig->minInt64Value
+ << " max: " << areaConfig->maxInt64Value;
+ }
+ }
+ break;
+ case VehiclePropertyType::FLOAT:
+ [[fallthrough]];
+ case VehiclePropertyType::FLOAT_VEC:
+ if (areaConfig->minFloatValue == 0.f && areaConfig->maxFloatValue == 0.f) {
+ break;
+ }
+ for (float floatValue : value.value.floatValues) {
+ if (floatValue < areaConfig->minFloatValue ||
+ floatValue > areaConfig->maxFloatValue) {
+ return Error() << "floatValue: " << floatValue
+ << " out of range, min: " << areaConfig->minFloatValue
+ << " max: " << areaConfig->maxFloatValue;
+ }
+ }
+ break;
+ default:
+ // We don't check the rest of property types. Additional logic needs to be added if
+ // required in VehicleHardware, e.g. you might want to check the range for mixed
+ // property.
+ break;
+ }
+ return {};
+}
+
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/Android.bp b/automotive/vehicle/aidl/impl/utils/common/test/Android.bp
index dd43712..250b331 100644
--- a/automotive/vehicle/aidl/impl/utils/common/test/Android.bp
+++ b/automotive/vehicle/aidl/impl/utils/common/test/Android.bp
@@ -27,6 +27,7 @@
"libgtest",
"libgmock",
],
+ header_libs: ["VehicleHalTestUtilHeaders"],
defaults: ["VehicleHalDefaults"],
test_suites: ["device-tests"],
}
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp b/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp
index 131eb3b..de8b26d 100644
--- a/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp
@@ -16,6 +16,7 @@
#include <ConcurrentQueue.h>
#include <PropertyUtils.h>
+#include <TestPropertyUtils.h>
#include <VehicleUtils.h>
#include <gtest/gtest.h>
@@ -29,6 +30,8 @@
namespace automotive {
namespace vehicle {
+namespace {
+
using ::aidl::android::hardware::automotive::vehicle::VehicleArea;
using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
@@ -37,6 +40,427 @@
using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+struct InvalidPropValueTestCase {
+ std::string name;
+ VehiclePropValue value;
+ bool valid = false;
+ VehiclePropConfig config;
+};
+
+constexpr int32_t int32Prop = toInt(VehicleProperty::INFO_MODEL_YEAR);
+constexpr int32_t int32VecProp = toInt(VehicleProperty::INFO_FUEL_TYPE);
+constexpr int32_t int64Prop = toInt(VehicleProperty::ANDROID_EPOCH_TIME);
+constexpr int32_t int64VecProp = toInt(VehicleProperty::WHEEL_TICK);
+constexpr int32_t floatProp = toInt(VehicleProperty::ENV_OUTSIDE_TEMPERATURE);
+constexpr int32_t floatVecProp = toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION);
+
+std::vector<InvalidPropValueTestCase> getInvalidPropValuesTestCases() {
+ return std::vector<InvalidPropValueTestCase>(
+ {
+ InvalidPropValueTestCase{
+ .name = "int32_normal",
+ .value =
+ {
+ .prop = int32Prop,
+ .value.int32Values = {0},
+ },
+ .valid = true,
+ },
+ InvalidPropValueTestCase{
+ .name = "int32_no_value",
+ .value =
+ {
+ .prop = int32Prop,
+ },
+ },
+ InvalidPropValueTestCase{
+ .name = "int32_more_than_one_value",
+ .value =
+ {
+ .prop = int32Prop,
+ .value.int32Values = {0, 1},
+ },
+ },
+ InvalidPropValueTestCase{
+ .name = "int32_vec_normal",
+ .value =
+ {
+ .prop = int32VecProp,
+ .value.int32Values = {0, 1},
+ },
+ .valid = true,
+ },
+ InvalidPropValueTestCase{
+ .name = "int32_vec_no_value",
+ .value =
+ {
+ .prop = int32VecProp,
+ },
+ },
+ InvalidPropValueTestCase{
+ .name = "int64_normal",
+ .value =
+ {
+ .prop = int64Prop,
+ .value.int64Values = {0},
+ },
+ .valid = true,
+ },
+ InvalidPropValueTestCase{
+ .name = "int64_no_value",
+ .value =
+ {
+ .prop = int64Prop,
+ },
+ },
+ InvalidPropValueTestCase{
+ .name = "int64_more_than_one_value",
+ .value =
+ {
+ .prop = int64Prop,
+ .value.int64Values = {0, 1},
+ },
+ },
+ InvalidPropValueTestCase{
+ .name = "int64_vec_normal",
+ .value =
+ {
+ .prop = int64VecProp,
+ .value.int64Values = {0, 1},
+ },
+ .valid = true,
+ },
+ InvalidPropValueTestCase{
+ .name = "int64_vec_no_value",
+ .value =
+ {
+ .prop = int64VecProp,
+ },
+ },
+ InvalidPropValueTestCase{
+ .name = "float_normal",
+ .value =
+ {
+ .prop = floatProp,
+ .value.floatValues = {0.0},
+ },
+ .valid = true,
+ },
+ InvalidPropValueTestCase{
+ .name = "float_no_value",
+ .value =
+ {
+ .prop = floatProp,
+ },
+ },
+ InvalidPropValueTestCase{
+ .name = "float_more_than_one_value",
+ .value =
+ {
+ .prop = floatProp,
+ .value.floatValues = {0.0, 1.0},
+ },
+ },
+ InvalidPropValueTestCase{
+ .name = "float_vec_normal",
+ .value =
+ {
+ .prop = floatVecProp,
+ .value.floatValues = {0.0, 1.0},
+ },
+ .valid = true,
+ },
+ InvalidPropValueTestCase{
+ .name = "float_vec_no_value",
+ .value =
+ {
+ .prop = floatVecProp,
+ },
+ },
+ InvalidPropValueTestCase{
+ .name = "mixed_normal",
+ .value =
+ {
+ .prop = kMixedTypePropertyForTest,
+ // Expect 3 values.
+ .value.int32Values = {0, 1, 2},
+ // Expect 2 values.
+ .value.int64Values = {0, 1},
+ // Expect 2 values.
+ .value.floatValues = {0.0, 1.0},
+ // Expect 1 value.
+ .value.byteValues = {static_cast<uint8_t>(0)},
+ },
+ .config =
+ {
+ .prop = kMixedTypePropertyForTest,
+ .configArray = {0, 1, 1, 1, 1, 1, 1, 1, 1},
+ },
+ .valid = true,
+ },
+ InvalidPropValueTestCase{
+ .name = "mixed_mismatch_int32_values_count",
+ .value =
+ {
+ .prop = kMixedTypePropertyForTest,
+ // Expect 3 values.
+ .value.int32Values = {0, 1},
+ // Expect 2 values.
+ .value.int64Values = {0, 1},
+ // Expect 2 values.
+ .value.floatValues = {0.0, 1.0},
+ // Expect 1 value.
+ .value.byteValues = {static_cast<uint8_t>(0)},
+ },
+ .config =
+ {
+ .prop = kMixedTypePropertyForTest,
+ .configArray = {0, 1, 1, 1, 1, 1, 1, 1, 1},
+ },
+ },
+ InvalidPropValueTestCase{
+ .name = "mixed_mismatch_int64_values_count",
+ .value =
+ {
+ .prop = kMixedTypePropertyForTest,
+ // Expect 3 values.
+ .value.int32Values = {0, 1, 2},
+ // Expect 2 values.
+ .value.int64Values = {0},
+ // Expect 2 values.
+ .value.floatValues = {0.0, 1.0},
+ // Expect 1 value.
+ .value.byteValues = {static_cast<uint8_t>(0)},
+ },
+ .config =
+ {
+ .prop = kMixedTypePropertyForTest,
+ .configArray = {0, 1, 1, 1, 1, 1, 1, 1, 1},
+ },
+ },
+ InvalidPropValueTestCase{
+ .name = "mixed_mismatch_float_values_count",
+ .value =
+ {
+ .prop = kMixedTypePropertyForTest,
+ // Expect 3 values.
+ .value.int32Values = {0, 1, 2},
+ // Expect 2 values.
+ .value.int64Values = {0, 1},
+ // Expect 2 values.
+ .value.floatValues = {0.0},
+ // Expect 1 value.
+ .value.byteValues = {static_cast<uint8_t>(0)},
+ },
+ .config =
+ {
+ .prop = kMixedTypePropertyForTest,
+ .configArray = {0, 1, 1, 1, 1, 1, 1, 1, 1},
+ },
+ },
+ InvalidPropValueTestCase{
+ .name = "mixed_mismatch_byte_values_count",
+ .value =
+ {
+ .prop = kMixedTypePropertyForTest,
+ // Expect 3 values.
+ .value.int32Values = {0, 1, 2},
+ // Expect 2 values.
+ .value.int64Values = {0, 1},
+ // Expect 2 values.
+ .value.floatValues = {0.0, 1.0},
+ // Expect 1 value.
+ .value.byteValues = {static_cast<uint8_t>(0),
+ static_cast<uint8_t>(1)},
+ },
+ .config =
+ {
+ .prop = kMixedTypePropertyForTest,
+ .configArray = {0, 1, 1, 1, 1, 1, 1, 1, 1},
+ },
+ },
+ });
+}
+
+struct InvalidValueRangeTestCase {
+ std::string name;
+ VehiclePropValue value;
+ bool valid = false;
+ VehicleAreaConfig config;
+};
+
+std::vector<InvalidValueRangeTestCase> getInvalidValueRangeTestCases() {
+ return std::vector<InvalidValueRangeTestCase>({{
+ InvalidValueRangeTestCase{
+ .name = "int32_normal",
+ .value =
+ {
+ .prop = int32Prop,
+ .value.int32Values = {0},
+ },
+ .valid = true,
+ .config =
+ {
+ .minInt32Value = 0,
+ .maxInt32Value = 10,
+ },
+ },
+ InvalidValueRangeTestCase{
+ .name = "int32_vec_normal",
+ .value =
+ {
+ .prop = int32VecProp,
+ .value.int32Values = {0, 1},
+ },
+ .valid = true,
+ .config =
+ {
+ .minInt32Value = 0,
+ .maxInt32Value = 10,
+ },
+ },
+ InvalidValueRangeTestCase{
+ .name = "int32_vec_underflow",
+ .value =
+ {
+ .prop = int32VecProp,
+ .value.int32Values = {-1, 1},
+ },
+
+ .config =
+ {
+ .minInt32Value = 0,
+ .maxInt32Value = 10,
+ },
+ },
+ InvalidValueRangeTestCase{
+ .name = "int32_vec_overflow",
+ .value =
+ {
+ .prop = int32VecProp,
+ .value.int32Values = {0, 100},
+ },
+ .config =
+ {
+ .minInt32Value = 0,
+ .maxInt32Value = 10,
+ },
+ },
+ InvalidValueRangeTestCase{
+ .name = "int64_normal",
+ .value =
+ {
+ .prop = int64Prop,
+ .value.int64Values = {0},
+ },
+ .valid = true,
+ .config =
+ {
+ .minInt64Value = 0,
+ .maxInt64Value = 10,
+ },
+ },
+ InvalidValueRangeTestCase{
+ .name = "int64_vec_normal",
+ .value =
+ {
+ .prop = int64VecProp,
+ .value.int64Values = {0, 1},
+ },
+ .valid = true,
+ .config =
+ {
+ .minInt64Value = 0,
+ .maxInt64Value = 10,
+ },
+ },
+ InvalidValueRangeTestCase{
+ .name = "int64_vec_underflow",
+ .value =
+ {
+ .prop = int64VecProp,
+ .value.int64Values = {-1, 1},
+ },
+
+ .config =
+ {
+ .minInt64Value = 0,
+ .maxInt64Value = 10,
+ },
+ },
+ InvalidValueRangeTestCase{
+ .name = "int64_vec_overflow",
+ .value =
+ {
+ .prop = int64VecProp,
+ .value.int64Values = {0, 100},
+ },
+ .config =
+ {
+ .minInt64Value = 0,
+ .maxInt64Value = 10,
+ },
+ },
+ InvalidValueRangeTestCase{
+ .name = "float_normal",
+ .value =
+ {
+ .prop = floatProp,
+ .value.floatValues = {0.0},
+ },
+ .valid = true,
+ .config =
+ {
+ .minFloatValue = 0.0,
+ .maxFloatValue = 10.0,
+ },
+ },
+ InvalidValueRangeTestCase{
+ .name = "float_vec_normal",
+ .value =
+ {
+ .prop = floatVecProp,
+ .value.floatValues = {0.0, 10.0},
+ },
+ .valid = true,
+ .config =
+ {
+ .minFloatValue = 0.0,
+ .maxFloatValue = 10.0,
+ },
+ },
+ InvalidValueRangeTestCase{
+ .name = "float_vec_underflow",
+ .value =
+ {
+ .prop = floatVecProp,
+ .value.floatValues = {-0.1, 1.1},
+ },
+
+ .config =
+ {
+ .minFloatValue = 0.0,
+ .maxFloatValue = 10.0,
+ },
+ },
+ InvalidValueRangeTestCase{
+ .name = "float_vec_overflow",
+ .value =
+ {
+ .prop = floatVecProp,
+ .value.floatValues = {0.0, 10.1},
+ },
+ .config =
+ {
+ .minFloatValue = 0.0,
+ .maxFloatValue = 10.0,
+ },
+ },
+ }});
+}
+
+} // namespace
+
TEST(VehicleUtilsTest, testToInt) {
int areaGlobal = toInt(VehicleArea::GLOBAL);
@@ -335,6 +759,40 @@
t.join();
}
+class InvalidPropValueTest : public testing::TestWithParam<InvalidPropValueTestCase> {};
+
+INSTANTIATE_TEST_SUITE_P(InvalidPropValueTests, InvalidPropValueTest,
+ testing::ValuesIn(getInvalidPropValuesTestCases()),
+ [](const testing::TestParamInfo<InvalidPropValueTest::ParamType>& info) {
+ return info.param.name;
+ });
+
+TEST_P(InvalidPropValueTest, testCheckPropValue) {
+ InvalidPropValueTestCase tc = GetParam();
+
+ // Config is not used for non-mixed types.
+ auto result = checkPropValue(tc.value, &tc.config);
+
+ ASSERT_EQ(tc.valid, result.ok());
+}
+
+class InvalidValueRangeTest : public testing::TestWithParam<InvalidValueRangeTestCase> {};
+
+INSTANTIATE_TEST_SUITE_P(InvalidValueRangeTests, InvalidValueRangeTest,
+ testing::ValuesIn(getInvalidValueRangeTestCases()),
+ [](const testing::TestParamInfo<InvalidValueRangeTest::ParamType>& info) {
+ return info.param.name;
+ });
+
+TEST_P(InvalidValueRangeTest, testCheckValueRange) {
+ InvalidValueRangeTestCase tc = GetParam();
+
+ // Config is not used for non-mixed types.
+ auto result = checkValueRange(tc.value, &tc.config);
+
+ ASSERT_EQ(tc.valid, result.ok());
+}
+
} // namespace vehicle
} // namespace automotive
} // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
index 43bdca2..4ee3ee9 100644
--- a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
+++ b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
@@ -17,10 +17,14 @@
#ifndef android_hardware_automotive_vehicle_aidl_impl_vhal_include_DefaultVehicleHal_H_
#define android_hardware_automotive_vehicle_aidl_impl_vhal_include_DefaultVehicleHal_H_
+#include "ConnectedClient.h"
+#include "ParcelableUtils.h"
+
#include <IVehicleHardware.h>
-#include <LargeParcelableBase.h>
#include <VehicleUtils.h>
#include <aidl/android/hardware/automotive/vehicle/BnVehicle.h>
+#include <android-base/expected.h>
+#include <android-base/thread_annotations.h>
#include <android/binder_auto_utils.h>
#include <memory>
@@ -37,59 +41,24 @@
constexpr int INVALID_MEMORY_FD = -1;
-template <class T>
-::ndk::ScopedAStatus toScopedAStatus(
- const ::android::base::Result<T>& result,
- ::aidl::android::hardware::automotive::vehicle::StatusCode status) {
- if (result.ok()) {
- return ::ndk::ScopedAStatus::ok();
- }
- return ::ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(toInt(status),
- getErrorMsg(result).c_str());
-}
-
-template <class T>
-::ndk::ScopedAStatus toScopedAStatus(const ::android::base::Result<T>& result) {
- return toScopedAStatus(result, getErrorCode(result));
-}
-
-template <class T1, class T2>
-::ndk::ScopedAStatus vectorToStableLargeParcelable(std::vector<T1>& values, T2* output) {
- auto result = ::android::automotive::car_binder_lib::LargeParcelableBase::
- parcelableVectorToStableLargeParcelable(values);
- if (!result.ok()) {
- return toScopedAStatus(
- result, ::aidl::android::hardware::automotive::vehicle::StatusCode::INTERNAL_ERROR);
- }
- auto& fd = result.value();
- if (fd == nullptr) {
- output->payloads = values;
- } else {
- // Move the returned ScopedFileDescriptor pointer to ScopedFileDescriptor value in
- // 'sharedMemoryFd' field.
- output->sharedMemoryFd.set(fd->get());
- *(fd->getR()) = INVALID_MEMORY_FD;
- }
- return ::ndk::ScopedAStatus::ok();
-}
-
} // namespace defaultvehiclehal_impl
class DefaultVehicleHal final : public ::aidl::android::hardware::automotive::vehicle::BnVehicle {
public:
+ using CallbackType =
+ std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback>;
+
explicit DefaultVehicleHal(std::unique_ptr<IVehicleHardware> hardware);
::ndk::ScopedAStatus getAllPropConfigs(
::aidl::android::hardware::automotive::vehicle::VehiclePropConfigs* returnConfigs)
override;
::ndk::ScopedAStatus getValues(
- const std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback>&
- callback,
+ const CallbackType& callback,
const ::aidl::android::hardware::automotive::vehicle::GetValueRequests& requests)
override;
::ndk::ScopedAStatus setValues(
- const std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback>&
- callback,
+ const CallbackType& callback,
const ::aidl::android::hardware::automotive::vehicle::SetValueRequests& requests)
override;
::ndk::ScopedAStatus getPropConfigs(
@@ -97,27 +66,49 @@
::aidl::android::hardware::automotive::vehicle::VehiclePropConfigs* returnConfigs)
override;
::ndk::ScopedAStatus subscribe(
- const std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback>&
- callback,
+ const CallbackType& callback,
const std::vector<::aidl::android::hardware::automotive::vehicle::SubscribeOptions>&
options,
int32_t maxSharedMemoryFileCount) override;
- ::ndk::ScopedAStatus unsubscribe(
- const std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback>&
- callback,
- const std::vector<int32_t>& propIds) override;
- ::ndk::ScopedAStatus returnSharedMemory(
- const std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback>&
- callback,
- int64_t sharedMemoryId) override;
+ ::ndk::ScopedAStatus unsubscribe(const CallbackType& callback,
+ const std::vector<int32_t>& propIds) override;
+ ::ndk::ScopedAStatus returnSharedMemory(const CallbackType& callback,
+ int64_t sharedMemoryId) override;
IVehicleHardware* getHardware();
private:
+ // friend class for unit testing.
+ friend class DefaultVehicleHalTest;
+
+ using GetValuesClient =
+ GetSetValuesClient<::aidl::android::hardware::automotive::vehicle::GetValueResult,
+ ::aidl::android::hardware::automotive::vehicle::GetValueResults>;
+ using SetValuesClient =
+ GetSetValuesClient<::aidl::android::hardware::automotive::vehicle::SetValueResult,
+ ::aidl::android::hardware::automotive::vehicle::SetValueResults>;
+
const std::unique_ptr<IVehicleHardware> mVehicleHardware;
+
+ // mConfigsByPropId and mConfigFile are only modified during initialization, so no need to
+ // lock guard them.
std::unordered_map<int32_t, ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
mConfigsByPropId;
std::unique_ptr<::ndk::ScopedFileDescriptor> mConfigFile;
+
+ std::mutex mLock;
+ std::unordered_map<CallbackType, std::shared_ptr<GetValuesClient>> mGetValuesClients
+ GUARDED_BY(mLock);
+ std::unordered_map<CallbackType, std::shared_ptr<SetValuesClient>> mSetValuesClients
+ GUARDED_BY(mLock);
+
+ template <class T>
+ std::shared_ptr<T> getOrCreateClient(
+ std::unordered_map<CallbackType, std::shared_ptr<T>>* clients,
+ const CallbackType& callback) REQUIRES(mLock);
+
+ ::android::base::Result<void> checkProperty(
+ const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue);
};
} // namespace vehicle
diff --git a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
index fd9e331..e98f021 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
@@ -21,6 +21,7 @@
#include <LargeParcelableBase.h>
#include <VehicleHalTypes.h>
#include <VehicleUtils.h>
+
#include <android-base/result.h>
#include <utils/Log.h>
@@ -29,14 +30,24 @@
namespace automotive {
namespace vehicle {
+using ::aidl::android::hardware::automotive::vehicle::GetValueRequest;
using ::aidl::android::hardware::automotive::vehicle::GetValueRequests;
+using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
+using ::aidl::android::hardware::automotive::vehicle::GetValueResults;
using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback;
+using ::aidl::android::hardware::automotive::vehicle::SetValueRequest;
using ::aidl::android::hardware::automotive::vehicle::SetValueRequests;
+using ::aidl::android::hardware::automotive::vehicle::SetValueResult;
+using ::aidl::android::hardware::automotive::vehicle::SetValueResults;
using ::aidl::android::hardware::automotive::vehicle::StatusCode;
using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions;
+using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfigs;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
using ::android::automotive::car_binder_lib::LargeParcelableBase;
+using ::android::base::Error;
+using ::android::base::expected;
using ::android::base::Result;
using ::ndk::ScopedAStatus;
@@ -70,15 +81,141 @@
return ScopedAStatus::ok();
}
-ScopedAStatus DefaultVehicleHal::getValues(const std::shared_ptr<IVehicleCallback>&,
- const GetValueRequests&) {
- // TODO(b/200737967): implement this.
+template <class T>
+std::shared_ptr<T> DefaultVehicleHal::getOrCreateClient(
+ std::unordered_map<CallbackType, std::shared_ptr<T>>* clients,
+ const CallbackType& callback) {
+ if (clients->find(callback) == clients->end()) {
+ // TODO(b/204943359): Remove client from clients when linkToDeath is implemented.
+ (*clients)[callback] = std::make_shared<T>(callback);
+ }
+ return (*clients)[callback];
+}
+
+template std::shared_ptr<DefaultVehicleHal::GetValuesClient>
+DefaultVehicleHal::getOrCreateClient<DefaultVehicleHal::GetValuesClient>(
+ std::unordered_map<CallbackType, std::shared_ptr<GetValuesClient>>* clients,
+ const CallbackType& callback);
+
+template std::shared_ptr<DefaultVehicleHal::SetValuesClient>
+DefaultVehicleHal::getOrCreateClient<DefaultVehicleHal::SetValuesClient>(
+ std::unordered_map<CallbackType, std::shared_ptr<SetValuesClient>>* clients,
+ const CallbackType& callback);
+
+Result<void> DefaultVehicleHal::checkProperty(const VehiclePropValue& propValue) {
+ int32_t propId = propValue.prop;
+ auto it = mConfigsByPropId.find(propId);
+ if (it == mConfigsByPropId.end()) {
+ return Error() << "no config for property, ID: " << propId;
+ }
+ const VehiclePropConfig& config = it->second;
+ const VehicleAreaConfig* areaConfig = getAreaConfig(propValue, config);
+ if (!isGlobalProp(propId) && areaConfig == nullptr) {
+ // Ignore areaId for global property. For non global property, check whether areaId is
+ // allowed. areaId must appear in areaConfig.
+ return Error() << "invalid area ID: " << propValue.areaId << " for prop ID: " << propId
+ << ", not listed in config";
+ }
+ if (auto result = checkPropValue(propValue, &config); !result.ok()) {
+ return Error() << "invalid property value: " << propValue.toString()
+ << ", error: " << result.error().message();
+ }
+ if (auto result = checkValueRange(propValue, areaConfig); !result.ok()) {
+ return Error() << "property value out of range: " << propValue.toString()
+ << ", error: " << result.error().message();
+ }
+ return {};
+}
+
+ScopedAStatus DefaultVehicleHal::getValues(const CallbackType& callback,
+ const GetValueRequests& requests) {
+ // TODO(b/203713317): check for duplicate properties and duplicate request IDs.
+
+ const std::vector<GetValueRequest>* getValueRequests;
+ // Define deserializedResults here because we need it to have the same lifetime as
+ // getValueRequests.
+ expected<std::vector<GetValueRequest>, ScopedAStatus> deserializedResults;
+ if (!requests.payloads.empty()) {
+ getValueRequests = &requests.payloads;
+ } else {
+ deserializedResults = stableLargeParcelableToVector<GetValueRequest>(requests);
+ if (!deserializedResults.ok()) {
+ ALOGE("failed to parse getValues requests");
+ return std::move(deserializedResults.error());
+ }
+ getValueRequests = &deserializedResults.value();
+ }
+
+ std::shared_ptr<GetValuesClient> client;
+ {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ client = getOrCreateClient(&mGetValuesClients, callback);
+ }
+
+ if (StatusCode status =
+ mVehicleHardware->getValues(client->getResultCallback(), *getValueRequests);
+ status != StatusCode::OK) {
+ return ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ toInt(status), "failed to get value from VehicleHardware");
+ }
+
return ScopedAStatus::ok();
}
-ScopedAStatus DefaultVehicleHal::setValues(const std::shared_ptr<IVehicleCallback>&,
- const SetValueRequests&) {
- // TODO(b/200737967): implement this.
+ScopedAStatus DefaultVehicleHal::setValues(const CallbackType& callback,
+ const SetValueRequests& requests) {
+ // TODO(b/203713317): check for duplicate properties and duplicate request IDs.
+
+ const std::vector<SetValueRequest>* setValueRequests;
+ // Define deserializedResults here because we need it to have the same lifetime as
+ // setValueRequests.
+ expected<std::vector<SetValueRequest>, ScopedAStatus> deserializedResults;
+ if (!requests.payloads.empty()) {
+ setValueRequests = &requests.payloads;
+ } else {
+ deserializedResults = stableLargeParcelableToVector<SetValueRequest>(requests);
+ if (!deserializedResults.ok()) {
+ ALOGE("failed to parse setValues requests");
+ return std::move(deserializedResults.error());
+ }
+ setValueRequests = &deserializedResults.value();
+ }
+
+ // A list of failed result we already know before sending to hardware.
+ std::vector<SetValueResult> failedResults;
+ // The list of requests that we would send to hardware.
+ std::vector<SetValueRequest> hardwareRequests;
+
+ for (auto& request : *setValueRequests) {
+ int64_t requestId = request.requestId;
+ if (auto result = checkProperty(request.value); !result.ok()) {
+ ALOGW("property not valid: %s", result.error().message().c_str());
+ failedResults.push_back(SetValueResult{
+ .requestId = requestId,
+ .status = StatusCode::INVALID_ARG,
+ });
+ continue;
+ }
+ hardwareRequests.push_back(request);
+ }
+
+ std::shared_ptr<SetValuesClient> client;
+ {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ client = getOrCreateClient(&mSetValuesClients, callback);
+ }
+
+ if (!failedResults.empty()) {
+ client->sendResults(failedResults);
+ }
+
+ if (StatusCode status =
+ mVehicleHardware->setValues(client->getResultCallback(), hardwareRequests);
+ status != StatusCode::OK) {
+ return ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ toInt(status), "failed to set value to VehicleHardware");
+ }
+
return ScopedAStatus::ok();
}
@@ -90,23 +227,21 @@
configs.push_back(mConfigsByPropId[prop]);
}
}
- return defaultvehiclehal_impl::vectorToStableLargeParcelable(configs, output);
+ return vectorToStableLargeParcelable(std::move(configs), output);
}
-ScopedAStatus DefaultVehicleHal::subscribe(const std::shared_ptr<IVehicleCallback>&,
+ScopedAStatus DefaultVehicleHal::subscribe(const CallbackType&,
const std::vector<SubscribeOptions>&, int32_t) {
// TODO(b/200737967): implement this.
return ScopedAStatus::ok();
}
-ScopedAStatus DefaultVehicleHal::unsubscribe(const std::shared_ptr<IVehicleCallback>&,
- const std::vector<int32_t>&) {
+ScopedAStatus DefaultVehicleHal::unsubscribe(const CallbackType&, const std::vector<int32_t>&) {
// TODO(b/200737967): implement this.
return ScopedAStatus::ok();
}
-ScopedAStatus DefaultVehicleHal::returnSharedMemory(const std::shared_ptr<IVehicleCallback>&,
- int64_t) {
+ScopedAStatus DefaultVehicleHal::returnSharedMemory(const CallbackType&, int64_t) {
// TODO(b/200737967): implement this.
return ScopedAStatus::ok();
}
diff --git a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
index 2b5ca70..8934a7b 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
@@ -15,17 +15,24 @@
*/
#include "DefaultVehicleHal.h"
+#include "MockVehicleCallback.h"
#include <IVehicleHardware.h>
#include <LargeParcelableBase.h>
#include <aidl/android/hardware/automotive/vehicle/IVehicle.h>
-#include <android-base/thread_annotations.h>
+#include <aidl/android/hardware/automotive/vehicle/IVehicleCallback.h>
+#include <android-base/thread_annotations.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include <utils/Log.h>
+#include <list>
#include <memory>
+#include <mutex>
#include <optional>
+#include <thread>
+#include <unordered_map>
#include <vector>
namespace android {
@@ -36,38 +43,77 @@
namespace {
using ::aidl::android::hardware::automotive::vehicle::GetValueRequest;
+using ::aidl::android::hardware::automotive::vehicle::GetValueRequests;
using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
+using ::aidl::android::hardware::automotive::vehicle::GetValueResults;
using ::aidl::android::hardware::automotive::vehicle::IVehicle;
+using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback;
using ::aidl::android::hardware::automotive::vehicle::SetValueRequest;
+using ::aidl::android::hardware::automotive::vehicle::SetValueRequests;
using ::aidl::android::hardware::automotive::vehicle::SetValueResult;
+using ::aidl::android::hardware::automotive::vehicle::SetValueResults;
using ::aidl::android::hardware::automotive::vehicle::StatusCode;
+using ::aidl::android::hardware::automotive::vehicle::VehicleAreaWindow;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfigs;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropErrors;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValues;
using ::android::automotive::car_binder_lib::LargeParcelableBase;
using ::android::base::Result;
+using ::ndk::ScopedAStatus;
+using ::ndk::ScopedFileDescriptor;
+
using ::testing::Eq;
using ::testing::WhenSortedBy;
+constexpr int32_t INVALID_PROP_ID = 0;
+// VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:INT32
+constexpr int32_t INT32_WINDOW_PROP = 10001 + 0x10000000 + 0x03000000 + 0x00400000;
+
+template <class T>
+std::optional<T> pop(std::list<T>& items) {
+ if (items.size() > 0) {
+ auto item = std::move(items.front());
+ items.pop_front();
+ return item;
+ }
+ return std::nullopt;
+}
+
+int32_t testInt32VecProp(size_t i) {
+ // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
+ return static_cast<int32_t>(i) + 0x10000000 + 0x01000000 + 0x00410000;
+}
+
class MockVehicleHardware final : public IVehicleHardware {
public:
+ ~MockVehicleHardware() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ for (auto& thread : mThreads) {
+ thread.join();
+ }
+ }
+
std::vector<VehiclePropConfig> getAllPropertyConfigs() const override {
std::scoped_lock<std::mutex> lockGuard(mLock);
return mPropertyConfigs;
}
- StatusCode setValues(std::shared_ptr<const SetValuesCallback>,
- const std::vector<SetValueRequest>&) override {
- // TODO(b/200737967): mock this.
- return StatusCode::OK;
+ StatusCode setValues(std::shared_ptr<const SetValuesCallback> callback,
+ const std::vector<SetValueRequest>& requests) override {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ return handleRequests(__func__, callback, requests, &mSetValueRequests,
+ &mSetValueResponses);
}
- StatusCode getValues(std::shared_ptr<const GetValuesCallback>,
- const std::vector<GetValueRequest>&) const override {
- // TODO(b/200737967): mock this.
- return StatusCode::OK;
+ StatusCode getValues(std::shared_ptr<const GetValuesCallback> callback,
+ const std::vector<GetValueRequest>& requests) const override {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ return handleRequests(__func__, callback, requests, &mGetValueRequests,
+ &mGetValueResponses);
}
DumpResult dump(const std::vector<std::string>&) override {
@@ -94,20 +140,316 @@
mPropertyConfigs = configs;
}
+ void addGetValueResponses(const std::vector<GetValueResult>& responses) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ mGetValueResponses.push_back(responses);
+ }
+
+ void addSetValueResponses(const std::vector<SetValueResult>& responses) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ mSetValueResponses.push_back(responses);
+ }
+
+ std::vector<GetValueRequest> nextGetValueRequests() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ std::optional<std::vector<GetValueRequest>> request = pop(mGetValueRequests);
+ if (!request.has_value()) {
+ return std::vector<GetValueRequest>();
+ }
+ return std::move(request.value());
+ }
+
+ std::vector<SetValueRequest> nextSetValueRequests() {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ std::optional<std::vector<SetValueRequest>> request = pop(mSetValueRequests);
+ if (!request.has_value()) {
+ return std::vector<SetValueRequest>();
+ }
+ return std::move(request.value());
+ }
+
+ void setStatus(const char* functionName, StatusCode status) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ mStatusByFunctions[functionName] = status;
+ }
+
+ void setSleepTime(int64_t timeInNano) {
+ std::scoped_lock<std::mutex> lockGuard(mLock);
+ mSleepTime = timeInNano;
+ }
+
private:
mutable std::mutex mLock;
std::vector<VehiclePropConfig> mPropertyConfigs GUARDED_BY(mLock);
+ mutable std::list<std::vector<GetValueRequest>> mGetValueRequests GUARDED_BY(mLock);
+ mutable std::list<std::vector<GetValueResult>> mGetValueResponses GUARDED_BY(mLock);
+ mutable std::list<std::vector<SetValueRequest>> mSetValueRequests GUARDED_BY(mLock);
+ mutable std::list<std::vector<SetValueResult>> mSetValueResponses GUARDED_BY(mLock);
+ std::unordered_map<const char*, StatusCode> mStatusByFunctions GUARDED_BY(mLock);
+ int64_t mSleepTime GUARDED_BY(mLock) = 0;
+ mutable std::vector<std::thread> mThreads GUARDED_BY(mLock);
+
+ template <class ResultType>
+ StatusCode returnResponse(
+ std::shared_ptr<const std::function<void(std::vector<ResultType>)>> callback,
+ std::list<std::vector<ResultType>>* storedResponses) const;
+
+ template <class RequestType, class ResultType>
+ StatusCode handleRequests(
+ const char* functionName,
+ std::shared_ptr<const std::function<void(std::vector<ResultType>)>> callback,
+ const std::vector<RequestType>& requests,
+ std::list<std::vector<RequestType>>* storedRequests,
+ std::list<std::vector<ResultType>>* storedResponses) const REQUIRES(mLock);
};
+template <class ResultType>
+StatusCode MockVehicleHardware::returnResponse(
+ std::shared_ptr<const std::function<void(std::vector<ResultType>)>> callback,
+ std::list<std::vector<ResultType>>* storedResponses) const {
+ if (storedResponses->size() > 0) {
+ (*callback)(std::move(storedResponses->front()));
+ storedResponses->pop_front();
+ return StatusCode::OK;
+ } else {
+ ALOGE("no more response");
+ return StatusCode::INTERNAL_ERROR;
+ }
+}
+
+template StatusCode MockVehicleHardware::returnResponse<GetValueResult>(
+ std::shared_ptr<const std::function<void(std::vector<GetValueResult>)>> callback,
+ std::list<std::vector<GetValueResult>>* storedResponses) const;
+
+template StatusCode MockVehicleHardware::returnResponse<SetValueResult>(
+ std::shared_ptr<const std::function<void(std::vector<SetValueResult>)>> callback,
+ std::list<std::vector<SetValueResult>>* storedResponses) const;
+
+template <class RequestType, class ResultType>
+StatusCode MockVehicleHardware::handleRequests(
+ const char* functionName,
+ std::shared_ptr<const std::function<void(std::vector<ResultType>)>> callback,
+ const std::vector<RequestType>& requests,
+ std::list<std::vector<RequestType>>* storedRequests,
+ std::list<std::vector<ResultType>>* storedResponses) const {
+ storedRequests->push_back(requests);
+ if (auto it = mStatusByFunctions.find(functionName); it != mStatusByFunctions.end()) {
+ if (StatusCode status = it->second; status != StatusCode::OK) {
+ return status;
+ }
+ }
+
+ if (mSleepTime != 0) {
+ int64_t sleepTime = mSleepTime;
+ mThreads.emplace_back([this, callback, sleepTime, storedResponses]() {
+ std::this_thread::sleep_for(std::chrono::nanoseconds(sleepTime));
+ returnResponse(callback, storedResponses);
+ });
+ return StatusCode::OK;
+
+ } else {
+ return returnResponse(callback, storedResponses);
+ }
+}
+
+template StatusCode MockVehicleHardware::handleRequests<GetValueRequest, GetValueResult>(
+ const char* functionName,
+ std::shared_ptr<const std::function<void(std::vector<GetValueResult>)>> callback,
+ const std::vector<GetValueRequest>& requests,
+ std::list<std::vector<GetValueRequest>>* storedRequests,
+ std::list<std::vector<GetValueResult>>* storedResponses) const;
+
+template StatusCode MockVehicleHardware::handleRequests<SetValueRequest, SetValueResult>(
+ const char* functionName,
+ std::shared_ptr<const std::function<void(std::vector<SetValueResult>)>> callback,
+ const std::vector<SetValueRequest>& requests,
+ std::list<std::vector<SetValueRequest>>* storedRequests,
+ std::list<std::vector<SetValueResult>>* storedResponses) const;
+
struct PropConfigCmp {
bool operator()(const VehiclePropConfig& a, const VehiclePropConfig& b) const {
return (a.prop < b.prop);
}
} propConfigCmp;
+struct SetValuesInvalidRequestTestCase {
+ std::string name;
+ VehiclePropValue request;
+ StatusCode expectedStatus;
+};
+
+std::vector<SetValuesInvalidRequestTestCase> getSetValuesInvalidRequestTestCases() {
+ return {{
+ .name = "config_not_found",
+ .request =
+ {
+ // No config for INVALID_PROP_ID.
+ .prop = INVALID_PROP_ID,
+ },
+ .expectedStatus = StatusCode::INVALID_ARG,
+ },
+ {
+ .name = "invalid_prop_value",
+ .request =
+ {
+ .prop = testInt32VecProp(0),
+ // No int32Values for INT32_VEC property.
+ .value.int32Values = {},
+ },
+ .expectedStatus = StatusCode::INVALID_ARG,
+ },
+ {
+ .name = "value_out_of_range",
+ .request =
+ {
+ .prop = testInt32VecProp(0),
+ // We configured the range to be 0-100.
+ .value.int32Values = {0, -1},
+ },
+ .expectedStatus = StatusCode::INVALID_ARG,
+ },
+ {
+ .name = "invalid_area",
+ .request =
+ {
+ .prop = INT32_WINDOW_PROP,
+ .value.int32Values = {0},
+ // Only ROW_1_LEFT is allowed.
+ .areaId = toInt(VehicleAreaWindow::ROW_1_RIGHT),
+ },
+ .expectedStatus = StatusCode::INVALID_ARG,
+ }};
+}
+
} // namespace
-TEST(DefaultVehicleHalTest, testGetAllPropConfigsSmall) {
+class DefaultVehicleHalTest : public ::testing::Test {
+ public:
+ void SetUp() override {
+ auto hardware = std::make_unique<MockVehicleHardware>();
+ std::vector<VehiclePropConfig> testConfigs;
+ for (size_t i = 0; i < 10000; i++) {
+ testConfigs.push_back(VehiclePropConfig{
+ .prop = testInt32VecProp(i),
+ .areaConfigs =
+ {
+ {
+ .areaId = 0,
+ .minInt32Value = 0,
+ .maxInt32Value = 100,
+ },
+ },
+ });
+ }
+ testConfigs.push_back(
+ VehiclePropConfig{.prop = INT32_WINDOW_PROP,
+ .areaConfigs = {{
+ .areaId = toInt(VehicleAreaWindow::ROW_1_LEFT),
+ .minInt32Value = 0,
+ .maxInt32Value = 100,
+ }}});
+ hardware->setPropertyConfigs(testConfigs);
+ mHardwarePtr = hardware.get();
+ mVhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
+ mVhalClient = IVehicle::fromBinder(mVhal->asBinder());
+ mCallback = ndk::SharedRefBase::make<MockVehicleCallback>();
+ mCallbackClient = IVehicleCallback::fromBinder(mCallback->asBinder());
+ }
+
+ MockVehicleHardware* getHardware() { return mHardwarePtr; }
+
+ std::shared_ptr<IVehicle> getClient() { return mVhal; }
+
+ std::shared_ptr<IVehicleCallback> getCallbackClient() { return mCallbackClient; }
+
+ MockVehicleCallback* getCallback() { return mCallback.get(); }
+
+ static Result<void> getValuesTestCases(size_t size, GetValueRequests& requests,
+ std::vector<GetValueResult>& expectedResults,
+ std::vector<GetValueRequest>& expectedHardwareRequests) {
+ expectedHardwareRequests.clear();
+ for (size_t i = 0; i < size; i++) {
+ int64_t requestId = static_cast<int64_t>(i);
+ int32_t propId = testInt32VecProp(i);
+ expectedHardwareRequests.push_back(GetValueRequest{
+ .prop =
+ VehiclePropValue{
+ .prop = propId,
+ },
+ .requestId = requestId,
+ });
+ expectedResults.push_back(GetValueResult{
+ .requestId = requestId,
+ .status = StatusCode::OK,
+ .prop =
+ VehiclePropValue{
+ .prop = propId,
+ .value.int32Values = {1, 2, 3, 4},
+ },
+ });
+ }
+
+ auto result = LargeParcelableBase::parcelableVectorToStableLargeParcelable(
+ expectedHardwareRequests);
+ if (!result.ok()) {
+ return result.error();
+ }
+ if (result.value() == nullptr) {
+ requests.payloads = expectedHardwareRequests;
+ } else {
+ requests.sharedMemoryFd = std::move(*result.value());
+ }
+ return {};
+ }
+
+ static Result<void> setValuesTestCases(size_t size, SetValueRequests& requests,
+ std::vector<SetValueResult>& expectedResults,
+ std::vector<SetValueRequest>& expectedHardwareRequests) {
+ expectedHardwareRequests.clear();
+ for (size_t i = 0; i < size; i++) {
+ int64_t requestId = static_cast<int64_t>(i);
+ int32_t propId = testInt32VecProp(i);
+ expectedHardwareRequests.push_back(SetValueRequest{
+ .value =
+ VehiclePropValue{
+ .prop = propId,
+ .value.int32Values = {1, 2, 3, 4},
+ },
+ .requestId = requestId,
+ });
+ expectedResults.push_back(SetValueResult{
+ .requestId = requestId,
+ .status = StatusCode::OK,
+ });
+ }
+
+ auto result = LargeParcelableBase::parcelableVectorToStableLargeParcelable(
+ expectedHardwareRequests);
+ if (!result.ok()) {
+ return result.error();
+ }
+ if (result.value() == nullptr) {
+ requests.payloads = expectedHardwareRequests;
+ } else {
+ requests.sharedMemoryFd = std::move(*result.value());
+ }
+ return {};
+ }
+
+ size_t countClients() {
+ std::scoped_lock<std::mutex> lockGuard(mVhal->mLock);
+ return mVhal->mGetValuesClients.size() + mVhal->mSetValuesClients.size();
+ }
+
+ private:
+ std::shared_ptr<DefaultVehicleHal> mVhal;
+ std::shared_ptr<IVehicle> mVhalClient;
+ MockVehicleHardware* mHardwarePtr;
+ std::shared_ptr<MockVehicleCallback> mCallback;
+ std::shared_ptr<IVehicleCallback> mCallbackClient;
+};
+
+TEST_F(DefaultVehicleHalTest, testGetAllPropConfigsSmall) {
auto testConfigs = std::vector<VehiclePropConfig>({
VehiclePropConfig{
.prop = 1,
@@ -125,14 +467,14 @@
VehiclePropConfigs output;
auto status = client->getAllPropConfigs(&output);
- ASSERT_TRUE(status.isOk());
+ ASSERT_TRUE(status.isOk()) << "getAllPropConfigs failed: " << status.getMessage();
ASSERT_THAT(output.payloads, WhenSortedBy(propConfigCmp, Eq(testConfigs)));
}
-TEST(DefaultVehicleHalTest, testGetAllPropConfigsLarge) {
+TEST_F(DefaultVehicleHalTest, testGetAllPropConfigsLarge) {
std::vector<VehiclePropConfig> testConfigs;
- // 10000 VehiclePropConfig exceeds 4k memory limit, so it would be sent through shared memory.
- for (size_t i = 0; i < 10000; i++) {
+ // 5000 VehiclePropConfig exceeds 4k memory limit, so it would be sent through shared memory.
+ for (size_t i = 0; i < 5000; i++) {
testConfigs.push_back(VehiclePropConfig{
.prop = static_cast<int32_t>(i),
});
@@ -146,16 +488,202 @@
VehiclePropConfigs output;
auto status = client->getAllPropConfigs(&output);
- ASSERT_TRUE(status.isOk());
+ ASSERT_TRUE(status.isOk()) << "getAllPropConfigs failed: " << status.getMessage();
ASSERT_TRUE(output.payloads.empty());
Result<std::optional<std::vector<VehiclePropConfig>>> result =
LargeParcelableBase::stableLargeParcelableToParcelableVector<VehiclePropConfig>(
output.sharedMemoryFd);
- ASSERT_TRUE(result.ok());
- ASSERT_TRUE(result.value().has_value());
+ ASSERT_TRUE(result.ok()) << "failed to parse result shared memory file: "
+ << result.error().message();
+ ASSERT_TRUE(result.value().has_value()) << "empty parsed value";
ASSERT_EQ(result.value().value(), testConfigs);
}
+TEST_F(DefaultVehicleHalTest, testGetValuesSmall) {
+ GetValueRequests requests;
+ std::vector<GetValueResult> expectedResults;
+ std::vector<GetValueRequest> expectedHardwareRequests;
+
+ ASSERT_TRUE(getValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok());
+
+ getHardware()->addGetValueResponses(expectedResults);
+
+ auto status = getClient()->getValues(getCallbackClient(), requests);
+
+ ASSERT_TRUE(status.isOk()) << "getValues failed: " << status.getMessage();
+
+ EXPECT_EQ(getHardware()->nextGetValueRequests(), expectedHardwareRequests)
+ << "requests to hardware mismatch";
+
+ auto maybeGetValueResults = getCallback()->nextGetValueResults();
+ ASSERT_TRUE(maybeGetValueResults.has_value()) << "no results in callback";
+ EXPECT_EQ(maybeGetValueResults.value().payloads, expectedResults) << "results mismatch";
+ EXPECT_EQ(countClients(), static_cast<size_t>(1));
+}
+
+TEST_F(DefaultVehicleHalTest, testGetValuesLarge) {
+ GetValueRequests requests;
+ std::vector<GetValueResult> expectedResults;
+ std::vector<GetValueRequest> expectedHardwareRequests;
+
+ ASSERT_TRUE(getValuesTestCases(5000, requests, expectedResults, expectedHardwareRequests).ok())
+ << "requests to hardware mismatch";
+ ;
+
+ getHardware()->addGetValueResponses(expectedResults);
+
+ auto status = getClient()->getValues(getCallbackClient(), requests);
+
+ ASSERT_TRUE(status.isOk()) << "getValues failed: " << status.getMessage();
+
+ EXPECT_EQ(getHardware()->nextGetValueRequests(), expectedHardwareRequests);
+
+ auto maybeGetValueResults = getCallback()->nextGetValueResults();
+ ASSERT_TRUE(maybeGetValueResults.has_value()) << "no results in callback";
+ const GetValueResults& getValueResults = maybeGetValueResults.value();
+ ASSERT_TRUE(getValueResults.payloads.empty())
+ << "payload should be empty, shared memory file should be used";
+
+ auto result = LargeParcelableBase::stableLargeParcelableToParcelableVector<GetValueResult>(
+ getValueResults.sharedMemoryFd);
+ ASSERT_TRUE(result.ok()) << "failed to parse shared memory file";
+ ASSERT_TRUE(result.value().has_value()) << "no parsed value";
+ ASSERT_EQ(result.value().value(), expectedResults) << "results mismatch";
+ EXPECT_EQ(countClients(), static_cast<size_t>(1));
+}
+
+TEST_F(DefaultVehicleHalTest, testGetValuesErrorFromHardware) {
+ GetValueRequests requests;
+ std::vector<GetValueResult> expectedResults;
+ std::vector<GetValueRequest> expectedHardwareRequests;
+
+ ASSERT_TRUE(getValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok());
+
+ getHardware()->setStatus("getValues", StatusCode::INTERNAL_ERROR);
+
+ auto status = getClient()->getValues(getCallbackClient(), requests);
+
+ ASSERT_FALSE(status.isOk()) << "expect getValues to fail when hardware returns error";
+ ASSERT_EQ(status.getServiceSpecificError(), toInt(StatusCode::INTERNAL_ERROR));
+}
+
+TEST_F(DefaultVehicleHalTest, testGetValuesInvalidLargeParcelableInput) {
+ GetValueRequests requests;
+ requests.sharedMemoryFd = ScopedFileDescriptor(0);
+
+ auto status = getClient()->getValues(getCallbackClient(), requests);
+
+ ASSERT_FALSE(status.isOk()) << "expect getValues to fail when input parcelable is not valid";
+ ASSERT_EQ(status.getServiceSpecificError(), toInt(StatusCode::INVALID_ARG));
+}
+
+TEST_F(DefaultVehicleHalTest, testSetValuesSmall) {
+ SetValueRequests requests;
+ std::vector<SetValueResult> expectedResults;
+ std::vector<SetValueRequest> expectedHardwareRequests;
+
+ ASSERT_TRUE(setValuesTestCases(10, requests, expectedResults, expectedHardwareRequests).ok());
+
+ getHardware()->addSetValueResponses(expectedResults);
+
+ auto status = getClient()->setValues(getCallbackClient(), requests);
+
+ ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage();
+
+ EXPECT_EQ(getHardware()->nextSetValueRequests(), expectedHardwareRequests)
+ << "requests to hardware mismatch";
+
+ auto maybeSetValueResults = getCallback()->nextSetValueResults();
+ ASSERT_TRUE(maybeSetValueResults.has_value()) << "no results in callback";
+ ASSERT_EQ(maybeSetValueResults.value().payloads, expectedResults) << "results mismatch";
+ EXPECT_EQ(countClients(), static_cast<size_t>(1));
+}
+
+TEST_F(DefaultVehicleHalTest, testSetValuesLarge) {
+ SetValueRequests requests;
+ std::vector<SetValueResult> expectedResults;
+ std::vector<SetValueRequest> expectedHardwareRequests;
+
+ ASSERT_TRUE(setValuesTestCases(5000, requests, expectedResults, expectedHardwareRequests).ok());
+
+ getHardware()->addSetValueResponses(expectedResults);
+
+ auto status = getClient()->setValues(getCallbackClient(), requests);
+
+ ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage();
+
+ EXPECT_EQ(getHardware()->nextSetValueRequests(), expectedHardwareRequests)
+ << "requests to hardware mismatch";
+
+ auto maybeSetValueResults = getCallback()->nextSetValueResults();
+ ASSERT_TRUE(maybeSetValueResults.has_value()) << "no results in callback";
+ const SetValueResults& setValueResults = maybeSetValueResults.value();
+ ASSERT_TRUE(setValueResults.payloads.empty())
+ << "payload should be empty, shared memory file should be used";
+
+ auto result = LargeParcelableBase::stableLargeParcelableToParcelableVector<SetValueResult>(
+ setValueResults.sharedMemoryFd);
+ ASSERT_TRUE(result.ok()) << "failed to parse shared memory file";
+ ASSERT_TRUE(result.value().has_value()) << "no parsed value";
+ ASSERT_EQ(result.value().value(), expectedResults) << "results mismatch";
+ EXPECT_EQ(countClients(), static_cast<size_t>(1));
+}
+
+class SetValuesInvalidRequestTest
+ : public DefaultVehicleHalTest,
+ public testing::WithParamInterface<SetValuesInvalidRequestTestCase> {};
+
+INSTANTIATE_TEST_SUITE_P(
+ SetValuesInvalidRequestTests, SetValuesInvalidRequestTest,
+ ::testing::ValuesIn(getSetValuesInvalidRequestTestCases()),
+ [](const testing::TestParamInfo<SetValuesInvalidRequestTest::ParamType>& info) {
+ return info.param.name;
+ });
+
+TEST_P(SetValuesInvalidRequestTest, testSetValuesInvalidRequest) {
+ SetValuesInvalidRequestTestCase tc = GetParam();
+ std::vector<SetValueResult> expectedHardwareResults{
+ SetValueResult{
+ .requestId = 1,
+ .status = StatusCode::OK,
+ },
+ };
+ getHardware()->addSetValueResponses(expectedHardwareResults);
+
+ SetValueRequests requests;
+ SetValueRequest invalidRequest{
+ .requestId = 0,
+ .value = tc.request,
+ };
+ SetValueRequest normalRequest{.requestId = 1,
+ .value = {
+ .prop = testInt32VecProp(0),
+ .value.int32Values = {0},
+ }};
+ requests.payloads = {invalidRequest, normalRequest};
+ auto status = getClient()->setValues(getCallbackClient(), requests);
+
+ ASSERT_TRUE(status.isOk()) << "setValues failed: " << status.getMessage();
+
+ EXPECT_EQ(getHardware()->nextSetValueRequests(), std::vector<SetValueRequest>({normalRequest}))
+ << "requests to hardware mismatch";
+
+ auto maybeSetValueResults = getCallback()->nextSetValueResults();
+ ASSERT_TRUE(maybeSetValueResults.has_value()) << "no results in callback";
+ EXPECT_EQ(maybeSetValueResults.value().payloads, std::vector<SetValueResult>({
+ {
+ .requestId = 0,
+ .status = tc.expectedStatus,
+ },
+ }))
+ << "invalid argument result mismatch";
+
+ maybeSetValueResults = getCallback()->nextSetValueResults();
+ ASSERT_TRUE(maybeSetValueResults.has_value()) << "no results from hardware in callback";
+ EXPECT_EQ(maybeSetValueResults.value().payloads, expectedHardwareResults)
+ << "results from hardware mismatch";
+}
+
} // namespace vehicle
} // namespace automotive
} // namespace hardware
diff --git a/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp
index d7d5476..6e8c1d7 100644
--- a/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp
+++ b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.cpp
@@ -41,12 +41,8 @@
BluetoothAudioProvidersFactory::hearing_aid_provider_instance_;
LeAudioOutputAudioProvider
BluetoothAudioProvidersFactory::leaudio_output_provider_instance_;
-LeAudioOffloadOutputAudioProvider
- BluetoothAudioProvidersFactory::leaudio_offload_output_provider_instance_;
LeAudioInputAudioProvider
BluetoothAudioProvidersFactory::leaudio_input_provider_instance_;
-LeAudioOffloadInputAudioProvider
- BluetoothAudioProvidersFactory::leaudio_offload_input_provider_instance_;
Return<void> BluetoothAudioProvidersFactory::openProvider(
const V2_0::SessionType sessionType, openProvider_cb _hidl_cb) {
@@ -94,15 +90,9 @@
case SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH:
provider = &leaudio_output_provider_instance_;
break;
- case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
- provider = &leaudio_offload_output_provider_instance_;
- break;
case SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH:
provider = &leaudio_input_provider_instance_;
break;
- case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
- provider = &leaudio_offload_input_provider_instance_;
- break;
default:
status = BluetoothAudioStatus::FAILURE;
}
diff --git a/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.h b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.h
index f8f557e..714d738 100644
--- a/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.h
+++ b/bluetooth/audio/2.1/default/BluetoothAudioProvidersFactory.h
@@ -56,8 +56,6 @@
static HearingAidAudioProvider hearing_aid_provider_instance_;
static LeAudioOutputAudioProvider leaudio_output_provider_instance_;
static LeAudioInputAudioProvider leaudio_input_provider_instance_;
- static LeAudioOffloadOutputAudioProvider leaudio_offload_output_provider_instance_;
- static LeAudioOffloadInputAudioProvider leaudio_offload_input_provider_instance_;
};
extern "C" IBluetoothAudioProvidersFactory*
diff --git a/bluetooth/audio/2.2/IBluetoothAudioProvider.hal b/bluetooth/audio/2.2/IBluetoothAudioProvider.hal
index bc16b01..f577537 100644
--- a/bluetooth/audio/2.2/IBluetoothAudioProvider.hal
+++ b/bluetooth/audio/2.2/IBluetoothAudioProvider.hal
@@ -59,4 +59,14 @@
*/
startSession_2_2(IBluetoothAudioPort hostIf, AudioConfiguration audioConfig)
generates (Status status, fmq_sync<uint8_t> dataMQ);
+
+ /**
+ * Called when the audio configuration of the stream has been changed.
+ *
+ * @param audioConfig The audio configuration negotiated with the remote
+ * device. The PCM parameters are set if software based encoding,
+ * otherwise the correct codec configuration is used for hardware
+ * encoding.
+ */
+ updateAudioConfiguration(AudioConfiguration audioConfig);
};
diff --git a/bluetooth/audio/2.2/default/BluetoothAudioProvider.cpp b/bluetooth/audio/2.2/default/BluetoothAudioProvider.cpp
index 18ac292..202cfb9 100644
--- a/bluetooth/audio/2.2/default/BluetoothAudioProvider.cpp
+++ b/bluetooth/audio/2.2/default/BluetoothAudioProvider.cpp
@@ -186,6 +186,29 @@
return Void();
}
+Return<void> BluetoothAudioProvider::updateAudioConfiguration(
+ const AudioConfiguration& audioConfig) {
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
+
+ if (stack_iface_ == nullptr) {
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+ << " has NO session";
+ return Void();
+ }
+
+ if (audioConfig.getDiscriminator() != audio_config_.getDiscriminator()) {
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+ << " audio config type is not match";
+ return Void();
+ }
+
+ audio_config_ = audioConfig;
+ BluetoothAudioSessionReport_2_2::ReportAudioConfigChanged(session_type_,
+ audio_config_);
+
+ return Void();
+}
+
} // namespace implementation
} // namespace V2_2
} // namespace audio
diff --git a/bluetooth/audio/2.2/default/BluetoothAudioProvider.h b/bluetooth/audio/2.2/default/BluetoothAudioProvider.h
index 0f1f3c6..425ea3b 100644
--- a/bluetooth/audio/2.2/default/BluetoothAudioProvider.h
+++ b/bluetooth/audio/2.2/default/BluetoothAudioProvider.h
@@ -53,6 +53,8 @@
Return<void> streamStarted(BluetoothAudioStatus status) override;
Return<void> streamSuspended(BluetoothAudioStatus status) override;
Return<void> endSession() override;
+ Return<void> updateAudioConfiguration(
+ const AudioConfiguration& audioConfig) override;
protected:
sp<BluetoothAudioDeathRecipient> death_recipient_;
diff --git a/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp b/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp
index 2fe31d5..490a436 100644
--- a/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp
+++ b/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp
@@ -98,15 +98,9 @@
case V2_1::SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH:
provider = &leaudio_output_provider_instance_;
break;
- case V2_1::SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
- provider = &leaudio_offload_output_provider_instance_;
- break;
case V2_1::SessionType::LE_AUDIO_SOFTWARE_DECODED_DATAPATH:
provider = &leaudio_input_provider_instance_;
break;
- case V2_1::SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
- provider = &leaudio_offload_input_provider_instance_;
- break;
default:
status = BluetoothAudioStatus::FAILURE;
}
@@ -239,7 +233,7 @@
LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
sessionType == V2_1::SessionType::
LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
- std::vector<LeAudioCodecCapabilitiesPair> db_codec_capabilities =
+ std::vector<LeAudioCodecCapabilitiesSetting> db_codec_capabilities =
android::bluetooth::audio::GetLeAudioOffloadCodecCapabilities(
sessionType);
if (db_codec_capabilities.size()) {
diff --git a/bluetooth/audio/2.2/types.hal b/bluetooth/audio/2.2/types.hal
index 8ec3660..6755899 100644
--- a/bluetooth/audio/2.2/types.hal
+++ b/bluetooth/audio/2.2/types.hal
@@ -83,23 +83,22 @@
safe_union AudioCapabilities {
PcmParameters pcmCapabilities;
CodecCapabilities codecCapabilities;
- LeAudioCodecCapabilitiesPair leAudioCapabilities;
+ LeAudioCodecCapabilitiesSetting leAudioCapabilities;
};
/**
- * Used to specify th le audio capabilities pair of the Hardware offload encode and decode.
+ * Used to specify the le audio capabilities for unicast and broadcast hardware offload.
*/
-struct LeAudioCodecCapabilitiesPair{
- LeAudioMode mode;
- LeAudioCodecCapability encodeCapability;
- LeAudioCodecCapability decodeCapability;
+struct LeAudioCodecCapabilitiesSetting{
+ UnicastCapability unicastEncodeCapability;
+ UnicastCapability unicastDecodeCapability;
+ BroadcastCapability broadcastCapability;
};
/**
- * Used to specify the le audio capabilities of the codecs supported by Hardware offload
- * for encode or decode.
+ * Used to specify the le audio unicast codec capabilities for hardware offload.
*/
-struct LeAudioCodecCapability {
+struct UnicastCapability {
CodecType codecType;
AudioLocation supportedChannel;
@@ -112,3 +111,17 @@
// Should use safe union when there is more than one codec
Lc3Parameters capabilities;
};
+
+/**
+ * Used to specify the le audio broadcast codec capabilities for hardware offload.
+ */
+struct BroadcastCapability {
+ CodecType codecType;
+ AudioLocation supportedChannel;
+
+ // Supported channel count for each stream
+ uint8_t channelCountPerStream;
+
+ // Should use safe union when there is more than one codec
+ vec<Lc3Parameters> capabilities;
+};
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h
index 71ab464..368939e 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSessionControl_2_2.h
@@ -48,20 +48,38 @@
std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
if (session_ptr != nullptr) {
- return session_ptr->GetAudioSession()->RegisterStatusCback(cbacks);
+ PortStatusCallbacks_2_2 cb = {
+ .control_result_cb_ = cbacks.control_result_cb_,
+ .session_changed_cb_ = cbacks.session_changed_cb_,
+ .audio_configuration_changed_cb_ = nullptr};
+ return session_ptr->RegisterStatusCback(cb);
+ }
+ return kObserversCookieUndefined;
+ }
+
+ // The control API helps the bluetooth_audio module to register
+ // PortStatusCallbacks_2_2
+ // @return: cookie - the assigned number to this bluetooth_audio output
+ static uint16_t RegisterControlResultCback(
+ const SessionType_2_1& session_type,
+ const PortStatusCallbacks_2_2& cbacks) {
+ std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
+ BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
+ if (session_ptr != nullptr) {
+ return session_ptr->RegisterStatusCback(cbacks);
}
return kObserversCookieUndefined;
}
// The control API helps the bluetooth_audio module to unregister
- // PortStatusCallbacks
+ // PortStatusCallbacks and PortStatusCallbacks_2_2
// @param: cookie - indicates which bluetooth_audio output is
static void UnregisterControlResultCback(const SessionType_2_1& session_type,
uint16_t cookie) {
std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
if (session_ptr != nullptr) {
- session_ptr->GetAudioSession()->UnregisterStatusCback(cookie);
+ session_ptr->UnregisterStatusCback(cookie);
}
}
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSessionReport_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSessionReport_2_2.h
index 79121cc..17e140e 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSessionReport_2_2.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSessionReport_2_2.h
@@ -60,7 +60,20 @@
std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
if (session_ptr != nullptr) {
- session_ptr->GetAudioSession()->ReportControlStatus(start_resp, status);
+ session_ptr->ReportControlStatus(start_resp, status);
+ }
+ }
+ // The API reports the Bluetooth stack has replied the changed of the audio
+ // configuration, and will inform registered bluetooth_audio outputs
+ static void ReportAudioConfigChanged(
+ const ::android::hardware::bluetooth::audio::V2_1::SessionType&
+ session_type,
+ const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
+ audio_config) {
+ std::shared_ptr<BluetoothAudioSession_2_2> session_ptr =
+ BluetoothAudioSessionInstance_2_2::GetSessionInstance(session_type);
+ if (session_ptr != nullptr) {
+ session_ptr->ReportAudioConfigChanged(audio_config);
}
}
};
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
index db1619b..60ac4ec 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
@@ -359,7 +359,7 @@
audio_session->stack_iface_ = stack_iface;
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_2_1_)
<< ", AudioConfiguration=" << toString(audio_config);
- audio_session->ReportSessionStatus();
+ ReportSessionStatus();
};
}
}
@@ -386,7 +386,150 @@
audio_session->stack_iface_ = nullptr;
audio_session->UpdateDataPath(nullptr);
if (toggled) {
+ ReportSessionStatus();
+ }
+}
+
+// The control function helps the bluetooth_audio module to register
+// PortStatusCallbacks_2_2
+// @return: cookie - the assigned number to this bluetooth_audio output
+uint16_t BluetoothAudioSession_2_2::RegisterStatusCback(
+ const PortStatusCallbacks_2_2& cbacks) {
+ if (session_type_2_1_ !=
+ SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
+ session_type_2_1_ !=
+ SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+ PortStatusCallbacks cb = {
+ .control_result_cb_ = cbacks.control_result_cb_,
+ .session_changed_cb_ = cbacks.session_changed_cb_};
+ return audio_session->RegisterStatusCback(cb);
+ }
+
+ std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
+ uint16_t cookie = ObserversCookieGetInitValue(session_type_2_1_);
+ uint16_t cookie_upper_bound = ObserversCookieGetUpperBound(session_type_2_1_);
+
+ while (cookie < cookie_upper_bound) {
+ if (observers_.find(cookie) == observers_.end()) {
+ break;
+ }
+ ++cookie;
+ }
+ if (cookie >= cookie_upper_bound) {
+ LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_2_1_)
+ << " has " << observers_.size()
+ << " observers already (No Resource)";
+ return kObserversCookieUndefined;
+ }
+ std::shared_ptr<struct PortStatusCallbacks_2_2> cb =
+ std::make_shared<struct PortStatusCallbacks_2_2>();
+ *cb = cbacks;
+ observers_[cookie] = cb;
+ return cookie;
+}
+
+// The control function helps the bluetooth_audio module to unregister
+// PortStatusCallbacks_2_2
+// @param: cookie - indicates which bluetooth_audio output is
+void BluetoothAudioSession_2_2::UnregisterStatusCback(uint16_t cookie) {
+ std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
+ if (session_type_2_1_ !=
+ SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
+ session_type_2_1_ !=
+ SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+ audio_session->UnregisterStatusCback(cookie);
+ return;
+ }
+ if (observers_.erase(cookie) != 1) {
+ LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_2_1_)
+ << " no such provider=0x"
+ << android::base::StringPrintf("%04x", cookie);
+ }
+}
+
+// invoking the registered session_changed_cb_
+void BluetoothAudioSession_2_2::ReportSessionStatus() {
+ // This is locked already by OnSessionStarted / OnSessionEnded
+ if (session_type_2_1_ !=
+ SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
+ session_type_2_1_ !=
+ SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
audio_session->ReportSessionStatus();
+ return;
+ }
+ if (observers_.empty()) {
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_2_1_)
+ << " has NO port state observer";
+ return;
+ }
+ for (auto& observer : observers_) {
+ uint16_t cookie = observer.first;
+ std::shared_ptr<struct PortStatusCallbacks_2_2> cb = observer.second;
+ LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_2_1_)
+ << " notify to bluetooth_audio=0x"
+ << android::base::StringPrintf("%04x", cookie);
+ cb->session_changed_cb_(cookie);
+ }
+}
+
+// The report function is used to report that the Bluetooth stack has notified
+// the result of startStream or suspendStream, and will invoke
+// control_result_cb_ to notify registered bluetooth_audio outputs
+void BluetoothAudioSession_2_2::ReportControlStatus(
+ bool start_resp, const BluetoothAudioStatus& status) {
+ if (session_type_2_1_ !=
+ SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
+ session_type_2_1_ !=
+ SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+ audio_session->ReportControlStatus(start_resp, status);
+ return;
+ }
+ std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
+ if (observers_.empty()) {
+ LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_2_1_)
+ << " has NO port state observer";
+ return;
+ }
+ for (auto& observer : observers_) {
+ uint16_t cookie = observer.first;
+ std::shared_ptr<struct PortStatusCallbacks_2_2> cb = observer.second;
+ LOG(INFO) << __func__ << " - status=" << toString(status)
+ << " for SessionType=" << toString(session_type_2_1_)
+ << ", bluetooth_audio=0x"
+ << android::base::StringPrintf("%04x", cookie)
+ << (start_resp ? " started" : " suspended");
+ cb->control_result_cb_(cookie, start_resp, status);
+ }
+}
+
+// The report function is used to report that the Bluetooth stack has notified
+// the result of startStream or suspendStream, and will invoke
+// control_result_cb_ to notify registered bluetooth_audio outputs
+void BluetoothAudioSession_2_2::ReportAudioConfigChanged(
+ const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
+ audio_config) {
+ if (session_type_2_1_ !=
+ SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
+ session_type_2_1_ !=
+ SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+ return;
+ }
+ std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
+ audio_config_2_2_ = audio_config;
+ if (observers_.empty()) {
+ LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_2_1_)
+ << " has NO port state observer";
+ return;
+ }
+ for (auto& observer : observers_) {
+ uint16_t cookie = observer.first;
+ std::shared_ptr<struct PortStatusCallbacks_2_2> cb = observer.second;
+ LOG(INFO) << __func__ << " for SessionType=" << toString(session_type_2_1_)
+ << ", bluetooth_audio=0x"
+ << android::base::StringPrintf("%04x", cookie);
+ if (cb->audio_configuration_changed_cb_ != nullptr) {
+ cb->audio_configuration_changed_cb_(cookie);
+ }
}
}
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
index 6ac0188..3673fd8 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
@@ -28,6 +28,40 @@
namespace bluetooth {
namespace audio {
+inline uint16_t ObserversCookieGetInitValue(
+ const ::android::hardware::bluetooth::audio::V2_1::SessionType&
+ session_type) {
+ return (static_cast<uint16_t>(session_type) << 8 & 0xff00);
+}
+inline uint16_t ObserversCookieGetUpperBound(
+ const ::android::hardware::bluetooth::audio::V2_1::SessionType&
+ session_type) {
+ return (static_cast<uint16_t>(session_type) << 8 & 0xff00) +
+ kObserversCookieSize;
+}
+
+struct PortStatusCallbacks_2_2 {
+ // control_result_cb_ - when the Bluetooth stack reports results of
+ // streamStarted or streamSuspended, the BluetoothAudioProvider will invoke
+ // this callback to report to the bluetooth_audio module.
+ // @param: cookie - indicates which bluetooth_audio output should handle
+ // @param: start_resp - this report is for startStream or not
+ // @param: status - the result of startStream
+ std::function<void(uint16_t cookie, bool start_resp,
+ const BluetoothAudioStatus& status)>
+ control_result_cb_;
+ // session_changed_cb_ - when the Bluetooth stack start / end session, the
+ // BluetoothAudioProvider will invoke this callback to notify to the
+ // bluetooth_audio module.
+ // @param: cookie - indicates which bluetooth_audio output should handle
+ std::function<void(uint16_t cookie)> session_changed_cb_;
+ // audio_configuration_changed_cb_ - when the Bluetooth stack change the audio
+ // configuration, the BluetoothAudioProvider will invoke this callback to
+ // notify to the bluetooth_audio module.
+ // @param: cookie - indicates which bluetooth_audio output should handle
+ std::function<void(uint16_t cookie)> audio_configuration_changed_cb_;
+};
+
class BluetoothAudioSession_2_2 {
private:
std::shared_ptr<BluetoothAudioSession> audio_session;
@@ -50,6 +84,13 @@
static ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
invalidLeOffloadAudioConfiguration;
+ // saving those registered bluetooth_audio's callbacks
+ std::unordered_map<uint16_t, std::shared_ptr<struct PortStatusCallbacks_2_2>>
+ observers_;
+
+ // invoking the registered session_changed_cb_
+ void ReportSessionStatus();
+
public:
BluetoothAudioSession_2_2(
const ::android::hardware::bluetooth::audio::V2_1::SessionType&
@@ -82,6 +123,29 @@
bool SuspendStream();
void StopStream();
+ // The control function helps the bluetooth_audio module to register
+ // PortStatusCallbacks_2_2
+ // @return: cookie - the assigned number to this bluetooth_audio output
+ uint16_t RegisterStatusCback(const PortStatusCallbacks_2_2& cbacks);
+
+ // The control function helps the bluetooth_audio module to unregister
+ // PortStatusCallbacks_2_2
+ // @param: cookie - indicates which bluetooth_audio output is
+ void UnregisterStatusCback(uint16_t cookie);
+
+ // The report function is used to report that the Bluetooth stack has notified
+ // the result of startStream or suspendStream, and will invoke
+ // control_result_cb_ to notify registered bluetooth_audio outputs
+ void ReportControlStatus(bool start_resp, const BluetoothAudioStatus& status);
+
+ // The report function is used to report that the Bluetooth stack has notified
+ // the audio configuration changed, and will invoke
+ // audio_configuration_changed_cb_ to notify registered bluetooth_audio
+ // outputs
+ void ReportAudioConfigChanged(
+ const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
+ audio_config);
+
// The control function is for the bluetooth_audio module to get the current
// AudioConfiguration
const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.cpp b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.cpp
index 34cfd7e..4c99b0f 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.cpp
+++ b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.cpp
@@ -30,16 +30,20 @@
using ::android::hardware::bluetooth::audio::V2_1::Lc3Parameters;
using ::android::hardware::bluetooth::audio::V2_1::SampleRate;
using ::android::hardware::bluetooth::audio::V2_2::AudioLocation;
-using ::android::hardware::bluetooth::audio::V2_2::LeAudioCodecCapabilitiesPair;
-using ::android::hardware::bluetooth::audio::V2_2::LeAudioCodecCapability;
-using ::android::hardware::bluetooth::audio::V2_2::LeAudioMode;
+using ::android::hardware::bluetooth::audio::V2_2::BroadcastCapability;
+using ::android::hardware::bluetooth::audio::V2_2::
+ LeAudioCodecCapabilitiesSetting;
+using ::android::hardware::bluetooth::audio::V2_2::UnicastCapability;
using SessionType_2_1 =
::android::hardware::bluetooth::audio::V2_1::SessionType;
// Stores the list of offload supported capability
-std::vector<LeAudioCodecCapabilitiesPair> kDefaultOffloadLeAudioCapabilities;
+std::vector<LeAudioCodecCapabilitiesSetting> kDefaultOffloadLeAudioCapabilities;
-static const LeAudioCodecCapability kInvalidLc3Capability = {
+static const UnicastCapability kInvalidUnicastCapability = {
+ .codecType = CodecType::UNKNOWN};
+
+static const BroadcastCapability kInvalidBroadcastCapability = {
.codecType = CodecType::UNKNOWN};
// Default Supported Codecs
@@ -94,53 +98,53 @@
return true;
}
-LeAudioCodecCapability composeLc3Capability(AudioLocation audioLocation,
- uint8_t deviceCnt,
- uint8_t channelCount,
- Lc3Parameters capability) {
- return LeAudioCodecCapability{.codecType = CodecType::LC3,
- .supportedChannel = audioLocation,
- .deviceCount = deviceCnt,
- .channelCountPerDevice = channelCount,
- .capabilities = capability};
+UnicastCapability composeUnicastLc3Capability(AudioLocation audioLocation,
+ uint8_t deviceCnt,
+ uint8_t channelCount,
+ Lc3Parameters capability) {
+ return UnicastCapability{.codecType = CodecType::LC3,
+ .supportedChannel = audioLocation,
+ .deviceCount = deviceCnt,
+ .channelCountPerDevice = channelCount,
+ .capabilities = capability};
}
-std::vector<LeAudioCodecCapabilitiesPair> GetLeAudioOffloadCodecCapabilities(
+std::vector<LeAudioCodecCapabilitiesSetting> GetLeAudioOffloadCodecCapabilities(
const SessionType_2_1& session_type) {
if (session_type !=
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
session_type !=
SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
- return std::vector<LeAudioCodecCapabilitiesPair>(0);
+ return std::vector<LeAudioCodecCapabilitiesSetting>(0);
}
if (kDefaultOffloadLeAudioCapabilities.empty()) {
for (auto [audioLocation, deviceCnt, channelCount] :
supportedDeviceSetting) {
for (auto capability : supportedLc3CapabilityList) {
- LeAudioCodecCapability lc3Capability = composeLc3Capability(
+ UnicastCapability lc3Capability = composeUnicastLc3Capability(
audioLocation, deviceCnt, channelCount, capability);
- LeAudioCodecCapability lc3MonoCapability =
- composeLc3Capability(monoAudio, 1, 1, capability);
+ UnicastCapability lc3MonoDecodeCapability =
+ composeUnicastLc3Capability(monoAudio, 1, 1, capability);
// Adds the capability for encode only
kDefaultOffloadLeAudioCapabilities.push_back(
- {.mode = LeAudioMode::UNICAST,
- .encodeCapability = lc3Capability,
- .decodeCapability = kInvalidLc3Capability});
+ {.unicastEncodeCapability = lc3Capability,
+ .unicastDecodeCapability = kInvalidUnicastCapability,
+ .broadcastCapability = kInvalidBroadcastCapability});
// Adds the capability for decode only
kDefaultOffloadLeAudioCapabilities.push_back(
- {.mode = LeAudioMode::UNICAST,
- .encodeCapability = kInvalidLc3Capability,
- .decodeCapability = lc3Capability});
+ {.unicastEncodeCapability = kInvalidUnicastCapability,
+ .unicastDecodeCapability = lc3Capability,
+ .broadcastCapability = kInvalidBroadcastCapability});
// Adds the capability for the case that encode and decode exist at the
// same time
kDefaultOffloadLeAudioCapabilities.push_back(
- {.mode = LeAudioMode::UNICAST,
- .encodeCapability = lc3Capability,
- .decodeCapability = lc3MonoCapability});
+ {.unicastEncodeCapability = lc3Capability,
+ .unicastDecodeCapability = lc3MonoDecodeCapability,
+ .broadcastCapability = kInvalidBroadcastCapability});
}
}
}
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.h
index 89da6a3..34bba5f 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.h
@@ -31,7 +31,7 @@
const ::android::hardware::bluetooth::audio::V2_2::LeAudioConfiguration&
le_audio_codec_config);
-std::vector<hardware::bluetooth::audio::V2_2::LeAudioCodecCapabilitiesPair>
+std::vector<hardware::bluetooth::audio::V2_2::LeAudioCodecCapabilitiesSetting>
GetLeAudioOffloadCodecCapabilities(
const ::android::hardware::bluetooth::audio::V2_1::SessionType&
session_type);
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index c480c13..cf85688 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -209,6 +209,18 @@
<instance>default</instance>
</interface>
</hal>
+ <hal format="aidl" optional="true">
+ <name>android.hardware.drm</name>
+ <version>1</version>
+ <interface>
+ <name>ICryptoFactory</name>
+ <regex-instance>.*</regex-instance>
+ </interface>
+ <interface>
+ <name>IDrmFactory</name>
+ <regex-instance>.*</regex-instance>
+ </interface>
+ </hal>
<hal format="hidl" optional="true">
<name>android.hardware.drm</name>
<version>1.3-4</version>
@@ -393,6 +405,7 @@
<interface>
<name>IRemotelyProvisionedComponent</name>
<instance>default</instance>
+ <instance>strongbox</instance>
</interface>
</hal>
<hal format="aidl" optional="true">
@@ -626,6 +639,13 @@
<instance>strongbox</instance>
</interface>
</hal>
+ <hal format="aidl" optional="true">
+ <name>android.hardware.sensors</name>
+ <interface>
+ <name>ISensors</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
<hal format="hidl" optional="true">
<name>android.hardware.sensors</name>
<version>1.0</version>
diff --git a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/HostEndpointInfo.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/HostEndpointInfo.aidl
index e7dcbc7..84e8531 100644
--- a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/HostEndpointInfo.aidl
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/HostEndpointInfo.aidl
@@ -40,7 +40,7 @@
@nullable String attributionTag;
@Backing(type="int") @VintfStability
enum Type {
- TYPE_FRAMEWORK = 1,
- TYPE_APP = 2,
+ FRAMEWORK = 1,
+ APP = 2,
}
}
diff --git a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHub.aidl b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHub.aidl
index facce4b..f0676be 100644
--- a/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHub.aidl
+++ b/contexthub/aidl/aidl_api/android.hardware.contexthub/current/android/hardware/contexthub/IContextHub.aidl
@@ -35,14 +35,15 @@
@VintfStability
interface IContextHub {
List<android.hardware.contexthub.ContextHubInfo> getContextHubs();
- boolean loadNanoapp(in int contextHubId, in android.hardware.contexthub.NanoappBinary appBinary, in int transactionId);
- boolean unloadNanoapp(in int contextHubId, in long appId, in int transactionId);
- boolean disableNanoapp(in int contextHubId, in long appId, in int transactionId);
- boolean enableNanoapp(in int contextHubId, in long appId, in int transactionId);
+ void loadNanoapp(in int contextHubId, in android.hardware.contexthub.NanoappBinary appBinary, in int transactionId);
+ void unloadNanoapp(in int contextHubId, in long appId, in int transactionId);
+ void disableNanoapp(in int contextHubId, in long appId, in int transactionId);
+ void enableNanoapp(in int contextHubId, in long appId, in int transactionId);
void onSettingChanged(in android.hardware.contexthub.Setting setting, in boolean enabled);
- boolean queryNanoapps(in int contextHubId);
- boolean registerCallback(in int contextHubId, in android.hardware.contexthub.IContextHubCallback cb);
- boolean sendMessageToHub(in int contextHubId, in android.hardware.contexthub.ContextHubMessage message);
+ void queryNanoapps(in int contextHubId);
+ void registerCallback(in int contextHubId, in android.hardware.contexthub.IContextHubCallback cb);
+ void sendMessageToHub(in int contextHubId, in android.hardware.contexthub.ContextHubMessage message);
void onHostEndpointConnected(in android.hardware.contexthub.HostEndpointInfo hostEndpointInfo);
void onHostEndpointDisconnected(char hostEndpointId);
+ const int EX_CONTEXT_HUB_UNSPECIFIED = -1;
}
diff --git a/contexthub/aidl/android/hardware/contexthub/ContextHubMessage.aidl b/contexthub/aidl/android/hardware/contexthub/ContextHubMessage.aidl
index 867da2f..95d478e 100644
--- a/contexthub/aidl/android/hardware/contexthub/ContextHubMessage.aidl
+++ b/contexthub/aidl/android/hardware/contexthub/ContextHubMessage.aidl
@@ -32,10 +32,14 @@
*/
char hostEndPoint;
- /** The type of this message */
+ /**
+ * The type of this message payload, defined by the communication endpoints (i.e.
+ * either the nanoapp or the host endpoint). This value can be used to distinguish
+ * the handling of messageBody (e.g. for decoding).
+ */
int messageType;
- /** The payload containing the message */
+ /** The payload containing the message. */
byte[] messageBody;
/**
diff --git a/contexthub/aidl/android/hardware/contexthub/HostEndpointInfo.aidl b/contexthub/aidl/android/hardware/contexthub/HostEndpointInfo.aidl
index 40a231d..a9d6657 100644
--- a/contexthub/aidl/android/hardware/contexthub/HostEndpointInfo.aidl
+++ b/contexthub/aidl/android/hardware/contexthub/HostEndpointInfo.aidl
@@ -37,12 +37,12 @@
@Backing(type="int")
enum Type {
/**
- This endpoint is from the Android framework, where packageName and attributionTag may be
- empty.
+ * This endpoint is from the Android framework, where packageName and attributionTag may be
+ * empty.
*/
- TYPE_FRAMEWORK = 1,
+ FRAMEWORK = 1,
/** This endpoint is an Android app. */
- TYPE_APP = 2,
+ APP = 2,
}
}
diff --git a/contexthub/aidl/android/hardware/contexthub/IContextHub.aidl b/contexthub/aidl/android/hardware/contexthub/IContextHub.aidl
index 33d241a..2135041 100644
--- a/contexthub/aidl/android/hardware/contexthub/IContextHub.aidl
+++ b/contexthub/aidl/android/hardware/contexthub/IContextHub.aidl
@@ -52,9 +52,12 @@
* @param appBinary The nanoapp binary with header
* @param transactionId The transaction ID associated with this request
*
- * @return The return code
+ * @throws EX_ILLEGAL_ARGUMENT if any of the arguments are invalid.
+ * EX_UNSUPPORTED_OPERATION if this functionality is unsupported.
+ * EX_SERVICE_SPECIFIC on error
+ * - EX_CONTEXT_HUB_UNSPECIFIED if the request failed for other reasons.
*/
- boolean loadNanoapp(in int contextHubId, in NanoappBinary appBinary, in int transactionId);
+ void loadNanoapp(in int contextHubId, in NanoappBinary appBinary, in int transactionId);
/**
* Invokes the nanoapp's deinitialization "end()" entrypoint, and unloads the nanoapp.
@@ -69,9 +72,12 @@
* @param appId The unique ID of the nanoapp
* @param transactionId The transaction ID associated with this request
*
- * @return The return code
+ * @throws EX_ILLEGAL_ARGUMENT if any of the arguments are invalid.
+ * EX_UNSUPPORTED_OPERATION if this functionality is unsupported.
+ * EX_SERVICE_SPECIFIC on error
+ * - EX_CONTEXT_HUB_UNSPECIFIED if the request failed for other reasons.
*/
- boolean unloadNanoapp(in int contextHubId, in long appId, in int transactionId);
+ void unloadNanoapp(in int contextHubId, in long appId, in int transactionId);
/**
* Disables a nanoapp by invoking the nanoapp's "end()" entrypoint, but does not unload the
@@ -87,9 +93,12 @@
* @param appId The unique ID of the nanoapp
* @param transactionId The transaction ID associated with this request
*
- * @return The return code
+ * @throws EX_ILLEGAL_ARGUMENT if any of the arguments are invalid.
+ * EX_UNSUPPORTED_OPERATION if this functionality is unsupported.
+ * EX_SERVICE_SPECIFIC on error
+ * - EX_CONTEXT_HUB_UNSPECIFIED if the request failed for other reasons.
*/
- boolean disableNanoapp(in int contextHubId, in long appId, in int transactionId);
+ void disableNanoapp(in int contextHubId, in long appId, in int transactionId);
/**
* Enables a nanoapp by invoking the nanoapp's initialization "start()" entrypoint.
@@ -104,9 +113,12 @@
* @param appId appIdentifier returned by the HAL
* @param message message to be sent
*
- * @return true on success
+ * @throws EX_ILLEGAL_ARGUMENT if any of the arguments are invalid.
+ * EX_UNSUPPORTED_OPERATION if this functionality is unsupported.
+ * EX_SERVICE_SPECIFIC on error
+ * - EX_CONTEXT_HUB_UNSPECIFIED if the request failed for other reasons.
*/
- boolean enableNanoapp(in int contextHubId, in long appId, in int transactionId);
+ void enableNanoapp(in int contextHubId, in long appId, in int transactionId);
/**
* Notification sent by the framework to indicate that the user has changed a setting.
@@ -124,9 +136,12 @@
*
* @param contextHubId The identifier of the Context Hub
*
- * @return true on success
+ * @throws EX_ILLEGAL_ARGUMENT if any of the arguments are invalid.
+ * EX_UNSUPPORTED_OPERATION if this functionality is unsupported.
+ * EX_SERVICE_SPECIFIC on error
+ * - EX_CONTEXT_HUB_UNSPECIFIED if the request failed for other reasons.
*/
- boolean queryNanoapps(in int contextHubId);
+ void queryNanoapps(in int contextHubId);
/**
* Register a callback for the HAL implementation to send asynchronous messages to the service
@@ -138,10 +153,11 @@
* @param contextHubId The identifier of the Context Hub
* @param callback an implementation of the IContextHubCallbacks
*
- * @return true on success
- *
+ * @throws EX_ILLEGAL_ARGUMENT if any of the arguments are invalid.
+ * EX_SERVICE_SPECIFIC on error
+ * - EX_CONTEXT_HUB_UNSPECIFIED if the request failed for other reasons.
*/
- boolean registerCallback(in int contextHubId, in IContextHubCallback cb);
+ void registerCallback(in int contextHubId, in IContextHubCallback cb);
/**
* Sends a message targeted to a nanoapp to the Context Hub.
@@ -149,9 +165,11 @@
* @param contextHubId The identifier of the Context Hub
* @param message The message to be sent
*
- * @return true on success
+ * @throws EX_ILLEGAL_ARGUMENT if any of the arguments are invalid.
+ * EX_SERVICE_SPECIFIC on error
+ * - EX_CONTEXT_HUB_UNSPECIFIED if the request failed for other reasons.
*/
- boolean sendMessageToHub(in int contextHubId, in ContextHubMessage message);
+ void sendMessageToHub(in int contextHubId, in ContextHubMessage message);
/**
* Invoked when a host endpoint has connected with the ContextHubService.
@@ -173,8 +191,13 @@
*
* @param hostEndPointId The ID of the host that has disconnected.
*
- * @return Status::ok on success
- * EX_ILLEGAL_ARGUMENT if hostEndpointId is not associated with a connected host.
+ * @throws EX_ILLEGAL_ARGUMENT if hostEndpointId is not associated with a connected host.
*/
void onHostEndpointDisconnected(char hostEndpointId);
+
+ /**
+ * Error codes that are used as service specific errors with the AIDL return
+ * value EX_SERVICE_SPECIFIC.
+ */
+ const int EX_CONTEXT_HUB_UNSPECIFIED = -1;
}
diff --git a/contexthub/aidl/default/ContextHub.cpp b/contexthub/aidl/default/ContextHub.cpp
index 6da690d..4c23cbc 100644
--- a/contexthub/aidl/default/ContextHub.cpp
+++ b/contexthub/aidl/default/ContextHub.cpp
@@ -21,7 +21,9 @@
namespace hardware {
namespace contexthub {
-::ndk::ScopedAStatus ContextHub::getContextHubs(std::vector<ContextHubInfo>* out_contextHubInfos) {
+using ::ndk::ScopedAStatus;
+
+ScopedAStatus ContextHub::getContextHubs(std::vector<ContextHubInfo>* out_contextHubInfos) {
ContextHubInfo hub = {};
hub.name = "Mock Context Hub";
hub.vendor = "AOSP";
@@ -39,85 +41,70 @@
}
// We don't expose any nanoapps for the default impl, therefore all nanoapp-related APIs fail.
-::ndk::ScopedAStatus ContextHub::loadNanoapp(int32_t /* in_contextHubId */,
- const NanoappBinary& /* in_appBinary */,
- int32_t /* in_transactionId */, bool* _aidl_return) {
- *_aidl_return = false;
+ScopedAStatus ContextHub::loadNanoapp(int32_t /* in_contextHubId */,
+ const NanoappBinary& /* in_appBinary */,
+ int32_t /* in_transactionId */) {
+ return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ScopedAStatus ContextHub::unloadNanoapp(int32_t /* in_contextHubId */, int64_t /* in_appId */,
+ int32_t /* in_transactionId */) {
+ return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ScopedAStatus ContextHub::disableNanoapp(int32_t /* in_contextHubId */, int64_t /* in_appId */,
+ int32_t /* in_transactionId */) {
+ return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ScopedAStatus ContextHub::enableNanoapp(int32_t /* in_contextHubId */, int64_t /* in_appId */,
+ int32_t /* in_transactionId */) {
+ return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ScopedAStatus ContextHub::onSettingChanged(Setting /* in_setting */, bool /*in_enabled */) {
return ndk::ScopedAStatus::ok();
}
-::ndk::ScopedAStatus ContextHub::unloadNanoapp(int32_t /* in_contextHubId */,
- int64_t /* in_appId */,
- int32_t /* in_transactionId */, bool* _aidl_return) {
- *_aidl_return = false;
- return ndk::ScopedAStatus::ok();
-}
-
-::ndk::ScopedAStatus ContextHub::disableNanoapp(int32_t /* in_contextHubId */,
- int64_t /* in_appId */,
- int32_t /* in_transactionId */,
- bool* _aidl_return) {
- *_aidl_return = false;
- return ndk::ScopedAStatus::ok();
-}
-
-::ndk::ScopedAStatus ContextHub::enableNanoapp(int32_t /* in_contextHubId */,
- int64_t /* in_appId */,
- int32_t /* in_transactionId */, bool* _aidl_return) {
- *_aidl_return = false;
- return ndk::ScopedAStatus::ok();
-}
-
-::ndk::ScopedAStatus ContextHub::onSettingChanged(Setting /* in_setting */, bool /*in_enabled */) {
- return ndk::ScopedAStatus::ok();
-}
-
-::ndk::ScopedAStatus ContextHub::queryNanoapps(int32_t in_contextHubId, bool* _aidl_return) {
+ScopedAStatus ContextHub::queryNanoapps(int32_t in_contextHubId) {
if (in_contextHubId == kMockHubId && mCallback != nullptr) {
std::vector<NanoappInfo> nanoapps;
mCallback->handleNanoappInfo(nanoapps);
- *_aidl_return = true;
+ return ndk::ScopedAStatus::ok();
} else {
- *_aidl_return = false;
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
-
- return ndk::ScopedAStatus::ok();
}
-::ndk::ScopedAStatus ContextHub::registerCallback(int32_t in_contextHubId,
- const std::shared_ptr<IContextHubCallback>& in_cb,
- bool* _aidl_return) {
+ScopedAStatus ContextHub::registerCallback(int32_t in_contextHubId,
+ const std::shared_ptr<IContextHubCallback>& in_cb) {
if (in_contextHubId == kMockHubId) {
mCallback = in_cb;
- *_aidl_return = true;
+ return ndk::ScopedAStatus::ok();
} else {
- *_aidl_return = false;
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
- return ndk::ScopedAStatus::ok();
}
-::ndk::ScopedAStatus ContextHub::sendMessageToHub(int32_t in_contextHubId,
- const ContextHubMessage& /* in_message */,
- bool* _aidl_return) {
+ScopedAStatus ContextHub::sendMessageToHub(int32_t in_contextHubId,
+ const ContextHubMessage& /* in_message */) {
if (in_contextHubId == kMockHubId) {
// Return true here to indicate that the HAL has accepted the message.
// Successful delivery of the message to a nanoapp should be handled at
// a higher level protocol.
- *_aidl_return = true;
+ return ndk::ScopedAStatus::ok();
} else {
- *_aidl_return = false;
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
-
- return ndk::ScopedAStatus::ok();
}
-::ndk::ScopedAStatus ContextHub::onHostEndpointConnected(const HostEndpointInfo& in_info) {
+ScopedAStatus ContextHub::onHostEndpointConnected(const HostEndpointInfo& in_info) {
mConnectedHostEndpoints.insert(in_info.hostEndpointId);
return ndk::ScopedAStatus::ok();
}
-::ndk::ScopedAStatus ContextHub::onHostEndpointDisconnected(char16_t in_hostEndpointId) {
+ScopedAStatus ContextHub::onHostEndpointDisconnected(char16_t in_hostEndpointId) {
if (mConnectedHostEndpoints.count(in_hostEndpointId) > 0) {
mConnectedHostEndpoints.erase(in_hostEndpointId);
return ndk::ScopedAStatus::ok();
diff --git a/contexthub/aidl/default/include/contexthub-impl/ContextHub.h b/contexthub/aidl/default/include/contexthub-impl/ContextHub.h
index dd739e6..03d8432 100644
--- a/contexthub/aidl/default/include/contexthub-impl/ContextHub.h
+++ b/contexthub/aidl/default/include/contexthub-impl/ContextHub.h
@@ -28,21 +28,19 @@
class ContextHub : public BnContextHub {
::ndk::ScopedAStatus getContextHubs(std::vector<ContextHubInfo>* out_contextHubInfos) override;
::ndk::ScopedAStatus loadNanoapp(int32_t in_contextHubId, const NanoappBinary& in_appBinary,
- int32_t in_transactionId, bool* _aidl_return) override;
+ int32_t in_transactionId) override;
::ndk::ScopedAStatus unloadNanoapp(int32_t in_contextHubId, int64_t in_appId,
- int32_t in_transactionId, bool* _aidl_return) override;
+ int32_t in_transactionId) override;
::ndk::ScopedAStatus disableNanoapp(int32_t in_contextHubId, int64_t in_appId,
- int32_t in_transactionId, bool* _aidl_return) override;
+ int32_t in_transactionId) override;
::ndk::ScopedAStatus enableNanoapp(int32_t in_contextHubId, int64_t in_appId,
- int32_t in_transactionId, bool* _aidl_return) override;
+ int32_t in_transactionId) override;
::ndk::ScopedAStatus onSettingChanged(Setting in_setting, bool in_enabled) override;
- ::ndk::ScopedAStatus queryNanoapps(int32_t in_contextHubId, bool* _aidl_return) override;
- ::ndk::ScopedAStatus registerCallback(int32_t in_contextHubId,
- const std::shared_ptr<IContextHubCallback>& in_cb,
- bool* _aidl_return) override;
+ ::ndk::ScopedAStatus queryNanoapps(int32_t in_contextHubId) override;
+ ::ndk::ScopedAStatus registerCallback(
+ int32_t in_contextHubId, const std::shared_ptr<IContextHubCallback>& in_cb) override;
::ndk::ScopedAStatus sendMessageToHub(int32_t in_contextHubId,
- const ContextHubMessage& in_message,
- bool* _aidl_return) override;
+ const ContextHubMessage& in_message) override;
::ndk::ScopedAStatus onHostEndpointConnected(const HostEndpointInfo& in_info) override;
::ndk::ScopedAStatus onHostEndpointDisconnected(char16_t in_hostEndpointId) override;
diff --git a/contexthub/aidl/vts/VtsAidlHalContextHubTargetTest.cpp b/contexthub/aidl/vts/VtsAidlHalContextHubTargetTest.cpp
index 392e23c..a47f64e 100644
--- a/contexthub/aidl/vts/VtsAidlHalContextHubTargetTest.cpp
+++ b/contexthub/aidl/vts/VtsAidlHalContextHubTargetTest.cpp
@@ -103,15 +103,12 @@
};
TEST_P(ContextHubAidl, TestRegisterCallback) {
- bool success;
sp<EmptyContextHubCallback> cb = sp<EmptyContextHubCallback>::make();
- ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb, &success).isOk());
- ASSERT_TRUE(success);
+ ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb).isOk());
}
TEST_P(ContextHubAidl, TestRegisterNullCallback) {
- bool success;
- ASSERT_TRUE(contextHub->registerCallback(getHubId(), nullptr, &success).isOk());
+ ASSERT_TRUE(contextHub->registerCallback(getHubId(), nullptr).isOk());
}
// Helper callback that puts the async appInfo callback data into a promise
@@ -140,12 +137,8 @@
// Calls queryApps() and checks the returned metadata
TEST_P(ContextHubAidl, TestQueryApps) {
sp<QueryAppsCallback> cb = sp<QueryAppsCallback>::make();
- bool success;
- ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb, &success).isOk());
- ASSERT_TRUE(success);
-
- ASSERT_TRUE(contextHub->queryNanoapps(getHubId(), &success).isOk());
- ASSERT_TRUE(success);
+ ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb).isOk());
+ ASSERT_TRUE(contextHub->queryNanoapps(getHubId()).isOk());
std::vector<NanoappInfo> appInfoList;
ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &appInfoList));
@@ -197,9 +190,7 @@
public:
virtual void SetUp() override {
ContextHubAidl::SetUp();
- bool success;
- ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb, &success).isOk());
- ASSERT_TRUE(success);
+ ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb).isOk());
}
sp<TransactionResultCallback> cb = sp<TransactionResultCallback>::make();
@@ -213,9 +204,7 @@
std::fill(message.messageBody.begin(), message.messageBody.end(), 0);
ALOGD("Sending message to non-existent nanoapp");
- bool success;
- ASSERT_TRUE(contextHub->sendMessageToHub(getHubId(), message, &success).isOk());
- ASSERT_TRUE(success);
+ ASSERT_TRUE(contextHub->sendMessageToHub(getHubId(), message).isOk());
}
TEST_P(ContextHubTransactionTest, TestLoadEmptyNanoapp) {
@@ -229,9 +218,7 @@
emptyApp.targetChreApiMinorVersion = 0;
ALOGD("Loading empty nanoapp");
- bool success;
- ASSERT_TRUE(contextHub->loadNanoapp(getHubId(), emptyApp, cb->expectedTransactionId, &success)
- .isOk());
+ bool success = contextHub->loadNanoapp(getHubId(), emptyApp, cb->expectedTransactionId).isOk();
if (success) {
bool transactionSuccess;
ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
@@ -243,11 +230,9 @@
cb->expectedTransactionId = 1234;
ALOGD("Unloading nonexistent nanoapp");
- bool success;
- ASSERT_TRUE(contextHub
- ->unloadNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId,
- &success)
- .isOk());
+ bool success =
+ contextHub->unloadNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId)
+ .isOk();
if (success) {
bool transactionSuccess;
ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
@@ -259,11 +244,9 @@
cb->expectedTransactionId = 2345;
ALOGD("Enabling nonexistent nanoapp");
- bool success;
- ASSERT_TRUE(contextHub
- ->enableNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId,
- &success)
- .isOk());
+ bool success =
+ contextHub->enableNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId)
+ .isOk();
if (success) {
bool transactionSuccess;
ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
@@ -275,11 +258,9 @@
cb->expectedTransactionId = 3456;
ALOGD("Disabling nonexistent nanoapp");
- bool success;
- ASSERT_TRUE(contextHub
- ->disableNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId,
- &success)
- .isOk());
+ bool success =
+ contextHub->disableNanoapp(getHubId(), kNonExistentAppId, cb->expectedTransactionId)
+ .isOk();
if (success) {
bool transactionSuccess;
ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &transactionSuccess));
@@ -290,16 +271,13 @@
void ContextHubAidl::testSettingChanged(Setting setting) {
// In VTS, we only test that sending the values doesn't cause things to blow up - GTS tests
// verify the expected E2E behavior in CHRE
- bool success;
sp<EmptyContextHubCallback> cb = sp<EmptyContextHubCallback>::make();
- ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb, &success).isOk());
- ASSERT_TRUE(success);
+ ASSERT_TRUE(contextHub->registerCallback(getHubId(), cb).isOk());
ASSERT_TRUE(contextHub->onSettingChanged(setting, true /* enabled */).isOk());
ASSERT_TRUE(contextHub->onSettingChanged(setting, false /* enabled */).isOk());
- ASSERT_TRUE(contextHub->registerCallback(getHubId(), nullptr, &success).isOk());
- ASSERT_TRUE(success);
+ ASSERT_TRUE(contextHub->registerCallback(getHubId(), nullptr).isOk());
}
TEST_P(ContextHubAidl, TestOnLocationSettingChanged) {
diff --git a/drm/aidl/Android.bp b/drm/aidl/Android.bp
new file mode 100644
index 0000000..d8500ec
--- /dev/null
+++ b/drm/aidl/Android.bp
@@ -0,0 +1,32 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+ name: "android.hardware.drm",
+ vendor_available: true,
+ srcs: ["android/hardware/drm/*.aidl"],
+ stability: "vintf",
+ imports: [
+ "android.hardware.common-V2",
+ ],
+ backend: {
+ cpp: {
+ enabled: false,
+ },
+ java: {
+ sdk_version: "module_current",
+ },
+ ndk: {
+ vndk: {
+ enabled: true,
+ },
+ min_sdk_version: "current",
+ },
+ },
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/BufferType.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/BufferType.aidl
new file mode 100644
index 0000000..b6ec34d
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/BufferType.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@Backing(type="int") @VintfStability
+enum BufferType {
+ SHARED_MEMORY = 0,
+ NATIVE_HANDLE = 1,
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/DecryptResult.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/DecryptResult.aidl
new file mode 100644
index 0000000..d2b48d2
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/DecryptResult.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@VintfStability
+parcelable DecryptResult {
+ int bytesWritten;
+ String detailedError;
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/DestinationBuffer.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/DestinationBuffer.aidl
new file mode 100644
index 0000000..4f2d133
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/DestinationBuffer.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@VintfStability
+parcelable DestinationBuffer {
+ android.hardware.drm.BufferType type;
+ android.hardware.drm.SharedBuffer nonsecureMemory;
+ android.hardware.common.NativeHandle secureMemory;
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/DrmMetric.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/DrmMetric.aidl
new file mode 100644
index 0000000..c78dff0
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/DrmMetric.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@VintfStability
+parcelable DrmMetric {
+ String name;
+ List<android.hardware.drm.DrmMetricNamedValue> attributes;
+ List<android.hardware.drm.DrmMetricNamedValue> values;
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/DrmMetricGroup.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/DrmMetricGroup.aidl
new file mode 100644
index 0000000..4128eaa
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/DrmMetricGroup.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@VintfStability
+parcelable DrmMetricGroup {
+ List<android.hardware.drm.DrmMetric> metrics;
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/DrmMetricNamedValue.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/DrmMetricNamedValue.aidl
new file mode 100644
index 0000000..76ec35c
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/DrmMetricNamedValue.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@VintfStability
+parcelable DrmMetricNamedValue {
+ String name;
+ android.hardware.drm.DrmMetricValue value;
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/DrmMetricValue.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/DrmMetricValue.aidl
new file mode 100644
index 0000000..8064913
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/DrmMetricValue.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@VintfStability
+union DrmMetricValue {
+ long int64Value;
+ double doubleValue;
+ String stringValue;
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/EventType.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/EventType.aidl
new file mode 100644
index 0000000..80ebb28
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/EventType.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@Backing(type="int") @VintfStability
+enum EventType {
+ PROVISION_REQUIRED = 0,
+ KEY_NEEDED = 1,
+ KEY_EXPIRED = 2,
+ VENDOR_DEFINED = 3,
+ SESSION_RECLAIMED = 4,
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/HdcpLevel.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/HdcpLevel.aidl
new file mode 100644
index 0000000..5704fb0
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/HdcpLevel.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@Backing(type="int") @VintfStability
+enum HdcpLevel {
+ HDCP_UNKNOWN = 0,
+ HDCP_NONE = 1,
+ HDCP_V1 = 2,
+ HDCP_V2 = 3,
+ HDCP_V2_1 = 4,
+ HDCP_V2_2 = 5,
+ HDCP_NO_OUTPUT = 6,
+ HDCP_V2_3 = 7,
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/HdcpLevels.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/HdcpLevels.aidl
new file mode 100644
index 0000000..a6f86ac
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/HdcpLevels.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@VintfStability
+parcelable HdcpLevels {
+ android.hardware.drm.HdcpLevel connectedLevel;
+ android.hardware.drm.HdcpLevel maxLevel;
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/ICryptoFactory.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/ICryptoFactory.aidl
new file mode 100644
index 0000000..0d4296e
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/ICryptoFactory.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@VintfStability
+interface ICryptoFactory {
+ @nullable android.hardware.drm.ICryptoPlugin createPlugin(in android.hardware.drm.Uuid uuid, in byte[] initData);
+ boolean isCryptoSchemeSupported(in android.hardware.drm.Uuid uuid);
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/ICryptoPlugin.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/ICryptoPlugin.aidl
new file mode 100644
index 0000000..2224795
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/ICryptoPlugin.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@VintfStability
+interface ICryptoPlugin {
+ android.hardware.drm.DecryptResult decrypt(in boolean secure, in byte[] keyId, in byte[] iv, in android.hardware.drm.Mode mode, in android.hardware.drm.Pattern pattern, in android.hardware.drm.SubSample[] subSamples, in android.hardware.drm.SharedBuffer source, in long offset, in android.hardware.drm.DestinationBuffer destination);
+ List<android.hardware.drm.LogMessage> getLogMessages();
+ void notifyResolution(in int width, in int height);
+ boolean requiresSecureDecoderComponent(in String mime);
+ void setMediaDrmSession(in byte[] sessionId);
+ void setSharedBufferBase(in android.hardware.common.Ashmem base, in int bufferId);
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/IDrmFactory.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/IDrmFactory.aidl
new file mode 100644
index 0000000..af48737
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/IDrmFactory.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@VintfStability
+interface IDrmFactory {
+ @nullable android.hardware.drm.IDrmPlugin createPlugin(in android.hardware.drm.Uuid uuid, in String appPackageName);
+ List<android.hardware.drm.Uuid> getSupportedCryptoSchemes();
+ boolean isContentTypeSupported(in String mimeType);
+ boolean isCryptoSchemeSupported(in android.hardware.drm.Uuid uuid, in String mimeType, in android.hardware.drm.SecurityLevel securityLevel);
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/IDrmPlugin.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/IDrmPlugin.aidl
new file mode 100644
index 0000000..5f839d7
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/IDrmPlugin.aidl
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@VintfStability
+interface IDrmPlugin {
+ void closeSession(in byte[] sessionId);
+ byte[] decrypt(in byte[] sessionId, in byte[] keyId, in byte[] input, in byte[] iv);
+ byte[] encrypt(in byte[] sessionId, in byte[] keyId, in byte[] input, in byte[] iv);
+ android.hardware.drm.HdcpLevels getHdcpLevels();
+ android.hardware.drm.KeyRequest getKeyRequest(in byte[] scope, in byte[] initData, in String mimeType, in android.hardware.drm.KeyType keyType, in android.hardware.drm.KeyValue[] optionalParameters);
+ List<android.hardware.drm.LogMessage> getLogMessages();
+ List<android.hardware.drm.DrmMetricGroup> getMetrics();
+ android.hardware.drm.NumberOfSessions getNumberOfSessions();
+ List<android.hardware.drm.KeySetId> getOfflineLicenseKeySetIds();
+ android.hardware.drm.OfflineLicenseState getOfflineLicenseState(in android.hardware.drm.KeySetId keySetId);
+ byte[] getPropertyByteArray(in String propertyName);
+ String getPropertyString(in String propertyName);
+ android.hardware.drm.ProvisionRequest getProvisionRequest(in String certificateType, in String certificateAuthority);
+ android.hardware.drm.SecureStop getSecureStop(in android.hardware.drm.SecureStopId secureStopId);
+ List<android.hardware.drm.SecureStopId> getSecureStopIds();
+ List<android.hardware.drm.SecureStop> getSecureStops();
+ android.hardware.drm.SecurityLevel getSecurityLevel(in byte[] sessionId);
+ byte[] openSession(in android.hardware.drm.SecurityLevel securityLevel);
+ android.hardware.drm.KeySetId provideKeyResponse(in byte[] scope, in byte[] response);
+ android.hardware.drm.ProvideProvisionResponseResult provideProvisionResponse(in byte[] response);
+ List<android.hardware.drm.KeyValue> queryKeyStatus(in byte[] sessionId);
+ void releaseAllSecureStops();
+ void releaseSecureStop(in android.hardware.drm.SecureStopId secureStopId);
+ void releaseSecureStops(in android.hardware.drm.OpaqueData ssRelease);
+ void removeAllSecureStops();
+ void removeKeys(in byte[] sessionId);
+ void removeOfflineLicense(in android.hardware.drm.KeySetId keySetId);
+ void removeSecureStop(in android.hardware.drm.SecureStopId secureStopId);
+ boolean requiresSecureDecoder(in String mime, in android.hardware.drm.SecurityLevel level);
+ boolean requiresSecureDecoderDefault(in String mime);
+ void restoreKeys(in byte[] sessionId, in android.hardware.drm.KeySetId keySetId);
+ void setCipherAlgorithm(in byte[] sessionId, in String algorithm);
+ void setListener(in android.hardware.drm.IDrmPluginListener listener);
+ void setMacAlgorithm(in byte[] sessionId, in String algorithm);
+ void setPlaybackId(in byte[] sessionId, in String playbackId);
+ void setPropertyByteArray(in String propertyName, in byte[] value);
+ void setPropertyString(in String propertyName, in String value);
+ byte[] sign(in byte[] sessionId, in byte[] keyId, in byte[] message);
+ byte[] signRSA(in byte[] sessionId, in String algorithm, in byte[] message, in byte[] wrappedkey);
+ boolean verify(in byte[] sessionId, in byte[] keyId, in byte[] message, in byte[] signature);
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/IDrmPluginListener.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/IDrmPluginListener.aidl
new file mode 100644
index 0000000..0a4b4b7
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/IDrmPluginListener.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@VintfStability
+interface IDrmPluginListener {
+ oneway void onEvent(in android.hardware.drm.EventType eventType, in byte[] sessionId, in byte[] data);
+ oneway void onExpirationUpdate(in byte[] sessionId, in long expiryTimeInMS);
+ oneway void onKeysChange(in byte[] sessionId, in android.hardware.drm.KeyStatus[] keyStatusList, in boolean hasNewUsableKey);
+ oneway void onSessionLostState(in byte[] sessionId);
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyRequest.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyRequest.aidl
new file mode 100644
index 0000000..267f532
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyRequest.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@VintfStability
+parcelable KeyRequest {
+ byte[] request;
+ android.hardware.drm.KeyRequestType requestType;
+ String defaultUrl;
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyRequestType.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyRequestType.aidl
new file mode 100644
index 0000000..34b9615
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyRequestType.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@Backing(type="int") @VintfStability
+enum KeyRequestType {
+ INITIAL = 0,
+ RENEWAL = 1,
+ RELEASE = 2,
+ UNKNOWN = 3,
+ NONE = 4,
+ UPDATE = 5,
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeySetId.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeySetId.aidl
new file mode 100644
index 0000000..58dfe1a
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeySetId.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@VintfStability
+parcelable KeySetId {
+ byte[] keySetId;
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyStatus.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyStatus.aidl
new file mode 100644
index 0000000..53ab70f
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyStatus.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@VintfStability
+parcelable KeyStatus {
+ byte[] keyId;
+ android.hardware.drm.KeyStatusType type;
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyStatusType.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyStatusType.aidl
new file mode 100644
index 0000000..e88d388
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyStatusType.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@Backing(type="int") @VintfStability
+enum KeyStatusType {
+ USABLE = 0,
+ EXPIRED = 1,
+ OUTPUTNOTALLOWED = 2,
+ STATUSPENDING = 3,
+ INTERNALERROR = 4,
+ USABLEINFUTURE = 5,
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyType.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyType.aidl
new file mode 100644
index 0000000..7a9d633
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyType.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@Backing(type="int") @VintfStability
+enum KeyType {
+ OFFLINE = 0,
+ STREAMING = 1,
+ RELEASE = 2,
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyValue.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyValue.aidl
new file mode 100644
index 0000000..35d7b77
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/KeyValue.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@VintfStability
+parcelable KeyValue {
+ String key;
+ String value;
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/LogMessage.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/LogMessage.aidl
new file mode 100644
index 0000000..93f76e1
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/LogMessage.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@VintfStability
+parcelable LogMessage {
+ long timeMs;
+ android.hardware.drm.LogPriority priority;
+ String message;
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/LogPriority.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/LogPriority.aidl
new file mode 100644
index 0000000..83362c3
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/LogPriority.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@Backing(type="int") @VintfStability
+enum LogPriority {
+ UNKNOWN = 0,
+ DEFAULT = 1,
+ VERBOSE = 2,
+ DEBUG = 3,
+ INFO = 4,
+ WARN = 5,
+ ERROR = 6,
+ FATAL = 7,
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/Mode.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/Mode.aidl
new file mode 100644
index 0000000..7379774
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/Mode.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@Backing(type="int") @VintfStability
+enum Mode {
+ UNENCRYPTED = 0,
+ AES_CTR = 1,
+ AES_CBC_CTS = 2,
+ AES_CBC = 3,
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/NumberOfSessions.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/NumberOfSessions.aidl
new file mode 100644
index 0000000..a421125
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/NumberOfSessions.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@VintfStability
+parcelable NumberOfSessions {
+ int currentSessions;
+ int maxSessions;
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/OfflineLicenseState.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/OfflineLicenseState.aidl
new file mode 100644
index 0000000..629564d
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/OfflineLicenseState.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@Backing(type="int") @VintfStability
+enum OfflineLicenseState {
+ UNKNOWN = 0,
+ USABLE = 1,
+ INACTIVE = 2,
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/OpaqueData.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/OpaqueData.aidl
new file mode 100644
index 0000000..3085889
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/OpaqueData.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@VintfStability
+parcelable OpaqueData {
+ byte[] opaqueData;
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/Pattern.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/Pattern.aidl
new file mode 100644
index 0000000..b01562e
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/Pattern.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@VintfStability
+parcelable Pattern {
+ int encryptBlocks;
+ int skipBlocks;
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/ProvideProvisionResponseResult.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/ProvideProvisionResponseResult.aidl
new file mode 100644
index 0000000..827de59
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/ProvideProvisionResponseResult.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@VintfStability
+parcelable ProvideProvisionResponseResult {
+ byte[] certificate;
+ byte[] wrappedKey;
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/ProvisionRequest.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/ProvisionRequest.aidl
new file mode 100644
index 0000000..84c5662
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/ProvisionRequest.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@VintfStability
+parcelable ProvisionRequest {
+ byte[] request;
+ String defaultUrl;
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/SecureStop.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/SecureStop.aidl
new file mode 100644
index 0000000..81d2dfe
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/SecureStop.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@VintfStability
+parcelable SecureStop {
+ byte[] opaqueData;
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/SecureStopId.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/SecureStopId.aidl
new file mode 100644
index 0000000..2b904c8
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/SecureStopId.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@VintfStability
+parcelable SecureStopId {
+ byte[] secureStopId;
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/SecurityLevel.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/SecurityLevel.aidl
new file mode 100644
index 0000000..65b2b9d
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/SecurityLevel.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@Backing(type="int") @VintfStability
+enum SecurityLevel {
+ UNKNOWN = 0,
+ SW_SECURE_CRYPTO = 1,
+ SW_SECURE_DECODE = 2,
+ HW_SECURE_CRYPTO = 3,
+ HW_SECURE_DECODE = 4,
+ HW_SECURE_ALL = 5,
+ DEFAULT = 6,
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/SharedBuffer.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/SharedBuffer.aidl
new file mode 100644
index 0000000..973ef0d
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/SharedBuffer.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@VintfStability
+parcelable SharedBuffer {
+ int bufferId;
+ long offset;
+ long size;
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/Status.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/Status.aidl
new file mode 100644
index 0000000..c640689
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/Status.aidl
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@Backing(type="int") @VintfStability
+enum Status {
+ OK = 0,
+ ERROR_DRM_NO_LICENSE = 1,
+ ERROR_DRM_LICENSE_EXPIRED = 2,
+ ERROR_DRM_SESSION_NOT_OPENED = 3,
+ ERROR_DRM_CANNOT_HANDLE = 4,
+ ERROR_DRM_INVALID_STATE = 5,
+ BAD_VALUE = 6,
+ ERROR_DRM_NOT_PROVISIONED = 7,
+ ERROR_DRM_RESOURCE_BUSY = 8,
+ ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION = 9,
+ ERROR_DRM_DEVICE_REVOKED = 10,
+ ERROR_DRM_DECRYPT = 11,
+ ERROR_DRM_UNKNOWN = 12,
+ ERROR_DRM_INSUFFICIENT_SECURITY = 13,
+ ERROR_DRM_FRAME_TOO_LARGE = 14,
+ ERROR_DRM_SESSION_LOST_STATE = 15,
+ ERROR_DRM_RESOURCE_CONTENTION = 16,
+ CANNOT_DECRYPT_ZERO_SUBSAMPLES = 17,
+ CRYPTO_LIBRARY_ERROR = 18,
+ GENERAL_OEM_ERROR = 19,
+ GENERAL_PLUGIN_ERROR = 20,
+ INIT_DATA_INVALID = 21,
+ KEY_NOT_LOADED = 22,
+ LICENSE_PARSE_ERROR = 23,
+ LICENSE_POLICY_ERROR = 24,
+ LICENSE_RELEASE_ERROR = 25,
+ LICENSE_REQUEST_REJECTED = 26,
+ LICENSE_RESTORE_ERROR = 27,
+ LICENSE_STATE_ERROR = 28,
+ MALFORMED_CERTIFICATE = 29,
+ MEDIA_FRAMEWORK_ERROR = 30,
+ MISSING_CERTIFICATE = 31,
+ PROVISIONING_CERTIFICATE_ERROR = 32,
+ PROVISIONING_CONFIGURATION_ERROR = 33,
+ PROVISIONING_PARSE_ERROR = 34,
+ PROVISIONING_REQUEST_REJECTED = 35,
+ RETRYABLE_PROVISIONING_ERROR = 36,
+ SECURE_STOP_RELEASE_ERROR = 37,
+ STORAGE_READ_FAILURE = 38,
+ STORAGE_WRITE_FAILURE = 39,
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/SubSample.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/SubSample.aidl
new file mode 100644
index 0000000..57d815e
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/SubSample.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@VintfStability
+parcelable SubSample {
+ int numBytesOfClearData;
+ int numBytesOfEncryptedData;
+}
diff --git a/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/Uuid.aidl b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/Uuid.aidl
new file mode 100644
index 0000000..ec2eb16
--- /dev/null
+++ b/drm/aidl/aidl_api/android.hardware.drm/current/android/hardware/drm/Uuid.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.drm;
+@VintfStability
+parcelable Uuid {
+ byte[] uuid;
+}
diff --git a/drm/aidl/android/hardware/drm/BufferType.aidl b/drm/aidl/android/hardware/drm/BufferType.aidl
new file mode 100644
index 0000000..089c950
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/BufferType.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+@VintfStability
+@Backing(type="int")
+enum BufferType {
+ SHARED_MEMORY = 0,
+ NATIVE_HANDLE = 1,
+}
diff --git a/drm/aidl/android/hardware/drm/DecryptResult.aidl b/drm/aidl/android/hardware/drm/DecryptResult.aidl
new file mode 100644
index 0000000..17e939b
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/DecryptResult.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+/**
+ * The DecryptResult parcelable contains the result of
+ * ICryptoPlugin decrypt method.
+ */
+@VintfStability
+parcelable DecryptResult {
+ /** The number of decrypted bytes. */
+ int bytesWritten;
+
+ /**
+ * Vendor-specific error message if provided by the vendor's
+ * crypto HAL.
+ */
+ String detailedError;
+}
diff --git a/drm/aidl/android/hardware/drm/DestinationBuffer.aidl b/drm/aidl/android/hardware/drm/DestinationBuffer.aidl
new file mode 100644
index 0000000..0f1e3f5
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/DestinationBuffer.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+import android.hardware.common.NativeHandle;
+import android.hardware.drm.BufferType;
+import android.hardware.drm.SharedBuffer;
+
+/**
+ * A decrypt destination buffer can be either normal user-space shared
+ * memory for the non-secure decrypt case, or it can be a secure buffer
+ * which is referenced by a native-handle. The native handle is allocated
+ * by the vendor's buffer allocator.
+ */
+@VintfStability
+parcelable DestinationBuffer {
+ /**
+ * The type of the buffer
+ */
+ BufferType type;
+ /**
+ * If type == SHARED_MEMORY, the decrypted data must be written
+ * to user-space non-secure shared memory.
+ */
+ SharedBuffer nonsecureMemory;
+ /**
+ * If type == NATIVE_HANDLE, the decrypted data must be written
+ * to secure memory referenced by the vendor's buffer allocator.
+ */
+ NativeHandle secureMemory;
+}
diff --git a/drm/aidl/android/hardware/drm/DrmMetric.aidl b/drm/aidl/android/hardware/drm/DrmMetric.aidl
new file mode 100644
index 0000000..6199af6
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/DrmMetric.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+import android.hardware.drm.DrmMetricNamedValue;
+
+/**
+ * The metric being captured.
+ *
+ * A metric must have a name and at least one value. A metric may have 0 or
+ * more attributes. The fields of a Metric are opaque to the framework.
+ */
+@VintfStability
+parcelable DrmMetric {
+ String name;
+
+ /**
+ * Detail(s) about the metric being captured.
+ *
+ * The fields of an Attribute are opaque to the framework.
+ */
+ List<DrmMetricNamedValue> attributes;
+
+ /**
+ * Value(s) of the metric.
+ *
+ * A metric may have multiple values. The component name may be left empty
+ * if there is only supposed to be one value for the given metric. The
+ * fields of the Value are opaque to the framework.
+ */
+ List<DrmMetricNamedValue> values;
+}
diff --git a/drm/aidl/android/hardware/drm/DrmMetricGroup.aidl b/drm/aidl/android/hardware/drm/DrmMetricGroup.aidl
new file mode 100644
index 0000000..3b1f3c9
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/DrmMetricGroup.aidl
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+import android.hardware.drm.DrmMetric;
+
+/**
+ * This message contains plugin-specific metrics made available to the client.
+ * The message is used for making vendor-specific metrics available to an
+ * application. The framework is not consuming any of the information.
+ *
+ * Metrics are grouped in instances of DrmMetricGroup. Each group contains
+ * multiple instances of Metric.
+ *
+ * Example:
+ *
+ * Capture the timing information of a buffer copy event, "buf_copy", broken
+ * out by the "size" of the buffer.
+ *
+ * DrmMetricGroup {
+ * metrics[0] {
+ * name: "buf_copy"
+ * attributes[0] {
+ * name: "size"
+ * type: INT64_TYPE
+ * int64Value: 1024
+ * }
+ * values[0] {
+ * componentName: "operation_count"
+ * type: INT64_TYPE
+ * int64Value: 75
+ * }
+ * values[1] {
+ * component_name: "average_time_seconds"
+ * type: DOUBLE_TYPE
+ * doubleValue: 0.00000042
+ * }
+ * }
+ * }
+ */
+@VintfStability
+parcelable DrmMetricGroup {
+ /**
+ * The list of metrics to be captured.
+ */
+ List<DrmMetric> metrics;
+}
diff --git a/drm/aidl/android/hardware/drm/DrmMetricNamedValue.aidl b/drm/aidl/android/hardware/drm/DrmMetricNamedValue.aidl
new file mode 100644
index 0000000..5bb17a6
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/DrmMetricNamedValue.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+import android.hardware.drm.DrmMetricValue;
+
+/**
+ * A name-value pair used in drm metrics.
+ */
+@VintfStability
+parcelable DrmMetricNamedValue {
+ String name;
+ DrmMetricValue value;
+}
diff --git a/drm/aidl/android/hardware/drm/DrmMetricValue.aidl b/drm/aidl/android/hardware/drm/DrmMetricValue.aidl
new file mode 100644
index 0000000..0203f3f
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/DrmMetricValue.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+/**
+ * The value of a metric or a metric's attribute.
+ */
+@VintfStability
+union DrmMetricValue {
+ long int64Value;
+ double doubleValue;
+ String stringValue;
+}
diff --git a/drm/aidl/android/hardware/drm/EventType.aidl b/drm/aidl/android/hardware/drm/EventType.aidl
new file mode 100644
index 0000000..7a06eb0
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/EventType.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+/**
+ * EventType enumerates the events that can be delivered by sendEvent
+ */
+@VintfStability
+@Backing(type="int")
+enum EventType {
+ /**
+ * This event type indicates that the app needs to request a certificate
+ * from the provisioning server. The request message data is obtained using
+ * getProvisionRequest().
+ */
+ PROVISION_REQUIRED,
+ /**
+ * This event type indicates that the app needs to request keys from a
+ * license server. The request message data is obtained using getKeyRequest.
+ */
+ KEY_NEEDED,
+ /**
+ * This event type indicates that the licensed usage duration for keys in a
+ * session has expired. The keys are no longer valid.
+ */
+ KEY_EXPIRED,
+ /**
+ * This event may indicate some specific vendor-defined condition, see your
+ * DRM provider documentation for details.
+ */
+ VENDOR_DEFINED,
+ /**
+ * This event indicates that a session opened by the app has been reclaimed
+ * by the resource manager.
+ */
+ SESSION_RECLAIMED,
+}
diff --git a/drm/aidl/android/hardware/drm/HdcpLevel.aidl b/drm/aidl/android/hardware/drm/HdcpLevel.aidl
new file mode 100644
index 0000000..3497b78
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/HdcpLevel.aidl
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+/**
+ * HDCP specifications are defined by Digital Content Protection LLC (DCP).
+ * "HDCP Specification Rev. 2.3 Interface Independent Adaptation"
+ * "HDCP 2.3 on HDMI Specification"
+ */
+@VintfStability
+@Backing(type="int")
+enum HdcpLevel {
+ /**
+ * Unable to determine the HDCP level
+ */
+ HDCP_UNKNOWN,
+ /**
+ * No HDCP, output is unprotected
+ */
+ HDCP_NONE,
+ /**
+ * HDCP version 1.0
+ */
+ HDCP_V1,
+ /**
+ * HDCP version 2.0 Type 1.
+ */
+ HDCP_V2,
+ /**
+ * HDCP version 2.1 Type 1.
+ */
+ HDCP_V2_1,
+ /**
+ * HDCP version 2.2 Type 1.
+ */
+ HDCP_V2_2,
+ /**
+ * No digital output, implicitly secure
+ */
+ HDCP_NO_OUTPUT,
+ /**
+ * HDCP version 2.3 Type 1.
+ */
+ HDCP_V2_3,
+}
diff --git a/drm/aidl/android/hardware/drm/HdcpLevels.aidl b/drm/aidl/android/hardware/drm/HdcpLevels.aidl
new file mode 100644
index 0000000..cd4642b
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/HdcpLevels.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+import android.hardware.drm.HdcpLevel;
+
+@VintfStability
+parcelable HdcpLevels {
+ /** The lowest HDCP level for any connected displays. */
+ HdcpLevel connectedLevel;
+
+ /** The highest HDCP level that can be supported by the device. */
+ HdcpLevel maxLevel;
+}
diff --git a/drm/aidl/android/hardware/drm/ICryptoFactory.aidl b/drm/aidl/android/hardware/drm/ICryptoFactory.aidl
new file mode 100644
index 0000000..202bd3d
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/ICryptoFactory.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+import android.hardware.drm.Uuid;
+
+/**
+ * ICryptoFactory is the main entry point for interacting with a vendor's
+ * crypto HAL to create crypto plugins.
+
+ * Crypto plugins create crypto sessions which are used by a codec to decrypt
+ * protected video content.
+ */
+@VintfStability
+interface ICryptoFactory {
+ /**
+ * Create a crypto plugin for the specified uuid and scheme-specific
+ * initialization data.
+ *
+ * @param uuid uniquely identifies the drm scheme. See
+ * http://dashif.org/identifiers/protection for uuid assignments
+ *
+ * @param initData scheme-specific init data.
+ *
+ * @return A crypto plugin instance if successful, or null if not created.
+ */
+ @nullable android.hardware.drm.ICryptoPlugin createPlugin(
+ in Uuid uuid, in byte[] initData);
+
+ /**
+ * Determine if a crypto scheme is supported by this HAL.
+ *
+ * @param uuid identifies the crypto scheme in question
+ * @return must be true only if the scheme is supported
+ */
+ boolean isCryptoSchemeSupported(in Uuid uuid);
+}
diff --git a/drm/aidl/android/hardware/drm/ICryptoPlugin.aidl b/drm/aidl/android/hardware/drm/ICryptoPlugin.aidl
new file mode 100644
index 0000000..80a63df
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/ICryptoPlugin.aidl
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+import android.hardware.common.Ashmem;
+import android.hardware.drm.DecryptResult;
+import android.hardware.drm.DestinationBuffer;
+import android.hardware.drm.LogMessage;
+import android.hardware.drm.Mode;
+import android.hardware.drm.Pattern;
+import android.hardware.drm.SharedBuffer;
+import android.hardware.drm.Status;
+import android.hardware.drm.SubSample;
+
+/**
+ * ICryptoPlugin is the HAL for vendor-provided crypto plugins.
+ *
+ * It allows crypto sessions to be opened and operated on, to
+ * load crypto keys for a codec to decrypt protected video content.
+ */
+@VintfStability
+interface ICryptoPlugin {
+ /**
+ * Decrypt an array of subsamples from the source memory buffer to the
+ * destination memory buffer.
+ *
+ * @param secure a flag to indicate if a secure decoder is being used.
+ * This enables the plugin to configure buffer modes to work
+ * consistently with a secure decoder.
+ * @param the keyId for the key that is used to do the decryption. The
+ * keyId refers to a key in the associated MediaDrm instance.
+ * @param iv the initialization vector to use
+ * @param mode the crypto mode to use
+ * @param pattern the crypto pattern to use
+ * @param subSamples a vector of subsamples indicating the number
+ * of clear and encrypted bytes to process. This allows the decrypt
+ * call to operate on a range of subsamples in a single call
+ * @param source the input buffer for the decryption
+ * @param offset the offset of the first byte of encrypted data from
+ * the base of the source buffer
+ * @param destination the output buffer for the decryption
+ *
+ * @return DecryptResult parcelable
+ * Implicit error codes:
+ * + ERROR_DRM_CANNOT_HANDLE in other failure cases
+ * + ERROR_DRM_DECRYPT if the decrypt operation fails
+ * + ERROR_DRM_FRAME_TOO_LARGE if the frame being decrypted into
+ * the secure output buffer exceeds the size of the buffer
+ * + ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION if required output
+ * protections are not active
+ * + ERROR_DRM_INSUFFICIENT_SECURITY if the security level of the
+ * device is not sufficient to meet the requirements in
+ * the license policy
+ * + ERROR_DRM_INVALID_STATE if the device is in a state where it
+ * is not able to perform decryption
+ * + ERROR_DRM_LICENSE_EXPIRED if the license keys have expired
+ * + ERROR_DRM_NO_LICENSE if no license keys have been loaded
+ * + ERROR_DRM_RESOURCE_BUSY if the resources required to perform
+ * the decryption are not available
+ * + ERROR_DRM_SESSION_NOT_OPENED if the decrypt session is not
+ * opened
+ */
+ DecryptResult decrypt(in boolean secure, in byte[] keyId, in byte[] iv, in Mode mode,
+ in Pattern pattern, in SubSample[] subSamples, in SharedBuffer source, in long offset,
+ in DestinationBuffer destination);
+
+ /**
+ * Get OEMCrypto or plugin error messages.
+ *
+ * @return LogMessages
+ * Implicit error codes:
+ * + GENERAL_OEM_ERROR on OEM-provided, low-level component failures;
+ * + GENERAL_PLUGIN_ERROR on unexpected plugin-level errors.
+ */
+ List<LogMessage> getLogMessages();
+
+ /**
+ * Notify a plugin of the currently configured resolution.
+ *
+ * @param width - the display resolutions's width
+ * @param height - the display resolution's height
+ */
+ void notifyResolution(in int width, in int height);
+
+ /**
+ * Check if the specified mime-type requires a secure decoder
+ * component.
+ *
+ * @param mime The content mime-type
+ * @return must be true only if a secure decoder is required
+ * for the specified mime-type
+ */
+ boolean requiresSecureDecoderComponent(in String mime);
+
+ /**
+ * Associate a mediadrm session with this crypto session.
+ *
+ * @param sessionId the MediaDrm session ID to associate with
+ * this crypto session
+ * @return (implicit) the status of the call, status can be:
+ * ERROR_DRM_SESSION_NOT_OPENED if the session is not opened, or
+ * ERROR_DRM_CANNOT_HANDLE if the operation is not supported by
+ * the drm scheme
+ */
+ void setMediaDrmSession(in byte[] sessionId);
+
+ /**
+ * Set a shared memory base for subsequent decrypt operations.
+ * The buffer base is mmaped from a ParcelFileDesciptor in Ashmem
+ * which maps shared memory in the HAL module.
+ * After the shared buffer base is established, the decrypt() method
+ * receives SharedBuffer instances which specify the buffer address range
+ * for decrypt source and destination addresses.
+ *
+ * There can be multiple shared buffers per crypto plugin. The buffers
+ * are distinguished by the bufferId.
+ *
+ * @param base the base of the memory buffer identified by
+ * bufferId
+ * @param bufferId identifies the specific shared buffer for which
+ * the base is being set.
+ */
+ void setSharedBufferBase(in Ashmem base, in int bufferId);
+}
diff --git a/drm/aidl/android/hardware/drm/IDrmFactory.aidl b/drm/aidl/android/hardware/drm/IDrmFactory.aidl
new file mode 100644
index 0000000..b9622a4
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/IDrmFactory.aidl
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+import android.hardware.drm.SecurityLevel;
+import android.hardware.drm.Uuid;
+
+/**
+ * IDrmFactory is the main entry point for interacting with a vendor's
+ * drm HAL to create drm plugin instances. A drm plugin instance
+ * creates drm sessions which are used to obtain keys for a crypto
+ * session so it can decrypt protected video content.
+ */
+@VintfStability
+interface IDrmFactory {
+ /**
+ * Create a drm plugin instance for the specified uuid and
+ * scheme-specific initialization data.
+ *
+ * @param uuid uniquely identifies the drm scheme. See
+ * http://dashif.org/identifiers/protection for uuid assignments
+ * @param appPackageName identifies the package name of the calling
+ * application.
+ *
+ * @return A DRM plugin instance if successful, or null if not created.
+ * Implicit error codes:
+ * + ERROR_DRM_CANNOT_HANDLE if the plugin cannot be created.
+ */
+ @nullable android.hardware.drm.IDrmPlugin createPlugin(
+ in Uuid uuid, in String appPackageName);
+
+ /**
+ * Return vector of uuids identifying crypto schemes supported by
+ * this HAL.
+ *
+ * @return List of uuids for which isCryptoSchemeSupported is true;
+ * each uuid can be used as input to createPlugin.
+ */
+ List<Uuid> getSupportedCryptoSchemes();
+
+ /**
+ * Determine if the HAL factory is able to construct plugins that
+ * support a given media container format specified by mimeType
+ *
+ * @param mimeType identifies the mime type in question
+ *
+ * @return must be true only if the scheme is supported
+ */
+ boolean isContentTypeSupported(in String mimeType);
+
+ /**
+ * Determine if a specific security level is supported by the device.
+ *
+ * @param uuid identifies the crypto scheme in question
+ * @param mimeType identifies the mime type in question
+ * @param securityLevel specifies the security level required
+ *
+ * @return must be true only if the scheme is supported
+ */
+ boolean isCryptoSchemeSupported(
+ in Uuid uuid, in String mimeType, in SecurityLevel securityLevel);
+}
diff --git a/drm/aidl/android/hardware/drm/IDrmPlugin.aidl b/drm/aidl/android/hardware/drm/IDrmPlugin.aidl
new file mode 100644
index 0000000..e649f26
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/IDrmPlugin.aidl
@@ -0,0 +1,755 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+import android.hardware.drm.DrmMetricGroup;
+import android.hardware.drm.HdcpLevels;
+import android.hardware.drm.IDrmPluginListener;
+import android.hardware.drm.KeySetId;
+import android.hardware.drm.KeyRequest;
+import android.hardware.drm.KeyStatus;
+import android.hardware.drm.KeyType;
+import android.hardware.drm.KeyValue;
+import android.hardware.drm.LogMessage;
+import android.hardware.drm.NumberOfSessions;
+import android.hardware.drm.OfflineLicenseState;
+import android.hardware.drm.OpaqueData;
+import android.hardware.drm.ProvideProvisionResponseResult;
+import android.hardware.drm.ProvisionRequest;
+import android.hardware.drm.SecureStop;
+import android.hardware.drm.SecureStopId;
+import android.hardware.drm.SecurityLevel;
+
+/**
+ * IDrmPlugin is used to interact with a specific drm plugin that was
+ * created by IDrmFactory::createPlugin.
+ *
+ * A drm plugin provides methods for obtaining drm keys to be used by a codec
+ * to decrypt protected video content.
+ */
+@VintfStability
+interface IDrmPlugin {
+ /**
+ * Close a session on the DrmPlugin object
+ *
+ * @param sessionId the session id the call applies to
+ *
+ * @return (implicit) the status of the call:
+ * BAD_VALUE if the sessionId is invalid
+ * ERROR_DRM_INVALID_STATE if the HAL is in a state where
+ * the session cannot be closed.
+ * ERROR_DRM_SESSION_NOT_OPENED if the session is not opened
+ */
+ void closeSession(in byte[] sessionId);
+
+ /**
+ * Decrypt the provided input buffer with the cipher algorithm
+ * specified by setCipherAlgorithm and the key selected by keyId,
+ * and return the decrypted data.
+ *
+ * @param sessionId the session id the call applies to
+ * @param keyId the ID of the key to use for decryption
+ * @param input the input data to decrypt
+ * @param iv the initialization vector to use for decryption
+ *
+ * @return decrypted output buffer
+ * Implicit error codes:
+ * + BAD_VALUE if the sessionId is invalid
+ * + ERROR_DRM_INVALID_STATE if the HAL is in a state where
+ * the decrypt operation cannot be performed.
+ * + ERROR_DRM_SESSION_NOT_OPENED if the session is not opened
+ */
+ byte[] decrypt(in byte[] sessionId, in byte[] keyId, in byte[] input, in byte[] iv);
+
+ /**
+ * Encrypt the provided input buffer with the cipher algorithm specified by
+ * setCipherAlgorithm and the key selected by keyId, and return the
+ * encrypted data.
+ *
+ * @param sessionId the session id the call applies to
+ * @param keyId the ID of the key to use for encryption
+ * @param input the input data to encrypt
+ * @param iv the initialization vector to use for encryption
+ *
+ * @return encrypted output buffer
+ * Implicit error codes:
+ * + BAD_VALUE if the sessionId is invalid
+ * + ERROR_DRM_INVALID_STATE if the HAL is in a state where
+ * the encrypt operation cannot be performed.
+ * + ERROR_DRM_SESSION_NOT_OPENED if the session is not opened
+ */
+ byte[] encrypt(in byte[] sessionId, in byte[] keyId, in byte[] input, in byte[] iv);
+
+ /**
+ * Return the currently negotiated and max supported HDCP levels.
+ *
+ * The current level is based on the display(s) the device is connected to.
+ * If multiple HDCP-capable displays are simultaneously connected to
+ * separate interfaces, this method returns the lowest negotiated HDCP level
+ * of all interfaces.
+ *
+ * The maximum HDCP level is the highest level that can potentially be
+ * negotiated. It is a constant for any device, i.e. it does not depend on
+ * downstream receiving devices that could be connected. For example, if
+ * the device has HDCP 1.x keys and is capable of negotiating HDCP 1.x, but
+ * does not have HDCP 2.x keys, then the maximum HDCP capability would be
+ * reported as 1.x. If multiple HDCP-capable interfaces are present, it
+ * indicates the highest of the maximum HDCP levels of all interfaces.
+ *
+ * This method should only be used for informational purposes, not for
+ * enforcing compliance with HDCP requirements. Trusted enforcement of HDCP
+ * policies must be handled by the DRM system.
+ *
+ * @return HdcpLevels parcelable
+ * Implicit error codes:
+ * + ERROR_DRM_INVALID_STATE if the HAL is in a state where
+ * the HDCP level cannot be queried
+ */
+ HdcpLevels getHdcpLevels();
+
+ /**
+ * A key request/response exchange occurs between the app and a License
+ * Server to obtain the keys required to decrypt the content.
+ * getKeyRequest() is used to obtain an opaque key request blob that is
+ * delivered to the license server.
+ *
+ * @param scope either a sessionId or a keySetId, depending on the
+ * specified keyType. When the keyType is OFFLINE or STREAMING, scope
+ * must be set to the sessionId the keys will be provided to. When the
+ * keyType is RELEASE, scope must be set to the keySetId of the keys
+ * being released.
+ * @param initData container-specific data, its meaning is interpreted
+ * based on the mime type provided in the mimeType parameter. It could
+ * contain, for example, the content ID, key ID or other data obtained
+ * from the content metadata that is required to generate the key
+ * request. initData must be empty when keyType is RELEASE.
+ * @param mimeType identifies the mime type of the content
+ * @param keyType specifies if the keys are to be used for streaming,
+ * offline or a release
+ * @param optionalParameters included in the key request message to
+ * allow a client application to provide additional message parameters
+ * to the server.
+ *
+ * @return KeyRequest parcelable
+ * Implicit error codes:
+ * + BAD_VALUE if any parameters are invalid
+ * + ERROR_DRM_CANNOT_HANDLE if getKeyRequest is not supported at
+ * the time of the call
+ * + ERROR_DRM_INVALID_STATE if the HAL is in a state where
+ * a key request cannot be generated
+ * + ERROR_DRM_NOT_PROVISIONED if the device requires provisioning
+ * before it is able to generate a key request
+ * + ERROR_DRM_RESOURCE_CONTENTION if client applications using the
+ * hal are temporarily exceeding the available crypto resources
+ * such that a retry of the operation is likely to succeed
+ * + ERROR_DRM_SESSION_NOT_OPENED if the session is not opened
+ */
+ KeyRequest getKeyRequest(in byte[] scope, in byte[] initData, in String mimeType,
+ in KeyType keyType, in KeyValue[] optionalParameters);
+
+ /**
+ * Get Plugin error messages.
+ *
+ * @return LogMessages
+ * Implicit error codes:
+ * + GENERAL_OEM_ERROR on OEM-provided, low-level component failures;
+ * + GENERAL_PLUGIN_ERROR on unexpected plugin-level errors.
+ */
+ List<LogMessage> getLogMessages();
+
+ /**
+ * Returns the plugin-specific metrics. Multiple metric groups may be
+ * returned in one call to getMetrics(). The scope and definition of the
+ * metrics is defined by the plugin.
+ *
+ * @return collection of metric groups provided by the plugin
+ * Implicit error codes:
+ * + ERROR_DRM_INVALID_STATE if the metrics are not available to be
+ * returned.
+ */
+ List<DrmMetricGroup> getMetrics();
+
+ /**
+ * Return the current number of open sessions and the maximum number of
+ * sessions that may be opened simultaneously among all DRM instances
+ * for the active DRM scheme.
+ *
+ * @return NumberOfSessions parcelable
+ * Implicit error codes:
+ * + ERROR_DRM_INVALID_STATE if the HAL is in a state where the
+ * number of sessions cannot be queried
+ */
+ NumberOfSessions getNumberOfSessions();
+
+ /**
+ * The keys in an offline license allow protected content to be
+ * played even if the device is not connected to a network.
+ * Offline licenses are stored on the device after a key
+ * request/response exchange when the key request KeyType is
+ * OFFLINE. Normally each app is responsible for keeping track of
+ * the KeySetIds it has created. In some situations however, it
+ * will be necessary to request the list of stored offline license
+ * KeySetIds. If an app loses the KeySetId for any stored licenses
+ * that it created, for example, it must be able to recover the
+ * stored KeySetIds so those licenses will be removed when they
+ * expire or when the app is uninstalled.
+ *
+ * This method returns a list of the KeySetIds for all offline
+ * licenses. The offline license KeySetId allows an app to query
+ * the status of an offline license or remove it.
+ *
+ * @return list of keySetIds
+ * Implicit error codes:
+ * + ERROR_DRM_INVALID_STATE if the HAL is in a state where the
+ * KeySetIds can't be returned
+ */
+ List<KeySetId> getOfflineLicenseKeySetIds();
+
+ /**
+ * Request the state of an offline license. An offline license must
+ * be usable or inactive. The keys in a usable offline license are
+ * available for decryption. When the offline license state is
+ * inactive, the keys have been marked for release using
+ * getKeyRequest with KeyType RELEASE but the key response has not
+ * been received. The keys in an inactive offline license are not
+ * usable for decryption.
+ *
+ * @param keySetId the id of the offline license
+ *
+ * @return The offline license state, UNKNOWN, USABLE or INACTIVE.
+ * Implicit error codes:
+ * + BAD_VALUE if the license is not found
+ * + ERROR_DRM_INVALID_STATE if the HAL is in a state where the
+ * offline license state can't be queried
+ */
+ OfflineLicenseState getOfflineLicenseState(in KeySetId keySetId);
+
+ /**
+ * Read a byte array property value given the property name.
+ * See getPropertyString.
+ *
+ * @param propertyName the name of the property
+ *
+ * @return property value bye array
+ * Implicit error codes:
+ * + BAD_VALUE if the property name is invalid
+ * + ERROR_DRM_CANNOT_HANDLE if the property is not supported
+ * + ERROR_DRM_INVALID_STATE if the HAL is in a state where the
+ * property cannot be obtained
+ */
+ byte[] getPropertyByteArray(in String propertyName);
+
+ /**
+ * A drm scheme can have properties that are settable and readable
+ * by an app. There are a few forms of property access methods,
+ * depending on the data type of the property.
+ *
+ * Property values defined by the public API are:
+ * "vendor" [string] identifies the maker of the drm scheme
+ * "version" [string] identifies the version of the drm scheme
+ * "description" [string] describes the drm scheme
+ * 'deviceUniqueId' [byte array] The device unique identifier is
+ * established during device provisioning and provides a means of
+ * uniquely identifying each device.
+ *
+ * Since drm scheme properties may vary, additional field names may be
+ * defined by each DRM vendor. Refer to your DRM provider documentation
+ * for definitions of its additional field names.
+ *
+ * Read a string property value given the property name.
+ *
+ * @param propertyName the name of the property
+ *
+ * @return the property value string.
+ * Implicit error codes:
+ * + BAD_VALUE if the property name is invalid
+ * + ERROR_DRM_CANNOT_HANDLE if the property is not supported
+ * + ERROR_DRM_INVALID_STATE if the HAL is in a state where the
+ * property cannot be obtained
+ */
+ String getPropertyString(in String propertyName);
+
+ /**
+ * A provision request/response exchange occurs between the app
+ * and a provisioning server to retrieve a device certificate.
+ * getProvisionRequest is used to obtain an opaque provisioning
+ * request blob that is delivered to the provisioning server.
+ *
+ * @param certificateType the type of certificate requested, e.g. "X.509"
+ * @param certificateAuthority identifies the certificate authority.
+ * A certificate authority (CA) is an entity which issues digital
+ * certificates for use by other parties. It is an example of a
+ * trusted third party.
+ *
+ * @return ProvisionRequest parcelable
+ * Implicit error codes:
+ * + ERROR_DRM_CANNOT_HANDLE if the drm scheme does not require
+ * provisioning
+ * + ERROR_DRM_INVALID_STATE if the HAL is in a state where
+ * the provision request cannot be generated
+ * + ERROR_DRM_RESOURCE_CONTENTION if client applications using
+ * the hal are temporarily exceeding the available crypto
+ * resources such that a retry of the operation is likely
+ * to succeed
+ */
+ ProvisionRequest getProvisionRequest(
+ in String certificateType, in String certificateAuthority);
+
+ /**
+ * Get all secure stops by secure stop ID
+ *
+ * @param secureStopId the ID of the secure stop to return.
+ * The secure stop ID is delivered by the key server
+ * as part of the key response and must also be known by the app.
+ *
+ * @return secure stop opaque object.
+ * Implicit error codes:
+ * + BAD_VALUE if the secureStopId is invalid
+ * + ERROR_DRM_INVALID_STATE if the HAL is in a state where
+ * the secure stop cannot be returned
+ */
+ SecureStop getSecureStop(in SecureStopId secureStopId);
+
+ /**
+ * Get the IDs of all secure stops on the device
+ *
+ * @return list of secure stops IDs.
+ * Implicit error codes:
+ * + ERROR_DRM_INVALID_STATE if the HAL is in a state where
+ * the secure stop IDs list cannot be returned
+ */
+ List<SecureStopId> getSecureStopIds();
+
+ /**
+ * SecureStop is a way of enforcing the concurrent stream limit per
+ * subscriber.
+ *
+ * It can securely monitor the lifetime of sessions across device reboots
+ * by periodically persisting the session lifetime status in secure
+ * storage.
+ *
+ * A signed version of the sessionID is written to persistent storage on the
+ * device when each MediaCrypto object is created and periodically during
+ * playback. The sessionID is signed by the device private key to prevent
+ * tampering.
+ *
+ * When playback is completed the session is destroyed, and the secure
+ * stops are queried by the app. The app then delivers the secure stop
+ * message to a server which verifies the signature to confirm that the
+ * session and its keys have been removed from the device. The persisted
+ * record on the device is removed after receiving and verifying the
+ * signed response from the server.
+ *
+ * Get all secure stops on the device
+ *
+ * @return list of the opaque secure stop objects.
+ * Implicit error codes:
+ * + ERROR_DRM_INVALID_STATE if the HAL is in a state where
+ * the secure stops cannot be returned
+ */
+ List<SecureStop> getSecureStops();
+
+ /**
+ * Return the current security level of a session. A session has an initial
+ * security level determined by the robustness of the DRM system's
+ * implementation on the device.
+ *
+ * @param sessionId the session id the call applies to
+ *
+ * @return the current security level for the session.
+ * Implicit error codes:
+ * + BAD_VALUE if the sessionId is invalid
+ * + ERROR_DRM_INVALID_STATE if the HAL is in a state where
+ * the security level cannot be queried
+ * + ERROR_DRM_SESSION_NOT_OPENED if the session is not opened
+ */
+ SecurityLevel getSecurityLevel(in byte[] sessionId);
+
+ /**
+ * Open a new session at a requested security level. The security level
+ * represents the robustness of the device's DRM implementation. By default,
+ * sessions are opened at the native security level of the device which is
+ * the maximum level that can be supported. Overriding the security level is
+ * necessary when the decrypted frames need to be manipulated, such as for
+ * image compositing. The security level parameter must be equal to or lower
+ * than the native level. If the requested level is not supported, the next
+ * lower supported security level must be set. The level can be queried
+ * using {@link #getSecurityLevel}. A session ID is returned.
+ *
+ * @param level the requested security level
+ *
+ * @return sessionId
+ */
+ byte[] openSession(in SecurityLevel securityLevel);
+
+ /**
+ * After a key response is received by the app, it is provided to the
+ * Drm plugin using provideKeyResponse.
+ *
+ * @param scope may be a sessionId or a keySetId depending on the
+ * type of the response. Scope should be set to the sessionId
+ * when the response is for either streaming or offline key requests.
+ * Scope should be set to the keySetId when the response is for
+ * a release request.
+ * @param response the response from the key server that is being
+ * provided to the drm HAL.
+ *
+ * @return a keySetId that can be used to later restore the keys to a new
+ * session with the method restoreKeys when the response is for an
+ * offline key request.
+ * Implicit error codes:
+ * + BAD_VALUE if any parameters are invalid
+ * + ERROR_DRM_CANNOT_HANDLE if provideKeyResponse is not supported
+ * at the time of the call
+ * + ERROR_DRM_DEVICE_REVOKED if the device has been disabled by
+ * the license policy
+ * + ERROR_DRM_INVALID_STATE if the HAL is in a state where
+ * a key response cannot be handled.
+ * + ERROR_DRM_NOT_PROVISIONED if the device requires provisioning
+ * before it can handle the key response
+ * + ERROR_DRM_SESSION_NOT_OPENED if the session is not opened
+ */
+ KeySetId provideKeyResponse(in byte[] scope, in byte[] response);
+
+ /**
+ * After a provision response is received by the app from a provisioning
+ * server, it is provided to the Drm HAL using provideProvisionResponse.
+ * The HAL implementation must receive the provision request and
+ * store the provisioned credentials.
+ *
+ * @param response the opaque provisioning response received by the
+ * app from a provisioning server.
+ *
+ * @return ProvideProvisionResponseResult parcelable, which contains
+ * the public certificate and encrypted private key that can be
+ * used by signRSA to compute an RSA signature on a message.
+ * Implicit error codes:
+ * + BAD_VALUE if any parameters are invalid
+ * + ERROR_DRM_DEVICE_REVOKED if the device has been disabled by
+ * the license policy
+ * + ERROR_DRM_INVALID_STATE if the HAL is in a state where the
+ * provision response cannot be handled
+ */
+ ProvideProvisionResponseResult provideProvisionResponse(in byte[] response);
+
+ /**
+ * Request an informative description of the license for the session.
+ * The status is in the form of {name, value} pairs. Since DRM license
+ * policies vary by vendor, the specific status field names are
+ * determined by each DRM vendor. Refer to your DRM provider
+ * documentation for definitions of the field names for a particular
+ * drm scheme.
+ *
+ * @param sessionId the session id the call applies to
+ *
+ * @return a list of name value pairs describing the license.
+ * Implicit error codes:
+ * + ERROR_DRM_SESSION_NOT_OPENED if the session is not opened
+ * + BAD_VALUE if any parameters are invalid
+ * + ERROR_DRM_INVALID_STATE if the HAL is in a state where the
+ * key status cannot be queried.
+ */
+ List<KeyValue> queryKeyStatus(in byte[] sessionId);
+
+ /**
+ * Release all secure stops on the device
+ *
+ * @return (implicit) the status of the call:
+ * ERROR_DRM_INVALID_STATE if the HAL is in a state where
+ * the secure stops cannot be released.
+ */
+ void releaseAllSecureStops();
+
+ /**
+ * Release a secure stop by secure stop ID
+ *
+ * @param secureStopId the ID of the secure stop to release.
+ * The secure stop ID is delivered by the key server as
+ * part of the key response and must also be known by the app.
+ *
+ * @return (implicit) the status of the call:
+ * BAD_VALUE if the secureStopId is invalid
+ * ERROR_DRM_INVALID_STATE if the HAL is in a state where
+ * the secure stop cannot be released.
+ */
+ void releaseSecureStop(in SecureStopId secureStopId);
+
+ /**
+ * Release secure stops given a release message from the key server
+ *
+ * @param ssRelease the secure stop release message identifying
+ * one or more secure stops to release. ssRelease is opaque,
+ * it is passed directly from a DRM license server through
+ * the app and media framework to the vendor HAL module.
+ * The format and content of ssRelease must be defined by the
+ * DRM scheme being implemented according to this HAL.
+ * The DRM scheme can be identified by its UUID which
+ * can be queried using IDrmFactory::isCryptoSchemeSupported.
+ *
+ * @return (implicit) the status of the call:
+ * BAD_VALUE if ssRelease is invalid
+ * ERROR_DRM_INVALID_STATE if the HAL is in a state wherei
+ * the secure stop cannot be released.
+ */
+ void releaseSecureStops(in OpaqueData ssRelease);
+
+ /**
+ * Remove all secure stops on the device without requiring a secure
+ * stop release response message from the key server.
+ *
+ * @return (implicit) the status of the call:
+ * ERROR_DRM_INVALID_STATE if the HAL is in a state where
+ * the secure stops cannot be removed.
+ */
+ void removeAllSecureStops();
+
+ /**
+ * Remove the current keys from a session
+ *
+ * @param sessionId the session id the call applies to
+ *
+ * @return (implicit) the status of the call:
+ * BAD_VALUE if the sessionId is invalid
+ * ERROR_DRM_INVALID_STATE if the HAL is in a state where
+ * the keys cannot be removed.
+ * ERROR_DRM_SESSION_NOT_OPENED if the session is not opened
+ */
+ void removeKeys(in byte[] sessionId);
+
+ /**
+ * Normally offline licenses are released using a key
+ * request/response exchange using getKeyRequest where the KeyType
+ * is RELEASE, followed by provideKeyResponse. This allows the
+ * server to cryptographically confirm that the license has been
+ * removed and then adjust the count of offline licenses allocated
+ * to the device.
+ * <p>
+ * In some exceptional situations it will be necessary to directly
+ * remove offline licenses without notifying the server, which is
+ * performed by this method.
+ *
+ * @param keySetId the id of the offline license to remove
+ *
+ * @return (implicit) the status of the call:
+ * BAD_VALUE if the license is not found
+ * ERROR_DRM_INVALID_STATE if the HAL is in a state where
+ * the KeySetIds can't be removed.
+ */
+ void removeOfflineLicense(in KeySetId keySetId);
+
+ /**
+ * Remove a secure stop given its secure stop ID, without requiring
+ * a secure stop release response message from the key server.
+ *
+ * @param secureStopId the ID of the secure stop to release.
+ *
+ * @return the status of the call:
+ * BAD_VALUE if the secureStopId is invalid
+ * ERROR_DRM_INVALID_STATE if the HAL is in a state where
+ * the secure stop cannot be removed.
+ */
+ void removeSecureStop(in SecureStopId secureStopId);
+
+ /**
+ * Check if the specified mime-type & security level require a secure decoder
+ * component.
+ *
+ * @param mime The content mime-type
+ * @param level the requested security level
+ *
+ * @return must be true if and only if a secure decoder is
+ * required for the specified mime-type & security level
+ */
+ boolean requiresSecureDecoder(in String mime, in SecurityLevel level);
+
+ /**
+ * Check if the specified mime-type requires a secure decoder component
+ * at the highest security level supported on the device.
+ *
+ * @param mime The content mime-type
+ *
+ * @return must be true if and only if a secure decoder is required
+ * for the specified mime-type
+ */
+ boolean requiresSecureDecoderDefault(in String mime);
+
+ /**
+ * Restore persisted offline keys into a new session
+ *
+ * @param sessionId the session id the call applies to
+ * @param keySetId identifies the keys to load, obtained from
+ * a prior call to provideKeyResponse().
+ *
+ * @return (implicit) the status of the call:
+ * ERROR_DRM_SESSION_NOT_OPENED if the session is not opened
+ * BAD_VALUE if any parameters are invalid
+ * ERROR_DRM_INVALID_STATE if the HAL is in a state where
+ * keys cannot be restored.
+ */
+ void restoreKeys(in byte[] sessionId, in KeySetId keySetId);
+
+ /**
+ * The following methods implement operations on a CryptoSession to support
+ * encrypt, decrypt, sign verify operations on operator-provided
+ * session keys.
+ *
+ *
+ * Set the cipher algorithm to be used for the specified session.
+ *
+ * @param sessionId the session id the call applies to
+ * @param algorithm the algorithm to use. The string conforms to JCA
+ * Standard Names for Cipher Transforms and is case insensitive. An
+ * example algorithm is "AES/CBC/PKCS5Padding".
+ *
+ * @return (implicit) the status of the call:
+ * BAD_VALUE if any parameters are invalid
+ * ERROR_DRM_INVALID_STATE if the HAL is in a state where
+ * the algorithm cannot be set.
+ * ERROR_DRM_SESSION_NOT_OPENED if the session is not opened`
+ */
+ void setCipherAlgorithm(in byte[] sessionId, in String algorithm);
+
+ /**
+ * Plugins call the following methods to deliver events to the
+ * java app.
+ *
+ *
+ * Set a listener for a drm session. This allows the drm HAL to
+ * make asynchronous calls back to the client of IDrm.
+ *
+ * @param listener instance of IDrmPluginListener to receive the events
+ */
+ void setListener(in IDrmPluginListener listener);
+
+ /**
+ * Set the MAC algorithm to be used for computing hashes in a session.
+ *
+ * @param sessionId the session id the call applies to
+ * @param algorithm the algorithm to use. The string conforms to JCA
+ * Standard Names for Mac Algorithms and is case insensitive. An example MAC
+ * algorithm string is "HmacSHA256".
+ *
+ * @return (implicit) the status of the call:
+ * BAD_VALUE if any parameters are invalid
+ * ERROR_DRM_INVALID_STATE if the HAL is in a state where
+ * the algorithm cannot be set.
+ * ERROR_DRM_SESSION_NOT_OPENED if the session is not opened`
+ */
+ void setMacAlgorithm(in byte[] sessionId, in String algorithm);
+
+ /**
+ * Set playback id of a drm session. The playback id can be used to join drm session metrics
+ * with metrics from other low level media components, e.g. codecs, or metrics from the high
+ * level player.
+ *
+ * @param sessionId drm session id
+ * @param playbackId high level playback id
+ *
+ * @return (implicit) the status of the call:
+ * ERROR_DRM_SESSION_NOT_OPENED if the drm session cannot be found
+ */
+ void setPlaybackId(in byte[] sessionId, in String playbackId);
+
+ /**
+ * Write a property byte array value given the property name
+ *
+ * @param propertyName the name of the property
+ * @param value the value to write
+ *
+ * @return (implicit) the status of the call:
+ * BAD_VALUE if the property name is invalid
+ * ERROR_DRM_CANNOT_HANDLE if the property is not supported
+ * ERROR_DRM_INVALID_STATE if the HAL is in a state where the
+ * property cannot be set
+ */
+ void setPropertyByteArray(in String propertyName, in byte[] value);
+
+ /**
+ * Write a property string value given the property name
+ *
+ * @param propertyName the name of the property
+ * @param value the value to write
+ *
+ * @return (implicit) status of the call:
+ * BAD_VALUE if the property name is invalid
+ * ERROR_DRM_CANNOT_HANDLE if the property is not supported
+ * ERROR_DRM_INVALID_STATE if the HAL is in a state where the
+ * property cannot be set
+ */
+ void setPropertyString(in String propertyName, in String value);
+
+ /**
+ * Compute a signature over the provided message using the mac algorithm
+ * specified by setMacAlgorithm and the key selected by keyId and return
+ * the signature.
+ *
+ * @param sessionId the session id the call applies to
+ * @param keyId the ID of the key to use for decryption
+ * @param message the message to compute a signature over
+ *
+ * @return signature computed over the message
+ * Implicit error codes:
+ * + ERROR_DRM_SESSION_NOT_OPENED if the session is not opened
+ * + BAD_VALUE if any parameters are invalid
+ * + ERROR_DRM_INVALID_STATE if the HAL is in a state where the
+ * sign operation cannot be performed.
+ */
+ byte[] sign(in byte[] sessionId, in byte[] keyId, in byte[] message);
+
+ /**
+ * Compute an RSA signature on the provided message using the specified
+ * algorithm.
+ *
+ * @param sessionId the session id the call applies to
+ * @param algorithm the signing algorithm, such as "RSASSA-PSS-SHA1"
+ * or "PKCS1-BlockType1"
+ * @param message the message to compute the signature on
+ * @param wrappedKey the private key returned during provisioning as
+ * returned by provideProvisionResponse.
+ *
+ * @return signature computed over the message
+ * Implicit error codes:
+ * + BAD_VALUE if any parameters are invalid
+ * + ERROR_DRM_INVALID_STATE if the HAL is in a state where the
+ * signRSA operation operation cannot be performed
+ * + ERROR_DRM_SESSION_NOT_OPENED if the session is not opened
+ */
+ byte[] signRSA(
+ in byte[] sessionId, in String algorithm, in byte[] message,
+ in byte[] wrappedkey);
+
+ /**
+ * Compute a hash of the provided message using the mac algorithm specified
+ * by setMacAlgorithm and the key selected by keyId, and compare with the
+ * expected result.
+ *
+ * @param sessionId the session id the call applies to
+ * @param keyId the ID of the key to use for decryption
+ * @param message the message to compute a hash of
+ * @param signature the signature to verify
+ *
+ * @return true if the signature is verified positively, false otherwise.
+ * Implicit error codes:
+ * + ERROR_DRM_SESSION_NOT_OPENED if the session is not opened
+ * + BAD_VALUE if any parameters are invalid
+ * + ERROR_DRM_INVALID_STATE if the HAL is in a state where the
+ * verify operation cannot be performed.
+ */
+ boolean verify(
+ in byte[] sessionId, in byte[] keyId, in byte[] message,
+ in byte[] signature);
+}
diff --git a/drm/aidl/android/hardware/drm/IDrmPluginListener.aidl b/drm/aidl/android/hardware/drm/IDrmPluginListener.aidl
new file mode 100644
index 0000000..d52da66
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/IDrmPluginListener.aidl
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+import android.hardware.drm.EventType;
+import android.hardware.drm.KeyStatus;
+
+/**
+ * IDrmPluginListener is a listener interface for Drm events sent from an
+ * IDrmPlugin instance.
+ */
+@VintfStability
+interface IDrmPluginListener {
+ /**
+ * Legacy event sending method, it sends events of various types using a
+ * single overloaded set of parameters. This form is deprecated.
+ *
+ * @param eventType the type of the event
+ * @param sessionId identifies the session the event originated from
+ * @param data event-specific data blob
+ */
+ oneway void onEvent(in EventType eventType, in byte[] sessionId, in byte[] data);
+
+ /**
+ * Send a license expiration update to the listener. The expiration
+ * update indicates how long the current keys are valid before they
+ * need to be renewed.
+ *
+ * @param sessionId identifies the session the event originated from
+ * @param expiryTimeInMS the time when the keys need to be renewed.
+ * The time is in milliseconds, relative to the Unix epoch. A time
+ * of 0 indicates that the keys never expire.
+ */
+ oneway void onExpirationUpdate(in byte[] sessionId, in long expiryTimeInMS);
+
+ /**
+ * Send a keys change event to the listener. The keys change event
+ * indicates the status of each key in the session. Keys can be
+ * indicated as being usable, expired, outputnotallowed or statuspending.
+ *
+ * @param sessionId identifies the session the event originated from
+ * @param keyStatusList indicates the status for each key ID in the
+ * session.
+ * @param hasNewUsableKey indicates if the event includes at least one
+ * key that has become usable.
+ */
+ oneway void onKeysChange(
+ in byte[] sessionId, in KeyStatus[] keyStatusList, in boolean hasNewUsableKey);
+
+ /**
+ * Some device crypto hardware is incapable of retaining crypto
+ * session state across suspend and resume cycles. A
+ * SessionLostState event must be signaled when a session has
+ * become invalid for this reason. This event must not be used to
+ * indicate a failure in the crypto system. Closing the session
+ * and opening a new one must allow the application to resume
+ * normal use of the drm hal module.
+ *
+ * @param sessionId identifies the session that has been invalidated
+ */
+ oneway void onSessionLostState(in byte[] sessionId);
+}
diff --git a/drm/aidl/android/hardware/drm/KeyRequest.aidl b/drm/aidl/android/hardware/drm/KeyRequest.aidl
new file mode 100644
index 0000000..0c73205
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/KeyRequest.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+import android.hardware.drm.KeyRequestType;
+
+@VintfStability
+parcelable KeyRequest {
+ /** The opaque key request blob. */
+ byte[] request;
+
+ /**
+ * Enumerated type:
+ * INITIAL - the first key request for a license
+ * NONE - indicates that no request is needed because the keys
+ * are already loaded
+ * RENEWAL - is a subsequent key request used to refresh the
+ * keys in a license
+ * RELEASE - indicates keys are being released
+ * UPDATE - indicates that the keys need to be refetched after
+ * the initial license request
+ */
+ KeyRequestType requestType;
+
+ /**
+ * The URL that the request may be sent to,
+ * if provided by the drm HAL. The app can choose to
+ * override this URL. If the HAL implementation does not provide
+ * a defaultUrl, the returned string must be empty.
+ */
+ String defaultUrl;
+}
diff --git a/drm/aidl/android/hardware/drm/KeyRequestType.aidl b/drm/aidl/android/hardware/drm/KeyRequestType.aidl
new file mode 100644
index 0000000..3a603ff
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/KeyRequestType.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+/**
+ * An app determines the type of a key request returned from getKeyRequest.
+ */
+@VintfStability
+@Backing(type="int")
+enum KeyRequestType {
+ /**
+ * Key request type is for an initial license request
+ */
+ INITIAL,
+ /**
+ * Key request type is for license renewal. Renewal requests are used
+ * to extend the validity period for streaming keys.
+ */
+ RENEWAL,
+ /**
+ * Key request type is a release. A key release causes offline keys
+ * to become available for streaming.
+ */
+ RELEASE,
+ /**
+ * Key request type is unknown due to some error condition.
+ */
+ UNKNOWN,
+ /**
+ * Keys are already loaded. No key request is needed.
+ */
+ NONE,
+ /**
+ * Keys have previously been loaded. An additional (non-renewal) license
+ * request is needed.
+ */
+ UPDATE,
+}
diff --git a/drm/aidl/android/hardware/drm/KeySetId.aidl b/drm/aidl/android/hardware/drm/KeySetId.aidl
new file mode 100644
index 0000000..be0ce0e
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/KeySetId.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+@VintfStability
+parcelable KeySetId {
+ byte[] keySetId;
+}
diff --git a/drm/aidl/android/hardware/drm/KeyStatus.aidl b/drm/aidl/android/hardware/drm/KeyStatus.aidl
new file mode 100644
index 0000000..16e042a
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/KeyStatus.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+import android.hardware.drm.KeyStatusType;
+
+/**
+ * Used by sendKeysChange to report the usability status of each key
+ * to the app.
+ */
+@VintfStability
+parcelable KeyStatus {
+ byte[] keyId;
+ KeyStatusType type;
+}
diff --git a/drm/aidl/android/hardware/drm/KeyStatusType.aidl b/drm/aidl/android/hardware/drm/KeyStatusType.aidl
new file mode 100644
index 0000000..6902d87
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/KeyStatusType.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+@VintfStability
+@Backing(type="int")
+enum KeyStatusType {
+ /**
+ * The key is currently usable to decrypt media data.
+ */
+ USABLE,
+ /**
+ * The key is no longer usable to decrypt media data because its expiration
+ * time has passed.
+ */
+ EXPIRED,
+ /**
+ * The key is not currently usable to decrypt media data because its output
+ * requirements cannot currently be met.
+ */
+ OUTPUTNOTALLOWED,
+ /**
+ * The status of the key is not yet known and is being determined.
+ */
+ STATUSPENDING,
+ /**
+ * The key is not currently usable to decrypt media data because of an
+ * internal error in processing unrelated to input parameters.
+ */
+ INTERNALERROR,
+ /**
+ * The key is not yet usable to decrypt media because the start
+ * time is in the future. The key must become usable when
+ * its start time is reached.
+ */
+ USABLEINFUTURE,
+}
diff --git a/drm/aidl/android/hardware/drm/KeyType.aidl b/drm/aidl/android/hardware/drm/KeyType.aidl
new file mode 100644
index 0000000..78b4d83
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/KeyType.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+@VintfStability
+@Backing(type="int")
+enum KeyType {
+ /**
+ * Drm keys can be for offline content or for online streaming.
+ * Offline keys are persisted on the device and may be used when the device
+ * is disconnected from the network.
+ */
+ OFFLINE,
+ /**
+ * Keys for streaming are not persisted and require the device to be
+ * connected to the network for periodic renewal.
+ */
+ STREAMING,
+ /**
+ * The Release type is used to request that offline keys be no longer
+ * restricted to offline use.
+ */
+ RELEASE,
+}
diff --git a/drm/aidl/android/hardware/drm/KeyValue.aidl b/drm/aidl/android/hardware/drm/KeyValue.aidl
new file mode 100644
index 0000000..e26781b
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/KeyValue.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+@VintfStability
+parcelable KeyValue {
+ String key;
+ String value;
+}
diff --git a/drm/aidl/android/hardware/drm/LogMessage.aidl b/drm/aidl/android/hardware/drm/LogMessage.aidl
new file mode 100644
index 0000000..8ac1ced
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/LogMessage.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+import android.hardware.drm.LogPriority;
+
+/**
+ * Returned by getLogMessages to report error diagnostics to the
+ * app.
+ *
+ * The |message| field is for informational purposes only, and
+ * NOT meant to be parsed programmatically when handling errors.
+ * For programmatic error handling, please check the return |Status|
+ * of APIs instead.
+ */
+@VintfStability
+parcelable LogMessage {
+ /**
+ * Epoch time in milliseconds.
+ */
+ long timeMs;
+ LogPriority priority;
+ String message;
+}
diff --git a/drm/aidl/android/hardware/drm/LogPriority.aidl b/drm/aidl/android/hardware/drm/LogPriority.aidl
new file mode 100644
index 0000000..4db3b40
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/LogPriority.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+@VintfStability
+@Backing(type="int")
+enum LogPriority {
+ UNKNOWN,
+ DEFAULT,
+ VERBOSE,
+ DEBUG,
+ INFO,
+ WARN,
+ ERROR,
+ FATAL,
+}
diff --git a/drm/aidl/android/hardware/drm/Mode.aidl b/drm/aidl/android/hardware/drm/Mode.aidl
new file mode 100644
index 0000000..6fc0065
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/Mode.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+/**
+ * Enumerate the supported crypto modes
+ */
+@VintfStability
+@Backing(type="int")
+enum Mode {
+ UNENCRYPTED = 0,
+ AES_CTR = 1,
+ AES_CBC_CTS = 2,
+ AES_CBC = 3,
+}
diff --git a/drm/aidl/android/hardware/drm/NumberOfSessions.aidl b/drm/aidl/android/hardware/drm/NumberOfSessions.aidl
new file mode 100644
index 0000000..75b7c2e
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/NumberOfSessions.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+@VintfStability
+parcelable NumberOfSessions {
+ /** The number of currently opened sessions. */
+ int currentSessions;
+
+ /** The maximum number of sessions that the device can support. */
+ int maxSessions;
+}
diff --git a/drm/aidl/android/hardware/drm/OfflineLicenseState.aidl b/drm/aidl/android/hardware/drm/OfflineLicenseState.aidl
new file mode 100644
index 0000000..0f447db
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/OfflineLicenseState.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+@VintfStability
+@Backing(type="int")
+enum OfflineLicenseState {
+ /**
+ * Offline license state is unknown
+ */
+ UNKNOWN,
+ /**
+ * Offline license state is usable, the keys are usable for decryption.
+ */
+ USABLE,
+ /**
+ * Offline license state is inactive, the keys have been marked for
+ * release using {@link #getKeyRequest} with KEY_TYPE_RELEASE but the
+ * key response has not been received.
+ */
+ INACTIVE,
+}
diff --git a/drm/aidl/android/hardware/drm/OpaqueData.aidl b/drm/aidl/android/hardware/drm/OpaqueData.aidl
new file mode 100644
index 0000000..6b2a2e7
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/OpaqueData.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+@VintfStability
+parcelable OpaqueData {
+ byte[] opaqueData;
+}
diff --git a/drm/aidl/android/hardware/drm/Pattern.aidl b/drm/aidl/android/hardware/drm/Pattern.aidl
new file mode 100644
index 0000000..88d22cf
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/Pattern.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+/**
+ * A crypto Pattern is a repeating sequence of encrypted and clear blocks
+ * occurring within the bytes indicated by mNumBytesOfEncryptedDatad bytes
+ * of a subsample. Patterns are used to reduce the CPU overhead of
+ * decrypting samples. As an example, HLS uses 1:9 patterns where every
+ * 10th block is encrypted.
+ */
+@VintfStability
+parcelable Pattern {
+ /**
+ * The number of blocks to be encrypted in the pattern. If zero,
+ * pattern encryption is inoperative.
+ */
+ int encryptBlocks;
+
+ /**
+ * The number of blocks to be skipped (left clear) in the pattern. If
+ * zero, pattern encryption is inoperative.
+ */
+ int skipBlocks;
+}
diff --git a/drm/aidl/android/hardware/drm/ProvideProvisionResponseResult.aidl b/drm/aidl/android/hardware/drm/ProvideProvisionResponseResult.aidl
new file mode 100644
index 0000000..e9f1e2b
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/ProvideProvisionResponseResult.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+@VintfStability
+parcelable ProvideProvisionResponseResult {
+ /**
+ * The public certificate resulting from the provisioning
+ * operation, if any. An empty vector indicates that no
+ * certificate was returned.
+ */
+ byte[] certificate;
+
+ /**
+ * An opaque object containing encrypted private key material
+ * to be used by signRSA when computing an RSA signature on a
+ * message, see the signRSA method.
+ */
+ byte[] wrappedKey;
+}
diff --git a/drm/aidl/android/hardware/drm/ProvisionRequest.aidl b/drm/aidl/android/hardware/drm/ProvisionRequest.aidl
new file mode 100644
index 0000000..eb42d32
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/ProvisionRequest.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+@VintfStability
+parcelable ProvisionRequest {
+ /** The opaque certificate request blob. */
+ byte[] request;
+
+ /**
+ * The URL that the provisioning request may be sent to,
+ * if known by the HAL implementation. An app can choose to
+ * override this URL. If the HAL implementation does not provide
+ * a defaultUrl, the returned string must be empty.
+ */
+ String defaultUrl;
+}
diff --git a/drm/aidl/android/hardware/drm/SecureStop.aidl b/drm/aidl/android/hardware/drm/SecureStop.aidl
new file mode 100644
index 0000000..37cfbd3
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/SecureStop.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+/**
+ * Encapsulates a secure stop opaque object.
+ */
+@VintfStability
+parcelable SecureStop {
+ byte[] opaqueData;
+}
diff --git a/drm/aidl/android/hardware/drm/SecureStopId.aidl b/drm/aidl/android/hardware/drm/SecureStopId.aidl
new file mode 100644
index 0000000..775e60b
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/SecureStopId.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+@VintfStability
+parcelable SecureStopId {
+ byte[] secureStopId;
+}
diff --git a/drm/aidl/android/hardware/drm/SecurityLevel.aidl b/drm/aidl/android/hardware/drm/SecurityLevel.aidl
new file mode 100644
index 0000000..aac1b68
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/SecurityLevel.aidl
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+@VintfStability
+@Backing(type="int")
+enum SecurityLevel {
+ /**
+ * Unable to determine the security level
+ */
+ UNKNOWN,
+ /**
+ * Software-based whitebox crypto
+ */
+ SW_SECURE_CRYPTO,
+ /**
+ * Software-based whitebox crypto and an obfuscated decoder
+ */
+ SW_SECURE_DECODE,
+ /**
+ * DRM key management and crypto operations are performed within a
+ * hardware backed trusted execution environment
+ */
+ HW_SECURE_CRYPTO,
+ /**
+ * DRM key management, crypto operations and decoding of content
+ * are performed within a hardware backed trusted execution environment
+ */
+ HW_SECURE_DECODE,
+ /**
+ * DRM key management, crypto operations, decoding of content and all
+ * handling of the media (compressed and uncompressed) is handled within
+ * a hardware backed trusted execution environment.
+ */
+ HW_SECURE_ALL,
+ /**
+ * The default security level is defined as the highest security level
+ * supported on the device.
+ */
+ DEFAULT,
+}
diff --git a/drm/aidl/android/hardware/drm/SharedBuffer.aidl b/drm/aidl/android/hardware/drm/SharedBuffer.aidl
new file mode 100644
index 0000000..6977284
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/SharedBuffer.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+/**
+ * SharedBuffer describes a decrypt buffer which is defined by a bufferId, an
+ * offset and a size. The offset is relative to the shared memory base for the
+ * memory region identified by bufferId, which is established by
+ * setSharedMemoryBase().
+ */
+@VintfStability
+parcelable SharedBuffer {
+ /**
+ * The unique buffer identifier
+ */
+ int bufferId;
+ /**
+ * The offset from the shared memory base
+ */
+ long offset;
+ /**
+ * The size of the shared buffer in bytes
+ */
+ long size;
+}
diff --git a/drm/aidl/android/hardware/drm/Status.aidl b/drm/aidl/android/hardware/drm/Status.aidl
new file mode 100644
index 0000000..ee57d64
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/Status.aidl
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+@VintfStability
+@Backing(type="int")
+enum Status {
+ /**
+ * The DRM plugin must return OK when an operation completes without any
+ * errors.
+ */
+ OK,
+ /**
+ * The DRM plugin must return ERROR_DRM_NO_LICENSE, when decryption is
+ * attempted and no license keys have been provided.
+ */
+ ERROR_DRM_NO_LICENSE,
+ /**
+ * ERROR_DRM_LICENSE_EXPIRED must be returned when an attempt is made
+ * to use a license and the keys in that license have expired.
+ */
+ ERROR_DRM_LICENSE_EXPIRED,
+ /**
+ * The DRM plugin must return ERROR_DRM_SESSION_NOT_OPENED when an
+ * attempt is made to use a session that has not been opened.
+ */
+ ERROR_DRM_SESSION_NOT_OPENED,
+ /**
+ * The DRM plugin must return ERROR_DRM_CANNOT_HANDLE when an unsupported
+ * data format or operation is attempted.
+ */
+ ERROR_DRM_CANNOT_HANDLE,
+ /**
+ * ERROR_DRM_INVALID_STATE must be returned when the device is in a state
+ * where it is not able to perform decryption.
+ */
+ ERROR_DRM_INVALID_STATE,
+ /**
+ * The DRM plugin must return BAD_VALUE whenever an illegal parameter is
+ * passed to one of the interface functions.
+ */
+ BAD_VALUE,
+ /**
+ * The DRM plugin must return ERROR_DRM_NOT_PROVISIONED from getKeyRequest,
+ * openSession or provideKeyResponse when the device has not yet been
+ * provisioned.
+ */
+ ERROR_DRM_NOT_PROVISIONED,
+ /**
+ * ERROR_DRM_RESOURCE_BUSY must be returned when resources, such as drm
+ * sessions or secure buffers are not available to perform a requested
+ * operation because they are already in use.
+ */
+ ERROR_DRM_RESOURCE_BUSY,
+ /**
+ * The DRM Plugin must return ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION
+ * when the output protection level enabled on the device is not
+ * sufficient to meet the requirements in the license policy. HDCP is an
+ * example of a form of output protection.
+ */
+ ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION,
+ /**
+ * The DRM Plugin must return ERROR_DRM_DEVICE_REVOKED from
+ * provideProvisionResponse and provideKeyResponse if the response indicates
+ * that the device has been revoked. Device revocation means that the device
+ * is no longer permitted to play content.
+ */
+ ERROR_DRM_DEVICE_REVOKED,
+ /**
+ * The DRM Plugin must return ERROR_DRM_DECRYPT if the CryptoPlugin
+ * decrypt operation fails.
+ */
+ ERROR_DRM_DECRYPT,
+ /**
+ * ERROR_DRM_UNKNOWN must be returned when a fatal failure occurs and no
+ * other defined error is appropriate.
+ */
+ ERROR_DRM_UNKNOWN,
+ /**
+ * The drm HAL module must return ERROR_DRM_INSUFFICIENT_SECURITY
+ * from the crypto plugin decrypt method when the security level
+ * of the device is not sufficient to meet the requirements in the
+ * license policy.
+ */
+ ERROR_DRM_INSUFFICIENT_SECURITY,
+ /**
+ * The drm HAL module must return ERROR_FRAME_TOO_LARGE from the
+ * decrypt method when the frame being decrypted into the secure
+ * output buffer exceeds the size of the buffer.
+ */
+ ERROR_DRM_FRAME_TOO_LARGE,
+ /**
+ * This error must be returned from any session method when an
+ * attempt is made to use the session after the crypto hardware
+ * state has been invalidated. Some devices are not able to
+ * retain crypto session state across device suspend/resume which
+ * results in invalid session state.
+ */
+ ERROR_DRM_SESSION_LOST_STATE,
+ /**
+ * The drm HAL module must return this error if client
+ * applications using the hal are temporarily exceeding the
+ * capacity of available crypto resources such that a retry of
+ * the operation is likely to succeed.
+ */
+ ERROR_DRM_RESOURCE_CONTENTION,
+ /**
+ * queueSecureInput buffer called with 0 subsamples.
+ */
+ CANNOT_DECRYPT_ZERO_SUBSAMPLES,
+ /**
+ * An error happened within the crypto library used by the drm plugin.
+ */
+ CRYPTO_LIBRARY_ERROR,
+ /**
+ * Non-specific error reported by the device OEM subsystem.
+ */
+ GENERAL_OEM_ERROR,
+ /**
+ * Unexpected internal failure in the drm/crypto plugin.
+ */
+ GENERAL_PLUGIN_ERROR,
+ /**
+ * The init data parameter passed to getKeyRequest is empty or invalid.
+ */
+ INIT_DATA_INVALID,
+ /**
+ * Either the key was not loaded from the license before attempting the
+ * operation, or the key ID parameter provided by the app is incorrect.
+ */
+ KEY_NOT_LOADED,
+ /**
+ * The license response was empty, fields are missing or otherwise unable
+ * to be parsed.
+ */
+ LICENSE_PARSE_ERROR,
+ /**
+ * The operation (e.g. to renew or persist a license) is prohibited by the
+ * license policy.
+ */
+ LICENSE_POLICY_ERROR,
+ /**
+ * Failed to generate a release request because a field in the stored
+ * license is empty or malformed.
+ */
+ LICENSE_RELEASE_ERROR,
+ /**
+ * The license server detected an error in the license request.
+ */
+ LICENSE_REQUEST_REJECTED,
+ /**
+ * Failed to restore an offline license because a field is empty or
+ * malformed.
+ */
+ LICENSE_RESTORE_ERROR,
+ /**
+ * License is in an invalid state for the attempted operation.
+ */
+ LICENSE_STATE_ERROR,
+ /**
+ * Certificate is malformed or is of the wrong type.
+ */
+ MALFORMED_CERTIFICATE,
+ /**
+ * Failure in the media framework.
+ */
+ MEDIA_FRAMEWORK_ERROR,
+ /**
+ * Certificate has not been set.
+ */
+ MISSING_CERTIFICATE,
+ /**
+ * There was an error loading the provisioned certificate.
+ */
+ PROVISIONING_CERTIFICATE_ERROR,
+ /**
+ * Required steps where not performed before provisioning was attempted.
+ */
+ PROVISIONING_CONFIGURATION_ERROR,
+ /**
+ * The provisioning response was empty, fields are missing or otherwise
+ * unable to be parsed.
+ */
+ PROVISIONING_PARSE_ERROR,
+ /**
+ * The provisioning server detected an error in the provisioning request.
+ */
+ PROVISIONING_REQUEST_REJECTED,
+ /**
+ * Provisioning failed in a way that is likely to succeed on a subsequent
+ * attempt.
+ */
+ RETRYABLE_PROVISIONING_ERROR,
+ /**
+ * Failed to generate a secure stop request because a field in the stored
+ * license is empty or malformed.
+ */
+ SECURE_STOP_RELEASE_ERROR,
+ /**
+ * The plugin was unable to read data from the filesystem.
+ */
+ STORAGE_READ_FAILURE,
+ /**
+ * The plugin was unable to write data to the filesystem.
+ */
+ STORAGE_WRITE_FAILURE,
+}
diff --git a/drm/aidl/android/hardware/drm/SubSample.aidl b/drm/aidl/android/hardware/drm/SubSample.aidl
new file mode 100644
index 0000000..68a8fb1
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/SubSample.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+/**
+ * A subsample consists of some number of bytes of clear (unencrypted)
+ * data followed by a number of bytes of encrypted data.
+ */
+@VintfStability
+parcelable SubSample {
+ int numBytesOfClearData;
+ int numBytesOfEncryptedData;
+}
diff --git a/drm/aidl/android/hardware/drm/Uuid.aidl b/drm/aidl/android/hardware/drm/Uuid.aidl
new file mode 100644
index 0000000..b36c409
--- /dev/null
+++ b/drm/aidl/android/hardware/drm/Uuid.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.drm;
+
+@VintfStability
+parcelable Uuid {
+ byte[] uuid;
+}
diff --git a/dumpstate/aidl/Android.bp b/dumpstate/aidl/Android.bp
index e18eade..22d836b 100644
--- a/dumpstate/aidl/Android.bp
+++ b/dumpstate/aidl/Android.bp
@@ -34,7 +34,6 @@
enabled: false,
},
ndk: {
- separate_platform_variant: false,
vndk: {
enabled: true,
},
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IAGnss.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IAGnss.aidl
index f02e08c..1a69f33 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IAGnss.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IAGnss.aidl
@@ -37,8 +37,8 @@
void setCallback(in android.hardware.gnss.IAGnssCallback callback);
void dataConnClosed();
void dataConnFailed();
- void setServer(in android.hardware.gnss.IAGnssCallback.AGnssType type, in String hostname, in int port);
- void dataConnOpen(in long networkHandle, in String apn, in android.hardware.gnss.IAGnss.ApnIpType apnIpType);
+ void setServer(in android.hardware.gnss.IAGnssCallback.AGnssType type, in @utf8InCpp String hostname, in int port);
+ void dataConnOpen(in long networkHandle, in @utf8InCpp String apn, in android.hardware.gnss.IAGnss.ApnIpType apnIpType);
@Backing(type="int") @VintfStability
enum ApnIpType {
INVALID = 0,
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl
index 3477380..1b4c581 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl
@@ -46,7 +46,41 @@
android.hardware.gnss.IAGnss getExtensionAGnss();
android.hardware.gnss.IGnssDebug getExtensionGnssDebug();
android.hardware.gnss.visibility_control.IGnssVisibilityControl getExtensionGnssVisibilityControl();
+ void start();
+ void stop();
+ void injectTime(in long timeMs, in long timeReferenceMs, in int uncertaintyMs);
+ void injectLocation(in android.hardware.gnss.GnssLocation location);
+ void injectBestLocation(in android.hardware.gnss.GnssLocation location);
+ void deleteAidingData(in android.hardware.gnss.IGnss.GnssAidingData aidingDataFlags);
+ void setPositionMode(in android.hardware.gnss.IGnss.GnssPositionMode mode, in android.hardware.gnss.IGnss.GnssPositionRecurrence recurrence, in int minIntervalMs, in int preferredAccuracyMeters, in int preferredTimeMs, in boolean lowPowerMode);
const int ERROR_INVALID_ARGUMENT = 1;
const int ERROR_ALREADY_INIT = 2;
const int ERROR_GENERIC = 3;
+ @Backing(type="int") @VintfStability
+ enum GnssPositionMode {
+ STANDALONE = 0,
+ MS_BASED = 1,
+ MS_ASSISTED = 2,
+ }
+ @Backing(type="int") @VintfStability
+ enum GnssPositionRecurrence {
+ RECURRENCE_PERIODIC = 0,
+ RECURRENCE_SINGLE = 1,
+ }
+ @Backing(type="int") @VintfStability
+ enum GnssAidingData {
+ DELETE_EPHEMERIS = 1,
+ DELETE_ALMANAC = 2,
+ DELETE_POSITION = 4,
+ DELETE_TIME = 8,
+ DELETE_IONO = 16,
+ DELETE_UTC = 32,
+ DELETE_HEALTH = 64,
+ DELETE_SVDIR = 128,
+ DELETE_SVSTEER = 256,
+ DELETE_SADATA = 512,
+ DELETE_RTI = 1024,
+ DELETE_CELLDB_INFO = 32768,
+ DELETE_ALL = 65535,
+ }
}
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl
index fb0931c..957a75f 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl
@@ -35,8 +35,60 @@
@VintfStability
interface IGnssCallback {
void gnssSetCapabilitiesCb(in int capabilities);
+ void gnssStatusCb(in android.hardware.gnss.IGnssCallback.GnssStatusValue status);
+ void gnssSvStatusCb(in android.hardware.gnss.IGnssCallback.GnssSvInfo[] svInfoList);
+ void gnssLocationCb(in android.hardware.gnss.GnssLocation location);
+ void gnssNmeaCb(in long timestamp, in @utf8InCpp String nmea);
+ void gnssAcquireWakelockCb();
+ void gnssReleaseWakelockCb();
+ void gnssSetSystemInfoCb(in android.hardware.gnss.IGnssCallback.GnssSystemInfo info);
+ void gnssRequestTimeCb();
+ void gnssRequestLocationCb(in boolean independentFromGnss, in boolean isUserEmergency);
+ const int CAPABILITY_SCHEDULING = 1;
+ const int CAPABILITY_MSB = 2;
+ const int CAPABILITY_MSA = 4;
+ const int CAPABILITY_SINGLE_SHOT = 8;
+ const int CAPABILITY_ON_DEMAND_TIME = 16;
+ const int CAPABILITY_GEOFENCING = 32;
+ const int CAPABILITY_MEASUREMENTS = 64;
+ const int CAPABILITY_NAV_MESSAGES = 128;
+ const int CAPABILITY_LOW_POWER_MODE = 256;
const int CAPABILITY_SATELLITE_BLOCKLIST = 512;
+ const int CAPABILITY_MEASUREMENT_CORRECTIONS = 1024;
+ const int CAPABILITY_ANTENNA_INFO = 2048;
const int CAPABILITY_CORRELATION_VECTOR = 4096;
const int CAPABILITY_SATELLITE_PVT = 8192;
const int CAPABILITY_MEASUREMENT_CORRECTIONS_FOR_DRIVING = 16384;
+ @Backing(type="int") @VintfStability
+ enum GnssStatusValue {
+ NONE = 0,
+ SESSION_BEGIN = 1,
+ SESSION_END = 2,
+ ENGINE_ON = 3,
+ ENGINE_OFF = 4,
+ }
+ @Backing(type="int") @VintfStability
+ enum GnssSvFlags {
+ NONE = 0,
+ HAS_EPHEMERIS_DATA = 1,
+ HAS_ALMANAC_DATA = 2,
+ USED_IN_FIX = 4,
+ HAS_CARRIER_FREQUENCY = 8,
+ }
+ @VintfStability
+ parcelable GnssSvInfo {
+ int svid;
+ android.hardware.gnss.GnssConstellationType constellation;
+ float cN0Dbhz;
+ float basebandCN0DbHz;
+ float elevationDegrees;
+ float azimuthDegrees;
+ long carrierFrequencyHz;
+ int svFlag;
+ }
+ @VintfStability
+ parcelable GnssSystemInfo {
+ int yearOfHw;
+ @utf8InCpp String name;
+ }
}
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementInterface.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementInterface.aidl
index 24d6f9c..9c4a54b 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementInterface.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssMeasurementInterface.aidl
@@ -36,4 +36,11 @@
interface IGnssMeasurementInterface {
void setCallback(in android.hardware.gnss.IGnssMeasurementCallback callback, in boolean enableFullTracking, in boolean enableCorrVecOutputs);
void close();
+ void setCallbackWithOptions(in android.hardware.gnss.IGnssMeasurementCallback callback, in android.hardware.gnss.IGnssMeasurementInterface.Options options);
+ @VintfStability
+ parcelable Options {
+ boolean enableFullTracking;
+ boolean enableCorrVecOutputs;
+ int intervalMs;
+ }
}
diff --git a/gnss/aidl/android/hardware/gnss/IAGnss.aidl b/gnss/aidl/android/hardware/gnss/IAGnss.aidl
index 3e256e2..30b2167 100644
--- a/gnss/aidl/android/hardware/gnss/IAGnss.aidl
+++ b/gnss/aidl/android/hardware/gnss/IAGnss.aidl
@@ -60,7 +60,7 @@
* @param hostname Hostname of the AGNSS server.
* @param port Port number associated with the server.
*/
- void setServer(in AGnssType type, in String hostname, in int port);
+ void setServer(in AGnssType type, in @utf8InCpp String hostname, in int port);
/**
* Notifies GNSS that a data connection is available and sets the network handle,
@@ -75,5 +75,6 @@
* @param apn Access Point Name (follows regular APN naming convention).
* @param apnIpType Specifies IP type of APN.
*/
- void dataConnOpen(in long networkHandle, in String apn, in ApnIpType apnIpType);
+ void dataConnOpen(
+ in long networkHandle, in @utf8InCpp String apn, in ApnIpType apnIpType);
}
diff --git a/gnss/aidl/android/hardware/gnss/IGnss.aidl b/gnss/aidl/android/hardware/gnss/IGnss.aidl
index 1351f59..4ddc6a6 100644
--- a/gnss/aidl/android/hardware/gnss/IGnss.aidl
+++ b/gnss/aidl/android/hardware/gnss/IGnss.aidl
@@ -16,6 +16,7 @@
package android.hardware.gnss;
+import android.hardware.gnss.GnssLocation;
import android.hardware.gnss.IAGnss;
import android.hardware.gnss.IGnssBatching;
import android.hardware.gnss.IGnssCallback;
@@ -45,6 +46,53 @@
/** Any other error. */
const int ERROR_GENERIC = 3;
+ /** Requested operational mode for GNSS operation. */
+ @VintfStability
+ @Backing(type="int")
+ enum GnssPositionMode {
+ /** Mode for running GNSS standalone (no assistance). */
+ STANDALONE = 0,
+ /** AGNSS MS-Based mode. */
+ MS_BASED = 1,
+ /**
+ * AGNSS MS-Assisted mode. This mode is not maintained by the platform anymore.
+ * It is strongly recommended to use MS_BASED instead.
+ */
+ MS_ASSISTED = 2,
+ }
+
+ /** Requested recurrence mode for GNSS operation. */
+ @VintfStability
+ @Backing(type="int")
+ enum GnssPositionRecurrence {
+ /** Receive GNSS fixes on a recurring basis at a specified period. */
+ RECURRENCE_PERIODIC = 0,
+ /** Request a single shot GNSS fix. */
+ RECURRENCE_SINGLE = 1,
+ }
+
+ /**
+ * Flags used to specify which aiding data to delete when calling
+ * deleteAidingData().
+ */
+ @VintfStability
+ @Backing(type="int")
+ enum GnssAidingData {
+ DELETE_EPHEMERIS = 0x0001,
+ DELETE_ALMANAC = 0x0002,
+ DELETE_POSITION = 0x0004,
+ DELETE_TIME = 0x0008,
+ DELETE_IONO = 0x0010,
+ DELETE_UTC = 0x0020,
+ DELETE_HEALTH = 0x0040,
+ DELETE_SVDIR = 0x0080,
+ DELETE_SVSTEER = 0x0100,
+ DELETE_SADATA = 0x0200,
+ DELETE_RTI = 0x0400,
+ DELETE_CELLDB_INFO = 0x8000,
+ DELETE_ALL = 0xFFFF
+ }
+
/**
* Opens the interface and provides the callback routines to the implementation of this
* interface.
@@ -152,4 +200,81 @@
* @return Handle to the IGnssVisibilityControl.
*/
IGnssVisibilityControl getExtensionGnssVisibilityControl();
+
+ /**
+ * Starts a location output stream using the IGnssCallback gnssLocationCb(), following the
+ * settings from the most recent call to setPositionMode().
+ *
+ * This output must operate independently of any GNSS location batching operations,
+ * see the IGnssBatching for details.
+ */
+ void start();
+
+ /**
+ * Stops the location output stream.
+ */
+ void stop();
+
+ /**
+ * Injects the current time.
+ *
+ * @param timeMs This is the UTC time received from the NTP server, its value is given in
+ * milliseconds since January 1, 1970.
+ * @param timeReferenceMs The corresponding value of SystemClock.elapsedRealtime() from the
+ * device when the NTP response was received in milliseconds.
+ * @param uncertaintyMs Uncertainty associated with the value represented by time. Represented
+ * in milliseconds.
+ */
+ void injectTime(in long timeMs, in long timeReferenceMs, in int uncertaintyMs);
+
+ /**
+ * Injects current location from another (typically network) location provider.
+ *
+ * @param location Current location from the location provider
+ */
+ void injectLocation(in GnssLocation location);
+
+ /**
+ * Injects current location from the best available location provider.
+ *
+ * Unlike injectLocation, this method may inject a recent GNSS location from the HAL
+ * implementation, if that is the best available location known to the framework.
+ *
+ * @param location Location information from the best available location provider.
+ */
+ void injectBestLocation(in GnssLocation location);
+
+ /**
+ * Specifies that the next call to start will not use the information defined in the flags.
+ * GnssAidingData value of DELETE_ALL is passed for a cold start.
+ *
+ * @param aidingDataFlags Flags specifying the aiding data to be deleted.
+ */
+ void deleteAidingData(in GnssAidingData aidingDataFlags);
+
+ /**
+ * Sets the GnssPositionMode parameter, its associated recurrence value, the time between fixes,
+ * requested fix accuracy, time to first fix.
+ *
+ * @param mode Parameter must be one of MS_BASED or STANDALONE. It is allowed by the platform
+ * (and it is recommended) to fallback to MS_BASED if MS_ASSISTED is passed in, and MS_BASED
+ * is supported.
+ * @param recurrence GNSS position recurrence value, either periodic or single.
+ * @param minIntervalMs Represents the time between fixes in milliseconds.
+ * @param preferredAccuracyMeters Represents the requested fix accuracy in meters.
+ * @param preferredTimeMs Represents the requested time to first fix in milliseconds.
+ * @param lowPowerMode When true, and IGnss is the only client to the GNSS hardware, the GNSS
+ * hardware must make strong tradeoffs to substantially restrict power use. Specifically, in
+ * the case of a several second long minIntervalMs, the GNSS hardware must not, on average,
+ * run power hungry operations like RF and signal searches for more than one second per
+ * interval, and must make exactly one call to gnssSvStatusCb(), and either zero or one call
+ * to GnssLocationCb() at each interval. When false, HAL must operate in the nominal mode
+ * and is expected to make power and performance tradoffs such as duty-cycling when signal
+ * conditions are good and more active searches to reacquire GNSS signals when no signals
+ * are present. When there are additional clients using the GNSS hardware other than IGnss,
+ * the GNSS hardware may operate in a higher power mode, on behalf of those clients.
+ */
+ void setPositionMode(in GnssPositionMode mode, in GnssPositionRecurrence recurrence,
+ in int minIntervalMs, in int preferredAccuracyMeters, in int preferredTimeMs,
+ in boolean lowPowerMode);
}
diff --git a/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl b/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl
index aad09ef..157c912 100644
--- a/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl
+++ b/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl
@@ -16,6 +16,8 @@
package android.hardware.gnss;
+import android.hardware.gnss.GnssConstellationType;
+import android.hardware.gnss.GnssLocation;
import android.hardware.gnss.IGnssConfiguration;
import android.hardware.gnss.IGnssPsds;
@@ -26,9 +28,48 @@
*/
@VintfStability
interface IGnssCallback {
+ /**
+ * Capability bit mask indicating that GNSS supports scheduling fixes for RECURRENCE_PERIODIC
+ * mode.
+ *
+ * If this is not set, then the framework will use 1000ms for minInterval and will call start()
+ * and stop() to schedule the GNSS.
+ */
+ const int CAPABILITY_SCHEDULING = 1 << 0;
+
+ /** Capability bit mask indicating that GNSS supports MS-Based AGNSS mode */
+ const int CAPABILITY_MSB = 1 << 1;
+
+ /** Capability bit mask indicating that GNSS supports MS-Assisted AGNSS mode */
+ const int CAPABILITY_MSA = 1 << 2;
+
+ /** Capability bit mask indicating that GNSS supports single-shot fixes */
+ const int CAPABILITY_SINGLE_SHOT = 1 << 3;
+
+ /** Capability bit mask indicating that GNSS supports on demand time injection */
+ const int CAPABILITY_ON_DEMAND_TIME = 1 << 4;
+
+ /** Capability bit mask indicating that GNSS supports Geofencing */
+ const int CAPABILITY_GEOFENCING = 1 << 5;
+
+ /** Capability bit mask indicating that GNSS supports Measurements. */
+ const int CAPABILITY_MEASUREMENTS = 1 << 6;
+
+ /** Capability bit mask indicating that GNSS supports Navigation Messages */
+ const int CAPABILITY_NAV_MESSAGES = 1 << 7;
+
+ /** Capability bit mask indicating that GNSS supports low power mode */
+ const int CAPABILITY_LOW_POWER_MODE = 1 << 8;
+
/** Capability bit mask indicating that GNSS supports blocklisting satellites */
const int CAPABILITY_SATELLITE_BLOCKLIST = 1 << 9;
+ /** Capability bit mask indicating that GNSS supports measurement corrections */
+ const int CAPABILITY_MEASUREMENT_CORRECTIONS = 1 << 10;
+
+ /** Capability bit mask indicating that GNSS supports measurement corrections */
+ const int CAPABILITY_ANTENNA_INFO = 1 << 11;
+
/** Capability bit mask indicating that GNSS supports correlation vector */
const int CAPABILITY_CORRELATION_VECTOR = 1 << 12;
@@ -44,4 +85,221 @@
* @param capabilities Capability parameter is a bit field of the Capability bit masks.
*/
void gnssSetCapabilitiesCb(in int capabilities);
+
+ /** GNSS status event values. */
+ @VintfStability
+ @Backing(type="int")
+ enum GnssStatusValue {
+ /** GNSS status unknown. */
+ NONE = 0,
+ /** GNSS has begun navigating. */
+ SESSION_BEGIN = 1,
+ /** GNSS has stopped navigating. */
+ SESSION_END = 2,
+ /** GNSS has powered on but is not navigating. */
+ ENGINE_ON = 3,
+ /** GNSS is powered off. */
+ ENGINE_OFF = 4
+ }
+
+ /**
+ * Flags that indicate information about the satellite
+ */
+ @VintfStability
+ @Backing(type="int")
+ enum GnssSvFlags {
+ NONE = 0,
+ HAS_EPHEMERIS_DATA = 1 << 0,
+ HAS_ALMANAC_DATA = 1 << 1,
+ USED_IN_FIX = 1 << 2,
+ HAS_CARRIER_FREQUENCY = 1 << 3,
+ }
+
+ @VintfStability
+ parcelable GnssSvInfo {
+ /**
+ * Pseudo-random or satellite ID number for the satellite, a.k.a. Space Vehicle (SV), or
+ * FCN/OSN number for Glonass. The distinction is made by looking at constellation field.
+ * Values must be in the range of:
+ *
+ * - GNSS: 1-32
+ * - SBAS: 120-151, 183-192
+ * - GLONASS: 1-24, the orbital slot number (OSN), if known. Or, if not:
+ * 93-106, the frequency channel number (FCN) (-7 to +6) offset by
+ * + 100
+ * i.e. report an FCN of -7 as 93, FCN of 0 as 100, and FCN of +6
+ * as 106.
+ * - QZSS: 193-200
+ * - Galileo: 1-36
+ * - Beidou: 1-37
+ * - IRNSS: 1-14
+ */
+ int svid;
+
+ /**
+ * Defines the constellation of the given SV.
+ */
+ GnssConstellationType constellation;
+
+ /**
+ * 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.
+ *
+ * This is a mandatory field.
+ */
+ float cN0Dbhz;
+
+ /**
+ * Baseband Carrier-to-noise density in dB-Hz, typically in the range [0, 63]. It contains
+ * the measured C/N0 value for the signal measured at the baseband.
+ *
+ * This is typically a few dB weaker than the value estimated for C/N0 at the antenna port,
+ * which is reported in cN0DbHz.
+ *
+ * If a signal has separate components (e.g. Pilot and Data channels) and the receiver only
+ * processes one of the components, then the reported basebandCN0DbHz reflects only the
+ * component that is processed.
+ *
+ * This field is mandatory. Like cN0DbHz, it may be reported as 0 for satellites being
+ * reported that may be searched for, but not yet tracked.
+ */
+ float basebandCN0DbHz;
+
+ /** Elevation of SV in degrees. */
+ float elevationDegrees;
+
+ /** Azimuth of SV in degrees. */
+ float azimuthDegrees;
+
+ /**
+ * Carrier frequency of the signal tracked, for example it can be the
+ * GPS central frequency for L1 = 1575.45 MHz, or L2 = 1227.60 MHz, L5 =
+ * 1176.45 MHz, varying GLO channels, etc. If the field is zero, it is
+ * the primary common use central frequency, e.g. L1 = 1575.45 MHz for
+ * GPS.
+ *
+ * For an L1, L5 receiver tracking a satellite on L1 and L5 at the same
+ * time, two GnssSvInfo structs must be reported for this same
+ * satellite, in one of the structs, all the values related
+ * to L1 must be filled, and in the other all of the values related to
+ * L5 must be filled.
+ *
+ * If the data is available, svFlag must contain HAS_CARRIER_FREQUENCY.
+ */
+ long carrierFrequencyHz;
+
+ /** A bit field of the GnssSvFlags. */
+ int svFlag;
+ }
+
+ /**
+ * Called to communicate the status of the GNSS engine.
+ *
+ * @param status Status information from HAL.
+ */
+ void gnssStatusCb(in GnssStatusValue status);
+
+ /**
+ * Callback for the HAL to pass a vector of GnssSvInfo back to the client.
+ *
+ * @param svInfo SV status information from HAL.
+ */
+ void gnssSvStatusCb(in GnssSvInfo[] svInfoList);
+
+ /**
+ * Called when a GNSS location is available.
+ *
+ * @param location Location information from HAL.
+ */
+ void gnssLocationCb(in GnssLocation location);
+
+ /**
+ * Callback for reporting NMEA sentences. Called when NMEA data is available.
+ *
+ * @param timestamp Marks the instance of reporting.
+ * @param nmea Follows standard NMEA 0183. Each sentence begins with a '$'
+ * and ends with a carriage return/line feed sequence and can be no longer
+ * than 80 characters of visible text (plus the line terminators). The data
+ * is contained within this single line with data items separated by commas.
+ * The data itself is just ascii text and may extend over multiple sentences
+ * in certain specialized instances but is normally fully contained in one
+ * variable length sentence. The data may vary in the amount of precision
+ * contained in the message. For example time might be indicated to decimal
+ * parts of a second or location may be shown with 3 or even 4 digits after
+ * the decimal point. Programs that read the data must only use the commas
+ * to determine the field boundaries and not depend on column positions.
+ * There is a provision for a checksum at the end of each sentence which may
+ * or may not be checked by the unit that reads the data. The checksum field
+ * consists of a '*' and two hex digits representing an 8 bit exclusive OR
+ * of all characters between, but not including, the '$' and '*'.
+ */
+ void gnssNmeaCb(in long timestamp, in @utf8InCpp String nmea);
+
+ /**
+ * Callback utility for acquiring the GNSS wakelock. This can be used to prevent
+ * the CPU from suspending while handling GNSS events.
+ */
+ void gnssAcquireWakelockCb();
+
+ /** Callback utility for releasing the GNSS wakelock. */
+ void gnssReleaseWakelockCb();
+
+ /**
+ * Provides information about how new the underlying GPS/GNSS hardware and software is.
+ */
+ @VintfStability
+ parcelable GnssSystemInfo {
+ /**
+ * The year in which the last update was made to the underlying hardware/firmware used to
+ * capture GNSS signals, e.g. 2016.
+ */
+ int yearOfHw;
+
+ /**
+ * The name of the GNSS HAL implementation model and version name.
+ *
+ * This is a user-visible string that identifies the model and version of the GNSS HAL.
+ * For example "ABC Co., Baseband Part 1234, RF Part 567, Software version 3.14.159"
+ *
+ * For privacy reasons, this string must not contain any device-specific serial number or
+ * other identifier that uniquely identifies an individual device.
+ */
+ @utf8InCpp String name;
+ }
+
+ /**
+ * Callback to inform the framework of the GNSS system information.
+ *
+ * This must be called in response to IGnss::setCallback
+ *
+ * @param info GnssSystemInfo about the GPS/GNSS hardware.
+ */
+ void gnssSetSystemInfoCb(in GnssSystemInfo info);
+
+ /** Callback for requesting NTP time */
+ void gnssRequestTimeCb();
+
+ /**
+ * Callback for requesting Location.
+ *
+ * HAL implementation must call this when it wants the framework to provide locations to assist
+ * with GNSS HAL operation, for example, to assist with time to first fix, error recovery, or to
+ * supplement GNSS location for other clients of the GNSS HAL.
+ *
+ * If a request is made with independentFromGnss set to true, the framework must avoid
+ * providing locations derived from GNSS locations (such as "fused" location), to help improve
+ * information independence for situations such as error recovery.
+ *
+ * In response to this method call, GNSS HAL can expect zero, one, or more calls to
+ * IGnss::injectLocation or IGnss::injectBestLocation, dependent on availability of location
+ * from other sources, which may happen at some arbitrary delay. Generally speaking, HAL
+ * implementations must be able to handle calls to IGnss::injectLocation or
+ * IGnss::injectBestLocation at any time.
+ *
+ * @param independentFromGnss True if requesting a location that is independent from GNSS.
+ * @param isUserEmergency True if the location request is for delivery of this location to an
+ * emergency services endpoint, during a user-initiated emergency session (e.g.
+ * during-call to E911, or up to 5 minutes after end-of-call or text to E911).
+ */
+ void gnssRequestLocationCb(in boolean independentFromGnss, in boolean isUserEmergency);
}
diff --git a/gnss/aidl/android/hardware/gnss/IGnssMeasurementInterface.aidl b/gnss/aidl/android/hardware/gnss/IGnssMeasurementInterface.aidl
index 08c83a4..102cdcd 100644
--- a/gnss/aidl/android/hardware/gnss/IGnssMeasurementInterface.aidl
+++ b/gnss/aidl/android/hardware/gnss/IGnssMeasurementInterface.aidl
@@ -24,6 +24,48 @@
@VintfStability
interface IGnssMeasurementInterface {
/**
+ * Options specifying the GnssMeasurement request.
+ */
+ @VintfStability
+ parcelable Options {
+ /**
+ * Enable full tracking mode.
+ *
+ * If true, GNSS chipset must switch off duty cycling. In such mode no clock discontinuities
+ * are expected and, when supported, carrier phase should be continuous in good signal
+ * conditions. All non-blocklisted, healthy constellations, satellites and frequency bands
+ * that the chipset supports must be reported in this mode. The GNSS chipset is allowed to
+ * consume more power in this mode. If false, API must optimize power via duty cycling,
+ * constellations and frequency limits, etc.
+ */
+ boolean enableFullTracking;
+
+ /**
+ * Enable Correlation Vector outputs.
+ *
+ * If true, enable correlation vectors as part of the raw GNSS measurements outputs. If
+ * false, disable correlation vectors.
+ */
+ boolean enableCorrVecOutputs;
+
+ /**
+ * Time interval between the reported measurements in milliseconds.
+ *
+ * The GNSS chipset must not report measurements with a rate slower than requested. All the
+ * available measurements must be reported to the framework.
+ *
+ * For cases where concurrently serving the location and the measurement requests would not
+ * consume more power than only the measurement request, the faster rate of the 2 requests
+ * must be chosen. Otherwise, it is recommended that the GNSS chipset minimizes the power
+ * consumption with appropriate location and measurement intervals to satisfy both requests.
+ * For example, for 2-sec measurement interval request and 7-sec location interval request,
+ * the GNSS chipset is recommended to run the measurement engine with 2-sec interval and the
+ * location engine with 6-sec interval.
+ */
+ int intervalMs;
+ }
+
+ /**
* Initializes the interface and registers the callback routines with the HAL. After a
* successful call to 'setCallback' the HAL must begin to provide updates at an average
* output rate of 1Hz (occasional intra-measurement time offsets in the range from 0-2000msec
@@ -39,13 +81,9 @@
*
* @param enableCorrVecOutputs If true, enable correlation vectors as part of the raw GNSS
* measurements outputs. If false, disable correlation vectors.
- *
- * Returns ok() if successful. Returns ERROR_ALREADY_INIT if a callback has already been
- * registered without a corresponding call to 'close'. Returns ERROR_GENERIC for any other
- * error. The HAL must not generate any other updates upon returning this error code.
*/
void setCallback(in IGnssMeasurementCallback callback, in boolean enableFullTracking,
- in boolean enableCorrVecOutputs);
+ in boolean enableCorrVecOutputs);
/**
* Stops updates from the HAL, and unregisters the callback routines. After a call to close(),
@@ -55,4 +93,11 @@
* no work.
*/
void close();
-}
\ No newline at end of file
+
+ /**
+ * Initializes the interface and registers the callback routines with the HAL.
+ *
+ * @param options See Options definition.
+ */
+ void setCallbackWithOptions(in IGnssMeasurementCallback callback, in Options options);
+}
diff --git a/gnss/aidl/default/Gnss.cpp b/gnss/aidl/default/Gnss.cpp
index afb7b95..e296351 100644
--- a/gnss/aidl/default/Gnss.cpp
+++ b/gnss/aidl/default/Gnss.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "GnssAidl"
#include "Gnss.h"
+#include <inttypes.h>
#include <log/log.h>
#include "AGnss.h"
#include "GnssBatching.h"
@@ -27,16 +28,24 @@
#include "GnssNavigationMessageInterface.h"
#include "GnssPsds.h"
#include "GnssVisibilityControl.h"
+#include "Utils.h"
namespace aidl::android::hardware::gnss {
+using ::android::hardware::gnss::common::Utils;
+using ndk::ScopedAStatus;
+using GnssSvInfo = IGnssCallback::GnssSvInfo;
+
+constexpr int TTFF_MILLIS = 2200;
std::shared_ptr<IGnssCallback> Gnss::sGnssCallback = nullptr;
-ndk::ScopedAStatus Gnss::setCallback(const std::shared_ptr<IGnssCallback>& callback) {
- ALOGD("Gnss::setCallback");
+Gnss::Gnss() : mMinIntervalMs(1000), mFirstFixReceived(false) {}
+
+ScopedAStatus Gnss::setCallback(const std::shared_ptr<IGnssCallback>& callback) {
+ ALOGD("setCallback");
if (callback == nullptr) {
ALOGE("%s: Null callback ignored", __func__);
- return ndk::ScopedAStatus::fromExceptionCode(STATUS_INVALID_OPERATION);
+ return ScopedAStatus::fromExceptionCode(STATUS_INVALID_OPERATION);
}
sGnssCallback = callback;
@@ -50,13 +59,99 @@
ALOGE("%s: Unable to invoke callback.gnssSetCapabilities", __func__);
}
- return ndk::ScopedAStatus::ok();
+ return ScopedAStatus::ok();
}
-ndk::ScopedAStatus Gnss::close() {
- ALOGD("Gnss::close");
+ScopedAStatus Gnss::start() {
+ ALOGD("start()");
+ if (mIsActive) {
+ ALOGW("Gnss has started. Restarting...");
+ stop();
+ }
+
+ mIsActive = true;
+ this->reportGnssStatusValue(IGnssCallback::GnssStatusValue::SESSION_BEGIN);
+ mThread = std::thread([this]() {
+ auto svStatus = filterBlocklistedSatellites(Utils::getMockSvInfoList());
+ this->reportSvStatus(svStatus);
+ if (!mFirstFixReceived) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(TTFF_MILLIS));
+ mFirstFixReceived = true;
+ }
+ while (mIsActive == true) {
+ auto svStatus = filterBlocklistedSatellites(Utils::getMockSvInfoList());
+ this->reportSvStatus(svStatus);
+
+ mGnssPowerIndication->notePowerConsumption();
+ const auto location = Utils::getMockLocation();
+ this->reportLocation(location);
+ std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMs));
+ }
+ });
+ return ScopedAStatus::ok();
+}
+
+void Gnss::reportLocation(const GnssLocation& location) const {
+ std::unique_lock<std::mutex> lock(mMutex);
+ if (sGnssCallback == nullptr) {
+ ALOGE("%s: GnssCallback is null.", __func__);
+ return;
+ }
+ auto status = sGnssCallback->gnssLocationCb(location);
+ if (!status.isOk()) {
+ ALOGE("%s: Unable to invoke gnssLocationCb", __func__);
+ }
+ return;
+}
+
+void Gnss::reportSvStatus(const std::vector<GnssSvInfo>& svInfoList) const {
+ std::unique_lock<std::mutex> lock(mMutex);
+ if (sGnssCallback == nullptr) {
+ ALOGE("%s: sGnssCallback is null.", __func__);
+ return;
+ }
+ auto status = sGnssCallback->gnssSvStatusCb(svInfoList);
+ if (!status.isOk()) {
+ ALOGE("%s: Unable to invoke callback", __func__);
+ }
+}
+
+std::vector<GnssSvInfo> Gnss::filterBlocklistedSatellites(std::vector<GnssSvInfo> gnssSvInfoList) {
+ ALOGD("filterBlocklistedSatellites");
+ for (uint32_t i = 0; i < gnssSvInfoList.size(); i++) {
+ if (mGnssConfiguration->isBlocklisted(gnssSvInfoList[i])) {
+ gnssSvInfoList[i].svFlag &= ~(uint32_t)IGnssCallback::GnssSvFlags::USED_IN_FIX;
+ }
+ }
+ return gnssSvInfoList;
+}
+
+void Gnss::reportGnssStatusValue(const IGnssCallback::GnssStatusValue gnssStatusValue) const {
+ std::unique_lock<std::mutex> lock(mMutex);
+ if (sGnssCallback == nullptr) {
+ ALOGE("%s: sGnssCallback is null.", __func__);
+ return;
+ }
+ auto status = sGnssCallback->gnssStatusCb(gnssStatusValue);
+ if (!status.isOk()) {
+ ALOGE("%s: Unable to invoke gnssStatusCb", __func__);
+ }
+}
+
+ScopedAStatus Gnss::stop() {
+ ALOGD("stop");
+ mIsActive = false;
+ this->reportGnssStatusValue(IGnssCallback::GnssStatusValue::SESSION_END);
+ if (mThread.joinable()) {
+ mThread.join();
+ }
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Gnss::close() {
+ ALOGD("close");
sGnssCallback = nullptr;
- return ndk::ScopedAStatus::ok();
+ return ScopedAStatus::ok();
}
ndk::ScopedAStatus Gnss::getExtensionAGnss(std::shared_ptr<IAGnss>* iAGnss) {
@@ -65,61 +160,93 @@
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Gnss::getExtensionPsds(std::shared_ptr<IGnssPsds>* iGnssPsds) {
- ALOGD("Gnss::getExtensionPsds");
- *iGnssPsds = SharedRefBase::make<GnssPsds>();
- return ndk::ScopedAStatus::ok();
+ScopedAStatus Gnss::injectTime(int64_t timeMs, int64_t timeReferenceMs, int uncertaintyMs) {
+ ALOGD("injectTime. timeMs:%" PRId64 ", timeReferenceMs:%" PRId64 ", uncertaintyMs:%d", timeMs,
+ timeReferenceMs, uncertaintyMs);
+ return ScopedAStatus::ok();
}
-ndk::ScopedAStatus Gnss::getExtensionGnssConfiguration(
+ScopedAStatus Gnss::injectLocation(const GnssLocation& location) {
+ ALOGD("injectLocation. lat:%lf, lng:%lf, acc:%f", location.latitudeDegrees,
+ location.longitudeDegrees, location.horizontalAccuracyMeters);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Gnss::injectBestLocation(const GnssLocation& location) {
+ ALOGD("injectBestLocation. lat:%lf, lng:%lf, acc:%f", location.latitudeDegrees,
+ location.longitudeDegrees, location.horizontalAccuracyMeters);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Gnss::deleteAidingData(GnssAidingData aidingDataFlags) {
+ ALOGD("deleteAidingData. flags:%d", (int)aidingDataFlags);
+ mFirstFixReceived = false;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Gnss::setPositionMode(GnssPositionMode, GnssPositionRecurrence, int minIntervalMs,
+ int /* preferredAccuracyMeters */, int /* preferredTimeMs */,
+ bool lowPowerMode) {
+ ALOGD("setPositionMode. minIntervalMs:%d, lowPowerMode:%d", minIntervalMs, (int)lowPowerMode);
+ mMinIntervalMs = minIntervalMs;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Gnss::getExtensionPsds(std::shared_ptr<IGnssPsds>* iGnssPsds) {
+ ALOGD("getExtensionPsds");
+ *iGnssPsds = SharedRefBase::make<GnssPsds>();
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Gnss::getExtensionGnssConfiguration(
std::shared_ptr<IGnssConfiguration>* iGnssConfiguration) {
- ALOGD("Gnss::getExtensionGnssConfiguration");
+ ALOGD("getExtensionGnssConfiguration");
if (mGnssConfiguration == nullptr) {
mGnssConfiguration = SharedRefBase::make<GnssConfiguration>();
}
*iGnssConfiguration = mGnssConfiguration;
- return ndk::ScopedAStatus::ok();
+ return ScopedAStatus::ok();
}
-ndk::ScopedAStatus Gnss::getExtensionGnssPowerIndication(
+ScopedAStatus Gnss::getExtensionGnssPowerIndication(
std::shared_ptr<IGnssPowerIndication>* iGnssPowerIndication) {
- ALOGD("Gnss::getExtensionGnssPowerIndication");
+ ALOGD("getExtensionGnssPowerIndication");
if (mGnssPowerIndication == nullptr) {
mGnssPowerIndication = SharedRefBase::make<GnssPowerIndication>();
}
*iGnssPowerIndication = mGnssPowerIndication;
- return ndk::ScopedAStatus::ok();
+ return ScopedAStatus::ok();
}
-ndk::ScopedAStatus Gnss::getExtensionGnssMeasurement(
+ScopedAStatus Gnss::getExtensionGnssMeasurement(
std::shared_ptr<IGnssMeasurementInterface>* iGnssMeasurement) {
- ALOGD("Gnss::getExtensionGnssMeasurement");
+ ALOGD("getExtensionGnssMeasurement");
*iGnssMeasurement = SharedRefBase::make<GnssMeasurementInterface>();
- return ndk::ScopedAStatus::ok();
+ return ScopedAStatus::ok();
}
-ndk::ScopedAStatus Gnss::getExtensionGnssBatching(std::shared_ptr<IGnssBatching>* iGnssBatching) {
- ALOGD("Gnss::getExtensionGnssBatching");
+ScopedAStatus Gnss::getExtensionGnssBatching(std::shared_ptr<IGnssBatching>* iGnssBatching) {
+ ALOGD("getExtensionGnssBatching");
*iGnssBatching = SharedRefBase::make<GnssBatching>();
- return ndk::ScopedAStatus::ok();
+ return ScopedAStatus::ok();
}
-ndk::ScopedAStatus Gnss::getExtensionGnssGeofence(std::shared_ptr<IGnssGeofence>* iGnssGeofence) {
- ALOGD("Gnss::getExtensionGnssGeofence");
+ScopedAStatus Gnss::getExtensionGnssGeofence(std::shared_ptr<IGnssGeofence>* iGnssGeofence) {
+ ALOGD("getExtensionGnssGeofence");
*iGnssGeofence = SharedRefBase::make<GnssGeofence>();
- return ndk::ScopedAStatus::ok();
+ return ScopedAStatus::ok();
}
-ndk::ScopedAStatus Gnss::getExtensionGnssNavigationMessage(
+ScopedAStatus Gnss::getExtensionGnssNavigationMessage(
std::shared_ptr<IGnssNavigationMessageInterface>* iGnssNavigationMessage) {
- ALOGD("Gnss::getExtensionGnssNavigationMessage");
+ ALOGD("getExtensionGnssNavigationMessage");
*iGnssNavigationMessage = SharedRefBase::make<GnssNavigationMessageInterface>();
- return ndk::ScopedAStatus::ok();
+ return ScopedAStatus::ok();
}
ndk::ScopedAStatus Gnss::getExtensionGnssDebug(std::shared_ptr<IGnssDebug>* iGnssDebug) {
diff --git a/gnss/aidl/default/Gnss.h b/gnss/aidl/default/Gnss.h
index 67fef94..384c862 100644
--- a/gnss/aidl/default/Gnss.h
+++ b/gnss/aidl/default/Gnss.h
@@ -25,6 +25,9 @@
#include <aidl/android/hardware/gnss/BnGnssPowerIndication.h>
#include <aidl/android/hardware/gnss/BnGnssPsds.h>
#include <aidl/android/hardware/gnss/visibility_control/BnGnssVisibilityControl.h>
+#include <atomic>
+#include <mutex>
+#include <thread>
#include "GnssConfiguration.h"
#include "GnssPowerIndication.h"
@@ -32,8 +35,22 @@
class Gnss : public BnGnss {
public:
+ Gnss();
+ ~Gnss() { stop(); };
ndk::ScopedAStatus setCallback(const std::shared_ptr<IGnssCallback>& callback) override;
+ ndk::ScopedAStatus start() override;
+ ndk::ScopedAStatus stop() override;
ndk::ScopedAStatus close() override;
+
+ ndk::ScopedAStatus injectTime(int64_t timeMs, int64_t timeReferenceMs,
+ int uncertaintyMs) override;
+ ndk::ScopedAStatus injectLocation(const GnssLocation& location) override;
+ ndk::ScopedAStatus injectBestLocation(const GnssLocation& location) override;
+ ndk::ScopedAStatus deleteAidingData(GnssAidingData aidingDataFlags) override;
+ ndk::ScopedAStatus setPositionMode(GnssPositionMode mode, GnssPositionRecurrence recurrence,
+ int minIntervalMs, int preferredAccuracyMeters,
+ int preferredTimeMs, bool lowPowerMode) override;
+
ndk::ScopedAStatus getExtensionPsds(std::shared_ptr<IGnssPsds>* iGnssPsds) override;
ndk::ScopedAStatus getExtensionGnssConfiguration(
std::shared_ptr<IGnssConfiguration>* iGnssConfiguration) override;
@@ -57,7 +74,20 @@
std::shared_ptr<GnssPowerIndication> mGnssPowerIndication;
private:
+ void reportLocation(const GnssLocation&) const;
+ void reportSvStatus(const std::vector<IGnssCallback::GnssSvInfo>& svInfoList) const;
+ std::vector<IGnssCallback::GnssSvInfo> filterBlocklistedSatellites(
+ std::vector<IGnssCallback::GnssSvInfo> gnssSvInfoList);
+ void reportGnssStatusValue(const IGnssCallback::GnssStatusValue gnssStatusValue) const;
+
static std::shared_ptr<IGnssCallback> sGnssCallback;
+
+ std::atomic<long> mMinIntervalMs;
+ std::atomic<bool> mIsActive;
+ std::atomic<bool> mFirstFixReceived;
+ std::thread mThread;
+
+ mutable std::mutex mMutex;
};
} // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/default/GnssConfiguration.cpp b/gnss/aidl/default/GnssConfiguration.cpp
index 30e0d8c..96a1aa2 100644
--- a/gnss/aidl/default/GnssConfiguration.cpp
+++ b/gnss/aidl/default/GnssConfiguration.cpp
@@ -49,4 +49,14 @@
return (mBlocklistedSourceSet.find(source) != mBlocklistedSourceSet.end());
}
+bool GnssConfiguration::isBlocklisted(const IGnssCallback::GnssSvInfo& gnssSvInfo) const {
+ std::unique_lock<std::recursive_mutex> lock(mMutex);
+ if (mBlocklistedConstellationSet.find(gnssSvInfo.constellation) !=
+ mBlocklistedConstellationSet.end()) {
+ return true;
+ }
+ BlocklistedSource source = {.constellation = gnssSvInfo.constellation, .svid = gnssSvInfo.svid};
+ return (mBlocklistedSourceSet.find(source) != mBlocklistedSourceSet.end());
+}
+
} // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/default/GnssConfiguration.h b/gnss/aidl/default/GnssConfiguration.h
index 491733c..3c77f32 100644
--- a/gnss/aidl/default/GnssConfiguration.h
+++ b/gnss/aidl/default/GnssConfiguration.h
@@ -16,6 +16,7 @@
#pragma once
+#include <aidl/android/hardware/gnss/BnGnssCallback.h>
#include <aidl/android/hardware/gnss/BnGnssConfiguration.h>
#include <android/hardware/gnss/2.1/IGnssCallback.h>
#include <mutex>
@@ -62,6 +63,7 @@
ndk::ScopedAStatus setBlocklist(const vector<BlocklistedSource>& blocklist) override;
bool isBlocklistedV2_1(const GnssSvInfoV2_1& gnssSvInfo) const;
+ bool isBlocklisted(const IGnssCallback::GnssSvInfo& gnssSvInfo) const;
private:
BlocklistedSourceSet mBlocklistedSourceSet;
diff --git a/gnss/aidl/default/GnssMeasurementInterface.cpp b/gnss/aidl/default/GnssMeasurementInterface.cpp
index 9e4f7c7..2c7241b 100644
--- a/gnss/aidl/default/GnssMeasurementInterface.cpp
+++ b/gnss/aidl/default/GnssMeasurementInterface.cpp
@@ -56,11 +56,29 @@
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus GnssMeasurementInterface::setCallbackWithOptions(
+ const std::shared_ptr<IGnssMeasurementCallback>& callback, const Options& options) {
+ ALOGD("setCallbackWithOptions: fullTracking:%d, corrVec:%d, intervalMs:%d",
+ (int)options.enableFullTracking, (int)options.enableCorrVecOutputs, options.intervalMs);
+ std::unique_lock<std::mutex> lock(mMutex);
+ sCallback = callback;
+
+ if (mIsActive) {
+ ALOGW("GnssMeasurement callback already set. Resetting the callback...");
+ stop();
+ }
+ mMinIntervalMillis = options.intervalMs;
+ start(options.enableCorrVecOutputs);
+
+ return ndk::ScopedAStatus::ok();
+}
+
ndk::ScopedAStatus GnssMeasurementInterface::close() {
ALOGD("close");
stop();
std::unique_lock<std::mutex> lock(mMutex);
sCallback = nullptr;
+ mMinIntervalMillis = 1000;
return ndk::ScopedAStatus::ok();
}
diff --git a/gnss/aidl/default/GnssMeasurementInterface.h b/gnss/aidl/default/GnssMeasurementInterface.h
index db63515..bf77806 100644
--- a/gnss/aidl/default/GnssMeasurementInterface.h
+++ b/gnss/aidl/default/GnssMeasurementInterface.h
@@ -32,6 +32,9 @@
const bool enableFullTracking,
const bool enableCorrVecOutputs) override;
ndk::ScopedAStatus close() override;
+ ndk::ScopedAStatus setCallbackWithOptions(
+ const std::shared_ptr<IGnssMeasurementCallback>& callback,
+ const Options& options) override;
private:
void start(const bool enableCorrVecOutputs);
diff --git a/gnss/aidl/vts/GnssBatchingCallback.cpp b/gnss/aidl/vts/GnssBatchingCallback.cpp
index 2da3b12..d4eb0a5 100644
--- a/gnss/aidl/vts/GnssBatchingCallback.cpp
+++ b/gnss/aidl/vts/GnssBatchingCallback.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#define LOG_TAG "GnssBatchingCallbackAidl"
+
#include "GnssBatchingCallback.h"
#include <inttypes.h>
#include <log/log.h>
diff --git a/gnss/aidl/vts/GnssCallbackAidl.cpp b/gnss/aidl/vts/GnssCallbackAidl.cpp
index f5c745b..77a2506 100644
--- a/gnss/aidl/vts/GnssCallbackAidl.cpp
+++ b/gnss/aidl/vts/GnssCallbackAidl.cpp
@@ -14,11 +14,62 @@
* limitations under the License.
*/
+#define LOG_TAG "GnssCallbackAidl"
+
#include "GnssCallbackAidl.h"
#include <log/log.h>
-android::binder::Status GnssCallbackAidl::gnssSetCapabilitiesCb(const int capabilities) {
- ALOGI("Capabilities received %d", capabilities);
+using android::binder::Status;
+using android::hardware::gnss::GnssLocation;
+using GnssSvInfo = android::hardware::gnss::IGnssCallback::GnssSvInfo;
+using GnssSystemInfo = android::hardware::gnss::IGnssCallback::GnssSystemInfo;
+
+Status GnssCallbackAidl::gnssSetCapabilitiesCb(const int capabilities) {
+ ALOGI("Capabilities received %#08x", capabilities);
capabilities_cbq_.store(capabilities);
- return android::binder::Status::ok();
+ return Status::ok();
+}
+
+Status GnssCallbackAidl::gnssStatusCb(const GnssStatusValue /* status */) {
+ ALOGI("gnssSvStatusCb");
+ return Status::ok();
+}
+
+Status GnssCallbackAidl::gnssSvStatusCb(const std::vector<GnssSvInfo>& svInfoList) {
+ ALOGI("gnssSvStatusCb. Size = %d", (int)svInfoList.size());
+ sv_info_list_cbq_.store(svInfoList);
+ return Status::ok();
+}
+
+Status GnssCallbackAidl::gnssLocationCb(const GnssLocation& location) {
+ ALOGI("Location received");
+ location_cbq_.store(location);
+ return Status::ok();
+}
+
+Status GnssCallbackAidl::gnssNmeaCb(const int64_t /* timestamp */, const std::string& /* nmea */) {
+ return Status::ok();
+}
+
+Status GnssCallbackAidl::gnssAcquireWakelockCb() {
+ return Status::ok();
+}
+
+Status GnssCallbackAidl::gnssReleaseWakelockCb() {
+ return Status::ok();
+}
+
+Status GnssCallbackAidl::gnssSetSystemInfoCb(const GnssSystemInfo& info) {
+ ALOGI("gnssSetSystemInfoCb, year=%d, name=%s", info.yearOfHw, info.name.c_str());
+ info_cbq_.store(info);
+ return Status::ok();
+}
+
+Status GnssCallbackAidl::gnssRequestTimeCb() {
+ return Status::ok();
+}
+
+Status GnssCallbackAidl::gnssRequestLocationCb(const bool /* independentFromGnss */,
+ const bool /* isUserEmergency */) {
+ return Status::ok();
}
diff --git a/gnss/aidl/vts/GnssCallbackAidl.h b/gnss/aidl/vts/GnssCallbackAidl.h
index 7f802ea..209728d 100644
--- a/gnss/aidl/vts/GnssCallbackAidl.h
+++ b/gnss/aidl/vts/GnssCallbackAidl.h
@@ -22,11 +22,37 @@
/* Callback class for data & Event. */
class GnssCallbackAidl : public android::hardware::gnss::BnGnssCallback {
public:
- GnssCallbackAidl() : capabilities_cbq_("capabilities"){};
+ GnssCallbackAidl()
+ : capabilities_cbq_("capabilities"),
+ info_cbq_("system_info"),
+ location_cbq_("location"),
+ sv_info_list_cbq_("sv_info"){};
~GnssCallbackAidl(){};
android::binder::Status gnssSetCapabilitiesCb(const int capabilities) override;
+ android::binder::Status gnssStatusCb(const GnssStatusValue status) override;
+ android::binder::Status gnssSvStatusCb(const std::vector<GnssSvInfo>& svInfoList) override;
+ android::binder::Status gnssLocationCb(
+ const android::hardware::gnss::GnssLocation& location) override;
+ android::binder::Status gnssNmeaCb(const int64_t timestamp, const std::string& nmea) override;
+ android::binder::Status gnssAcquireWakelockCb() override;
+ android::binder::Status gnssReleaseWakelockCb() override;
+ android::binder::Status gnssSetSystemInfoCb(const GnssSystemInfo& info) override;
+ android::binder::Status gnssRequestTimeCb() override;
+ android::binder::Status gnssRequestLocationCb(const bool independentFromGnss,
+ const bool isUserEmergency) override;
int last_capabilities_;
+ android::hardware::gnss::IGnssCallback::GnssSystemInfo last_info_;
+ android::hardware::gnss::GnssLocation last_location_;
+
android::hardware::gnss::common::GnssCallbackEventQueue<int> capabilities_cbq_;
+ android::hardware::gnss::common::GnssCallbackEventQueue<
+ android::hardware::gnss::IGnssCallback::GnssSystemInfo>
+ info_cbq_;
+ android::hardware::gnss::common::GnssCallbackEventQueue<android::hardware::gnss::GnssLocation>
+ location_cbq_;
+ android::hardware::gnss::common::GnssCallbackEventQueue<
+ std::vector<android::hardware::gnss::IGnssCallback::GnssSvInfo>>
+ sv_info_list_cbq_;
};
\ No newline at end of file
diff --git a/gnss/aidl/vts/gnss_hal_test.cpp b/gnss/aidl/vts/gnss_hal_test.cpp
index 2447bf8..13c32ee 100644
--- a/gnss/aidl/vts/gnss_hal_test.cpp
+++ b/gnss/aidl/vts/gnss_hal_test.cpp
@@ -14,20 +14,31 @@
* limitations under the License.
*/
+#define LOG_TAG "GnssHalTest"
+
#include "gnss_hal_test.h"
#include <hidl/ServiceManagement.h>
+#include "Utils.h"
-using GnssConstellationTypeAidl = android::hardware::gnss::GnssConstellationType;
+using android::hardware::gnss::GnssConstellationType;
+using android::hardware::gnss::GnssLocation;
+using android::hardware::gnss::IGnss;
+using android::hardware::gnss::IGnssCallback;
+using android::hardware::gnss::common::Utils;
+using GnssConstellationTypeV2_0 = android::hardware::gnss::V2_0::GnssConstellationType;
void GnssHalTest::SetUp() {
// Get AIDL handle
aidl_gnss_hal_ = android::waitForDeclaredService<IGnssAidl>(String16(GetParam().c_str()));
ASSERT_NE(aidl_gnss_hal_, nullptr);
+ ALOGD("AIDL Interface Version = %d", aidl_gnss_hal_->getInterfaceVersion());
- const auto& hidlInstanceNames = android::hardware::getAllHalInstanceNames(
- android::hardware::gnss::V2_1::IGnss::descriptor);
- gnss_hal_ = IGnss_V2_1::getService(hidlInstanceNames[0]);
- ASSERT_NE(gnss_hal_, nullptr);
+ if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+ const auto& hidlInstanceNames = android::hardware::getAllHalInstanceNames(
+ android::hardware::gnss::V2_1::IGnss::descriptor);
+ gnss_hal_ = IGnss_V2_1::getService(hidlInstanceNames[0]);
+ ASSERT_NE(gnss_hal_, nullptr);
+ }
SetUpGnssCallback();
}
@@ -40,7 +51,6 @@
if (!status.isOk()) {
ALOGE("Failed to setCallback");
}
-
ASSERT_TRUE(status.isOk());
/*
@@ -48,9 +58,243 @@
*/
EXPECT_TRUE(aidl_gnss_cb_->capabilities_cbq_.retrieve(aidl_gnss_cb_->last_capabilities_,
TIMEOUT_SEC));
-
EXPECT_EQ(aidl_gnss_cb_->capabilities_cbq_.calledCount(), 1);
- // Invoke the super method.
- GnssHalTestTemplate<IGnss_V2_1>::SetUpGnssCallback();
+ if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+ // Invoke the super method.
+ GnssHalTestTemplate<IGnss_V2_1>::SetUpGnssCallback();
+ }
+}
+
+void GnssHalTest::CheckLocation(const GnssLocation& location, bool check_speed) {
+ Utils::checkLocation(location, check_speed, /* check_more_accuracies= */ true);
+}
+
+void GnssHalTest::SetPositionMode(const int min_interval_msec, const bool low_power_mode) {
+ if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+ // Invoke the super method.
+ return GnssHalTestTemplate<IGnss_V2_1>::SetPositionMode(min_interval_msec, low_power_mode);
+ }
+
+ const int kPreferredAccuracy = 0; // Ideally perfect (matches GnssLocationProvider)
+ const int kPreferredTimeMsec = 0; // Ideally immediate
+
+ auto status = aidl_gnss_hal_->setPositionMode(
+ IGnss::GnssPositionMode::MS_BASED, IGnss::GnssPositionRecurrence::RECURRENCE_PERIODIC,
+ min_interval_msec, kPreferredAccuracy, kPreferredTimeMsec, low_power_mode);
+
+ ASSERT_TRUE(status.isOk());
+}
+
+bool GnssHalTest::StartAndCheckFirstLocation(const int min_interval_msec,
+ const bool low_power_mode) {
+ if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+ // Invoke the super method.
+ return GnssHalTestTemplate<IGnss_V2_1>::StartAndCheckFirstLocation(min_interval_msec,
+ low_power_mode);
+ }
+
+ SetPositionMode(min_interval_msec, low_power_mode);
+ auto result = aidl_gnss_hal_->start();
+
+ EXPECT_TRUE(result.isOk());
+
+ /*
+ * GnssLocationProvider support of AGPS SUPL & XtraDownloader is not available in VTS,
+ * so allow time to demodulate ephemeris over the air.
+ */
+ const int kFirstGnssLocationTimeoutSeconds = 75;
+
+ EXPECT_TRUE(aidl_gnss_cb_->location_cbq_.retrieve(aidl_gnss_cb_->last_location_,
+ kFirstGnssLocationTimeoutSeconds));
+ int locationCalledCount = aidl_gnss_cb_->location_cbq_.calledCount();
+ EXPECT_EQ(locationCalledCount, 1);
+
+ if (locationCalledCount > 0) {
+ // don't require speed on first fix
+ CheckLocation(aidl_gnss_cb_->last_location_, false);
+ return true;
+ }
+ return false;
+}
+
+void GnssHalTest::StopAndClearLocations() {
+ ALOGD("StopAndClearLocations");
+ if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+ // Invoke the super method.
+ return GnssHalTestTemplate<IGnss_V2_1>::StopAndClearLocations();
+ }
+
+ auto status = aidl_gnss_hal_->stop();
+ EXPECT_TRUE(status.isOk());
+
+ /*
+ * Clear notify/waiting counter, allowing up till the timeout after
+ * the last reply for final startup messages to arrive (esp. system
+ * info.)
+ */
+ while (aidl_gnss_cb_->location_cbq_.retrieve(aidl_gnss_cb_->last_location_, TIMEOUT_SEC)) {
+ }
+ aidl_gnss_cb_->location_cbq_.reset();
+}
+
+void GnssHalTest::StartAndCheckLocations(int count) {
+ if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+ // Invoke the super method.
+ return GnssHalTestTemplate<IGnss_V2_1>::StartAndCheckLocations(count);
+ }
+ const int kMinIntervalMsec = 500;
+ const int kLocationTimeoutSubsequentSec = 2;
+ const bool kLowPowerMode = false;
+
+ EXPECT_TRUE(StartAndCheckFirstLocation(kMinIntervalMsec, kLowPowerMode));
+
+ for (int i = 1; i < count; i++) {
+ EXPECT_TRUE(aidl_gnss_cb_->location_cbq_.retrieve(aidl_gnss_cb_->last_location_,
+ kLocationTimeoutSubsequentSec));
+ int locationCalledCount = aidl_gnss_cb_->location_cbq_.calledCount();
+ EXPECT_EQ(locationCalledCount, i + 1);
+ // Don't cause confusion by checking details if no location yet
+ if (locationCalledCount > 0) {
+ // Should be more than 1 location by now, but if not, still don't check first fix speed
+ CheckLocation(aidl_gnss_cb_->last_location_, locationCalledCount > 1);
+ }
+ }
+}
+
+std::list<std::vector<IGnssCallback::GnssSvInfo>> GnssHalTest::convertToAidl(
+ const std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>>& sv_info_list) {
+ std::list<std::vector<IGnssCallback::GnssSvInfo>> aidl_sv_info_list;
+ for (const auto& sv_info_vec : sv_info_list) {
+ std::vector<IGnssCallback::GnssSvInfo> aidl_sv_info_vec;
+ for (const auto& sv_info : sv_info_vec) {
+ IGnssCallback::GnssSvInfo aidl_sv_info;
+ aidl_sv_info.svid = sv_info.v2_0.v1_0.svid;
+ aidl_sv_info.constellation =
+ static_cast<GnssConstellationType>(sv_info.v2_0.constellation);
+ aidl_sv_info.cN0Dbhz = sv_info.v2_0.v1_0.cN0Dbhz;
+ aidl_sv_info.basebandCN0DbHz = sv_info.basebandCN0DbHz;
+ aidl_sv_info.elevationDegrees = sv_info.v2_0.v1_0.elevationDegrees;
+ aidl_sv_info.azimuthDegrees = sv_info.v2_0.v1_0.azimuthDegrees;
+ aidl_sv_info.carrierFrequencyHz = (int64_t)sv_info.v2_0.v1_0.carrierFrequencyHz;
+ aidl_sv_info.svFlag = (int)sv_info.v2_0.v1_0.svFlag;
+ aidl_sv_info_vec.push_back(aidl_sv_info);
+ }
+ aidl_sv_info_list.push_back(aidl_sv_info_vec);
+ }
+ return aidl_sv_info_list;
+}
+
+/*
+ * FindStrongFrequentNonGpsSource:
+ *
+ * Search through a GnssSvStatus list for the strongest non-GPS satellite observed enough times
+ *
+ * returns the strongest source,
+ * or a source with constellation == UNKNOWN if none are found sufficient times
+ */
+BlocklistedSource GnssHalTest::FindStrongFrequentNonGpsSource(
+ const std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_list,
+ const int min_observations) {
+ return FindStrongFrequentNonGpsSource(convertToAidl(sv_info_list), min_observations);
+}
+
+BlocklistedSource GnssHalTest::FindStrongFrequentNonGpsSource(
+ const std::list<std::vector<IGnssCallback::GnssSvInfo>> sv_info_list,
+ const int min_observations) {
+ std::map<ComparableBlocklistedSource, SignalCounts> mapSignals;
+
+ for (const auto& sv_info_vec : sv_info_list) {
+ for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
+ const auto& gnss_sv = sv_info_vec[iSv];
+ if ((gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX) &&
+ (gnss_sv.constellation != GnssConstellationType::GPS)) {
+ ComparableBlocklistedSource source;
+ source.id.svid = gnss_sv.svid;
+ source.id.constellation = gnss_sv.constellation;
+
+ const auto& itSignal = mapSignals.find(source);
+ if (itSignal == mapSignals.end()) {
+ SignalCounts counts;
+ counts.observations = 1;
+ counts.max_cn0_dbhz = gnss_sv.cN0Dbhz;
+ mapSignals.insert(
+ std::pair<ComparableBlocklistedSource, SignalCounts>(source, counts));
+ } else {
+ itSignal->second.observations++;
+ if (itSignal->second.max_cn0_dbhz < gnss_sv.cN0Dbhz) {
+ itSignal->second.max_cn0_dbhz = gnss_sv.cN0Dbhz;
+ }
+ }
+ }
+ }
+ }
+
+ float max_cn0_dbhz_with_sufficient_count = 0.;
+ int total_observation_count = 0;
+ int blocklisted_source_count_observation = 0;
+
+ ComparableBlocklistedSource source_to_blocklist; // initializes to zero = UNKNOWN constellation
+ for (auto const& pairSignal : mapSignals) {
+ total_observation_count += pairSignal.second.observations;
+ if ((pairSignal.second.observations >= min_observations) &&
+ (pairSignal.second.max_cn0_dbhz > max_cn0_dbhz_with_sufficient_count)) {
+ source_to_blocklist = pairSignal.first;
+ blocklisted_source_count_observation = pairSignal.second.observations;
+ max_cn0_dbhz_with_sufficient_count = pairSignal.second.max_cn0_dbhz;
+ }
+ }
+ ALOGD("Among %d observations, chose svid %d, constellation %d, "
+ "with %d observations at %.1f max CNo",
+ total_observation_count, source_to_blocklist.id.svid,
+ (int)source_to_blocklist.id.constellation, blocklisted_source_count_observation,
+ max_cn0_dbhz_with_sufficient_count);
+
+ return source_to_blocklist.id;
+}
+
+GnssConstellationType GnssHalTest::startLocationAndGetNonGpsConstellation(
+ const int locations_to_await, const int gnss_sv_info_list_timeout) {
+ if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+ return static_cast<GnssConstellationType>(
+ GnssHalTestTemplate<IGnss_V2_1>::startLocationAndGetNonGpsConstellation(
+ locations_to_await, gnss_sv_info_list_timeout));
+ }
+ aidl_gnss_cb_->location_cbq_.reset();
+ StartAndCheckLocations(locations_to_await);
+ const int location_called_count = aidl_gnss_cb_->location_cbq_.calledCount();
+
+ // Tolerate 1 less sv status to handle edge cases in reporting.
+ int sv_info_list_cbq_size = aidl_gnss_cb_->sv_info_list_cbq_.size();
+ EXPECT_GE(sv_info_list_cbq_size + 1, locations_to_await);
+ ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)",
+ sv_info_list_cbq_size, locations_to_await, location_called_count);
+
+ // Find first non-GPS constellation to blocklist
+ GnssConstellationType constellation_to_blocklist = GnssConstellationType::UNKNOWN;
+ for (int i = 0; i < sv_info_list_cbq_size; ++i) {
+ std::vector<IGnssCallback::GnssSvInfo> sv_info_vec;
+ aidl_gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, gnss_sv_info_list_timeout);
+ for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
+ auto& gnss_sv = sv_info_vec[iSv];
+ if ((gnss_sv.svFlag & (uint32_t)IGnssCallback::GnssSvFlags::USED_IN_FIX) &&
+ (gnss_sv.constellation != GnssConstellationType::UNKNOWN) &&
+ (gnss_sv.constellation != GnssConstellationType::GPS)) {
+ // found a non-GPS constellation
+ constellation_to_blocklist = gnss_sv.constellation;
+ break;
+ }
+ }
+ if (constellation_to_blocklist != GnssConstellationType::UNKNOWN) {
+ break;
+ }
+ }
+
+ if (constellation_to_blocklist == GnssConstellationType::UNKNOWN) {
+ ALOGI("No non-GPS constellations found, constellation blocklist test less effective.");
+ // Proceed functionally to blocklist something.
+ constellation_to_blocklist = GnssConstellationType::GLONASS;
+ }
+
+ return constellation_to_blocklist;
}
diff --git a/gnss/aidl/vts/gnss_hal_test.h b/gnss/aidl/vts/gnss_hal_test.h
index e3ecbed..d479af3 100644
--- a/gnss/aidl/vts/gnss_hal_test.h
+++ b/gnss/aidl/vts/gnss_hal_test.h
@@ -41,9 +41,50 @@
public:
GnssHalTest(){};
~GnssHalTest(){};
+
+ struct ComparableBlocklistedSource {
+ android::hardware::gnss::BlocklistedSource id;
+
+ ComparableBlocklistedSource() {
+ id.constellation = android::hardware::gnss::GnssConstellationType::UNKNOWN;
+ id.svid = 0;
+ }
+
+ bool operator<(const ComparableBlocklistedSource& compare) const {
+ return ((id.svid < compare.id.svid) || ((id.svid == compare.id.svid) &&
+ (id.constellation < compare.id.constellation)));
+ }
+ };
+
+ struct SignalCounts {
+ int observations;
+ float max_cn0_dbhz;
+ };
+
virtual void SetUp() override;
virtual void SetUpGnssCallback() override;
+ void CheckLocation(const android::hardware::gnss::GnssLocation& location,
+ const bool check_speed);
+ void SetPositionMode(const int min_interval_msec, const bool low_power_mode);
+ bool StartAndCheckFirstLocation(const int min_interval_msec, const bool low_power_mode);
+ void StopAndClearLocations();
+ void StartAndCheckLocations(int count);
+
+ android::hardware::gnss::GnssConstellationType startLocationAndGetNonGpsConstellation(
+ const int locations_to_await, const int gnss_sv_info_list_timeout);
+ std::list<std::vector<android::hardware::gnss::IGnssCallback::GnssSvInfo>> convertToAidl(
+ const std::list<hidl_vec<android::hardware::gnss::V2_1::IGnssCallback::GnssSvInfo>>&
+ sv_info_list);
+ android::hardware::gnss::BlocklistedSource FindStrongFrequentNonGpsSource(
+ const std::list<hidl_vec<android::hardware::gnss::V2_1::IGnssCallback::GnssSvInfo>>
+ sv_info_list,
+ const int min_observations);
+ android::hardware::gnss::BlocklistedSource FindStrongFrequentNonGpsSource(
+ const std::list<std::vector<android::hardware::gnss::IGnssCallback::GnssSvInfo>>
+ sv_info_list,
+ const int min_observations);
+
sp<IGnssAidl> aidl_gnss_hal_;
sp<GnssCallbackAidl> aidl_gnss_cb_; // Primary callback interface
};
diff --git a/gnss/aidl/vts/gnss_hal_test_cases.cpp b/gnss/aidl/vts/gnss_hal_test_cases.cpp
index 90b643c..9acef8b 100644
--- a/gnss/aidl/vts/gnss_hal_test_cases.cpp
+++ b/gnss/aidl/vts/gnss_hal_test_cases.cpp
@@ -46,6 +46,7 @@
using android::hardware::gnss::IGnss;
using android::hardware::gnss::IGnssBatching;
using android::hardware::gnss::IGnssBatchingCallback;
+using android::hardware::gnss::IGnssCallback;
using android::hardware::gnss::IGnssConfiguration;
using android::hardware::gnss::IGnssDebug;
using android::hardware::gnss::IGnssGeofence;
@@ -59,6 +60,7 @@
using android::hardware::gnss::SatellitePvt;
using android::hardware::gnss::visibility_control::IGnssVisibilityControl;
+using GnssConstellationTypeV2_0 = android::hardware::gnss::V2_0::GnssConstellationType;
using GnssConstellationTypeAidl = android::hardware::gnss::GnssConstellationType;
static bool IsAutomotiveDevice() {
@@ -324,7 +326,11 @@
auto powerStats1 = gnssPowerIndicationCallback->last_gnss_power_stats_;
// Get a location and request another GnssPowerStats
- gnss_cb_->location_cbq_.reset();
+ if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+ gnss_cb_->location_cbq_.reset();
+ } else {
+ aidl_gnss_cb_->location_cbq_.reset();
+ }
StartAndCheckFirstLocation(/* min_interval_msec= */ 1000, /* low_power_mode= */ false);
// Request and verify the 2nd GnssPowerStats has larger values than the 1st one
@@ -375,88 +381,6 @@
}
/*
- * FindStrongFrequentNonGpsSource:
- *
- * Search through a GnssSvStatus list for the strongest non-GPS satellite observed enough times
- *
- * returns the strongest source,
- * or a source with constellation == UNKNOWN if none are found sufficient times
- */
-BlocklistedSource FindStrongFrequentNonGpsSource(
- const std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_list,
- const int min_observations) {
- struct ComparableBlocklistedSource {
- BlocklistedSource id;
-
- ComparableBlocklistedSource() {
- id.constellation = GnssConstellationTypeAidl::UNKNOWN;
- id.svid = 0;
- }
-
- bool operator<(const ComparableBlocklistedSource& compare) const {
- return ((id.svid < compare.id.svid) || ((id.svid == compare.id.svid) &&
- (id.constellation < compare.id.constellation)));
- }
- };
-
- struct SignalCounts {
- int observations;
- float max_cn0_dbhz;
- };
-
- std::map<ComparableBlocklistedSource, SignalCounts> mapSignals;
-
- for (const auto& sv_info_vec : sv_info_list) {
- for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
- const auto& gnss_sv = sv_info_vec[iSv];
- if ((gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX) &&
- (gnss_sv.v2_0.constellation != GnssConstellationType::GPS)) {
- ComparableBlocklistedSource source;
- source.id.svid = gnss_sv.v2_0.v1_0.svid;
- source.id.constellation =
- static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation);
-
- const auto& itSignal = mapSignals.find(source);
- if (itSignal == mapSignals.end()) {
- SignalCounts counts;
- counts.observations = 1;
- counts.max_cn0_dbhz = gnss_sv.v2_0.v1_0.cN0Dbhz;
- mapSignals.insert(
- std::pair<ComparableBlocklistedSource, SignalCounts>(source, counts));
- } else {
- itSignal->second.observations++;
- if (itSignal->second.max_cn0_dbhz < gnss_sv.v2_0.v1_0.cN0Dbhz) {
- itSignal->second.max_cn0_dbhz = gnss_sv.v2_0.v1_0.cN0Dbhz;
- }
- }
- }
- }
- }
-
- float max_cn0_dbhz_with_sufficient_count = 0.;
- int total_observation_count = 0;
- int blocklisted_source_count_observation = 0;
-
- ComparableBlocklistedSource source_to_blocklist; // initializes to zero = UNKNOWN constellation
- for (auto const& pairSignal : mapSignals) {
- total_observation_count += pairSignal.second.observations;
- if ((pairSignal.second.observations >= min_observations) &&
- (pairSignal.second.max_cn0_dbhz > max_cn0_dbhz_with_sufficient_count)) {
- source_to_blocklist = pairSignal.first;
- blocklisted_source_count_observation = pairSignal.second.observations;
- max_cn0_dbhz_with_sufficient_count = pairSignal.second.max_cn0_dbhz;
- }
- }
- ALOGD("Among %d observations, chose svid %d, constellation %d, "
- "with %d observations at %.1f max CNo",
- total_observation_count, source_to_blocklist.id.svid,
- (int)source_to_blocklist.id.constellation, blocklisted_source_count_observation,
- max_cn0_dbhz_with_sufficient_count);
-
- return source_to_blocklist.id;
-}
-
-/*
* BlocklistIndividualSatellites:
*
* 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding
@@ -481,12 +405,20 @@
const int kLocationsToAwait = 3;
const int kRetriesToUnBlocklist = 10;
- gnss_cb_->location_cbq_.reset();
+ if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+ gnss_cb_->location_cbq_.reset();
+ } else {
+ aidl_gnss_cb_->location_cbq_.reset();
+ }
StartAndCheckLocations(kLocationsToAwait);
- int location_called_count = gnss_cb_->location_cbq_.calledCount();
+ int location_called_count = (aidl_gnss_hal_->getInterfaceVersion() == 1)
+ ? gnss_cb_->location_cbq_.calledCount()
+ : aidl_gnss_cb_->location_cbq_.calledCount();
// Tolerate 1 less sv status to handle edge cases in reporting.
- int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
+ int sv_info_list_cbq_size = (aidl_gnss_hal_->getInterfaceVersion() == 1)
+ ? gnss_cb_->sv_info_list_cbq_.size()
+ : aidl_gnss_cb_->sv_info_list_cbq_.size();
EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)",
sv_info_list_cbq_size, kLocationsToAwait, location_called_count);
@@ -498,14 +430,22 @@
*/
const int kGnssSvInfoListTimeout = 2;
- std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_vec_list;
- int count = gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec_list, sv_info_list_cbq_size,
- kGnssSvInfoListTimeout);
-
- ASSERT_EQ(count, sv_info_list_cbq_size);
-
- BlocklistedSource source_to_blocklist =
- FindStrongFrequentNonGpsSource(sv_info_vec_list, kLocationsToAwait - 1);
+ BlocklistedSource source_to_blocklist;
+ if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+ std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_vec_list;
+ int count = gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec_list, sv_info_list_cbq_size,
+ kGnssSvInfoListTimeout);
+ ASSERT_EQ(count, sv_info_list_cbq_size);
+ source_to_blocklist =
+ FindStrongFrequentNonGpsSource(sv_info_vec_list, kLocationsToAwait - 1);
+ } else {
+ std::list<std::vector<IGnssCallback::GnssSvInfo>> sv_info_vec_list;
+ int count = aidl_gnss_cb_->sv_info_list_cbq_.retrieve(
+ sv_info_vec_list, sv_info_list_cbq_size, kGnssSvInfoListTimeout);
+ ASSERT_EQ(count, sv_info_list_cbq_size);
+ source_to_blocklist =
+ FindStrongFrequentNonGpsSource(sv_info_vec_list, kLocationsToAwait - 1);
+ }
if (source_to_blocklist.constellation == GnssConstellationTypeAidl::UNKNOWN) {
// Cannot find a non-GPS satellite. Let the test pass.
@@ -529,32 +469,53 @@
ASSERT_TRUE(status.isOk());
// retry and ensure satellite not used
- gnss_cb_->sv_info_list_cbq_.reset();
+ if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+ gnss_cb_->sv_info_list_cbq_.reset();
+ gnss_cb_->location_cbq_.reset();
+ } else {
+ aidl_gnss_cb_->sv_info_list_cbq_.reset();
+ aidl_gnss_cb_->location_cbq_.reset();
+ }
- gnss_cb_->location_cbq_.reset();
StartAndCheckLocations(kLocationsToAwait);
// early exit if test is being run with insufficient signal
- location_called_count = gnss_cb_->location_cbq_.calledCount();
+ location_called_count = (aidl_gnss_hal_->getInterfaceVersion() == 1)
+ ? gnss_cb_->location_cbq_.calledCount()
+ : aidl_gnss_cb_->location_cbq_.calledCount();
if (location_called_count == 0) {
ALOGE("0 Gnss locations received - ensure sufficient signal and retry");
}
ASSERT_TRUE(location_called_count > 0);
// Tolerate 1 less sv status to handle edge cases in reporting.
- sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
+ sv_info_list_cbq_size = (aidl_gnss_hal_->getInterfaceVersion() == 1)
+ ? gnss_cb_->sv_info_list_cbq_.size()
+ : aidl_gnss_cb_->sv_info_list_cbq_.size();
EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)",
sv_info_list_cbq_size, kLocationsToAwait, location_called_count);
for (int i = 0; i < sv_info_list_cbq_size; ++i) {
- hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
- gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
- for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
- const auto& gnss_sv = sv_info_vec[iSv];
- EXPECT_FALSE((gnss_sv.v2_0.v1_0.svid == source_to_blocklist.svid) &&
- (static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
- source_to_blocklist.constellation) &&
- (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
+ if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+ hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
+ gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
+ for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
+ auto& gnss_sv = sv_info_vec[iSv];
+ EXPECT_FALSE(
+ (gnss_sv.v2_0.v1_0.svid == source_to_blocklist.svid) &&
+ (static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
+ source_to_blocklist.constellation) &&
+ (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
+ }
+ } else {
+ std::vector<IGnssCallback::GnssSvInfo> sv_info_vec;
+ aidl_gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
+ for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
+ auto& gnss_sv = sv_info_vec[iSv];
+ EXPECT_FALSE((gnss_sv.svid == source_to_blocklist.svid) &&
+ (gnss_sv.constellation == source_to_blocklist.constellation) &&
+ (gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX));
+ }
}
}
@@ -569,36 +530,59 @@
int unblocklist_loops_remaining = kRetriesToUnBlocklist;
while (!strongest_sv_is_reobserved && (unblocklist_loops_remaining-- > 0)) {
StopAndClearLocations();
- gnss_cb_->sv_info_list_cbq_.reset();
- gnss_cb_->location_cbq_.reset();
+ if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+ gnss_cb_->sv_info_list_cbq_.reset();
+ gnss_cb_->location_cbq_.reset();
+ } else {
+ aidl_gnss_cb_->sv_info_list_cbq_.reset();
+ aidl_gnss_cb_->location_cbq_.reset();
+ }
StartAndCheckLocations(kLocationsToAwait);
// early exit loop if test is being run with insufficient signal
- location_called_count = gnss_cb_->location_cbq_.calledCount();
+ location_called_count = (aidl_gnss_hal_->getInterfaceVersion() == 1)
+ ? gnss_cb_->location_cbq_.calledCount()
+ : aidl_gnss_cb_->location_cbq_.calledCount();
if (location_called_count == 0) {
ALOGE("0 Gnss locations received - ensure sufficient signal and retry");
}
ASSERT_TRUE(location_called_count > 0);
// Tolerate 1 less sv status to handle edge cases in reporting.
- sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
+ sv_info_list_cbq_size = (aidl_gnss_hal_->getInterfaceVersion() == 1)
+ ? gnss_cb_->sv_info_list_cbq_.size()
+ : aidl_gnss_cb_->sv_info_list_cbq_.size();
EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
ALOGD("Clear blocklist, observed %d GnssSvInfo, while awaiting %d Locations"
", tries remaining %d",
sv_info_list_cbq_size, kLocationsToAwait, unblocklist_loops_remaining);
for (int i = 0; i < sv_info_list_cbq_size; ++i) {
- hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
- gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
- for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
- const auto& gnss_sv = sv_info_vec[iSv];
- if ((gnss_sv.v2_0.v1_0.svid == source_to_blocklist.svid) &&
- (static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
- source_to_blocklist.constellation) &&
- (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)) {
- strongest_sv_is_reobserved = true;
- break;
+ if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+ hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
+ gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
+ for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
+ auto& gnss_sv = sv_info_vec[iSv];
+ if ((gnss_sv.v2_0.v1_0.svid == source_to_blocklist.svid) &&
+ (static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
+ source_to_blocklist.constellation) &&
+ (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)) {
+ strongest_sv_is_reobserved = true;
+ break;
+ }
+ }
+ } else {
+ std::vector<IGnssCallback::GnssSvInfo> sv_info_vec;
+ aidl_gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
+ for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
+ auto& gnss_sv = sv_info_vec[iSv];
+ if ((gnss_sv.svid == source_to_blocklist.svid) &&
+ (gnss_sv.constellation == source_to_blocklist.constellation) &&
+ (gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX)) {
+ strongest_sv_is_reobserved = true;
+ break;
+ }
}
}
if (strongest_sv_is_reobserved) break;
@@ -660,27 +644,47 @@
ASSERT_TRUE(status.isOk());
// retry and ensure constellation not used
- gnss_cb_->sv_info_list_cbq_.reset();
-
- gnss_cb_->location_cbq_.reset();
+ if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+ gnss_cb_->sv_info_list_cbq_.reset();
+ gnss_cb_->location_cbq_.reset();
+ } else {
+ aidl_gnss_cb_->sv_info_list_cbq_.reset();
+ aidl_gnss_cb_->location_cbq_.reset();
+ }
StartAndCheckLocations(kLocationsToAwait);
// Tolerate 1 less sv status to handle edge cases in reporting.
- int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
+ int sv_info_list_cbq_size = (aidl_gnss_hal_->getInterfaceVersion() == 1)
+ ? gnss_cb_->sv_info_list_cbq_.size()
+ : aidl_gnss_cb_->sv_info_list_cbq_.size();
EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations", sv_info_list_cbq_size,
kLocationsToAwait);
for (int i = 0; i < sv_info_list_cbq_size; ++i) {
- hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
- gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
- for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
- const auto& gnss_sv = sv_info_vec[iSv];
- EXPECT_FALSE((static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
- source_to_blocklist_1.constellation) &&
- (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
- EXPECT_FALSE((static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
- source_to_blocklist_2.constellation) &&
- (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
+ if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+ hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
+ gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
+ for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
+ const auto& gnss_sv = sv_info_vec[iSv];
+ EXPECT_FALSE(
+ (static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
+ source_to_blocklist_1.constellation) &&
+ (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
+ EXPECT_FALSE(
+ (static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
+ source_to_blocklist_2.constellation) &&
+ (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
+ }
+ } else {
+ std::vector<IGnssCallback::GnssSvInfo> sv_info_vec;
+ aidl_gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
+ for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
+ const auto& gnss_sv = sv_info_vec[iSv];
+ EXPECT_FALSE((gnss_sv.constellation == source_to_blocklist_1.constellation) &&
+ (gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX));
+ EXPECT_FALSE((gnss_sv.constellation == source_to_blocklist_2.constellation) &&
+ (gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX));
+ }
}
}
@@ -743,27 +747,47 @@
StopAndClearLocations();
// retry and ensure constellation not used
- gnss_cb_->sv_info_list_cbq_.reset();
-
- gnss_cb_->location_cbq_.reset();
+ if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+ gnss_cb_->sv_info_list_cbq_.reset();
+ gnss_cb_->location_cbq_.reset();
+ } else {
+ aidl_gnss_cb_->sv_info_list_cbq_.reset();
+ aidl_gnss_cb_->location_cbq_.reset();
+ }
StartAndCheckLocations(kLocationsToAwait);
// Tolerate 1 less sv status to handle edge cases in reporting.
- int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
+ int sv_info_list_cbq_size = (aidl_gnss_hal_->getInterfaceVersion() == 1)
+ ? gnss_cb_->sv_info_list_cbq_.size()
+ : aidl_gnss_cb_->sv_info_list_cbq_.size();
EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations", sv_info_list_cbq_size,
kLocationsToAwait);
for (int i = 0; i < sv_info_list_cbq_size; ++i) {
- hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
- gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
- for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
- const auto& gnss_sv = sv_info_vec[iSv];
- EXPECT_FALSE((static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
- source_to_blocklist_1.constellation) &&
- (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
- EXPECT_FALSE((static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
- source_to_blocklist_2.constellation) &&
- (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
+ if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+ hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
+ gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
+ for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
+ const auto& gnss_sv = sv_info_vec[iSv];
+ EXPECT_FALSE(
+ (static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
+ source_to_blocklist_1.constellation) &&
+ (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
+ EXPECT_FALSE(
+ (static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
+ source_to_blocklist_2.constellation) &&
+ (gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
+ }
+ } else {
+ std::vector<IGnssCallback::GnssSvInfo> sv_info_vec;
+ aidl_gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
+ for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
+ const auto& gnss_sv = sv_info_vec[iSv];
+ EXPECT_FALSE((gnss_sv.constellation == source_to_blocklist_1.constellation) &&
+ (gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX));
+ EXPECT_FALSE((gnss_sv.constellation == source_to_blocklist_2.constellation) &&
+ (gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX));
+ }
}
}
@@ -829,7 +853,7 @@
ASSERT_TRUE(status.isOk());
// Set SUPL server host/port
- status = iAGnss->setServer(AGnssType::SUPL, String16("supl.google.com"), 7275);
+ status = iAGnss->setServer(AGnssType::SUPL, std::string("supl.google.com"), 7275);
ASSERT_TRUE(status.isOk());
}
@@ -845,7 +869,7 @@
auto status = aidl_gnss_hal_->getExtensionGnssDebug(&iGnssDebug);
ASSERT_TRUE(status.isOk());
- if (!IsAutomotiveDevice() && gnss_cb_->info_cbq_.calledCount() > 0) {
+ if (!IsAutomotiveDevice()) {
ASSERT_TRUE(iGnssDebug != nullptr);
IGnssDebug::DebugData data;
@@ -903,3 +927,42 @@
status = iGnssVisibilityControl->enableNfwLocationAccess(proxyApps);
ASSERT_TRUE(status.isOk());
}
+
+/*
+ * TestGnssMeasurementSetCallbackWithOptions:
+ * 1. Gets the GnssMeasurementExtension and verifies that it returns a non-null extension.
+ * 2. Sets a GnssMeasurementCallback with intervalMillis option, waits for measurements reported,
+ * and verifies mandatory fields are valid.
+ */
+TEST_P(GnssHalTest, TestGnssMeasurementSetCallbackWithOptions) {
+ if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+ return;
+ }
+ const int kFirstGnssMeasurementTimeoutSeconds = 10;
+ const int kNumMeasurementEvents = 5;
+
+ sp<IGnssMeasurementInterface> iGnssMeasurement;
+ auto status = aidl_gnss_hal_->getExtensionGnssMeasurement(&iGnssMeasurement);
+ ASSERT_TRUE(status.isOk());
+ ASSERT_TRUE(iGnssMeasurement != nullptr);
+
+ auto callback = sp<GnssMeasurementCallbackAidl>::make();
+ IGnssMeasurementInterface::Options options;
+ options.intervalMs = 2000;
+ status = iGnssMeasurement->setCallbackWithOptions(callback, options);
+ ASSERT_TRUE(status.isOk());
+
+ for (int i = 0; i < kNumMeasurementEvents; i++) {
+ GnssData lastMeasurement;
+ ASSERT_TRUE(callback->gnss_data_cbq_.retrieve(lastMeasurement,
+ kFirstGnssMeasurementTimeoutSeconds));
+ EXPECT_EQ(callback->gnss_data_cbq_.calledCount(), i + 1);
+ ASSERT_TRUE(lastMeasurement.measurements.size() > 0);
+
+ // Validity check GnssData fields
+ CheckGnssMeasurementClockFields(lastMeasurement);
+ }
+
+ status = iGnssMeasurement->close();
+ ASSERT_TRUE(status.isOk());
+}
diff --git a/gnss/common/utils/default/Utils.cpp b/gnss/common/utils/default/Utils.cpp
index c339e72..563c6d5 100644
--- a/gnss/common/utils/default/Utils.cpp
+++ b/gnss/common/utils/default/Utils.cpp
@@ -27,14 +27,17 @@
using aidl::android::hardware::gnss::ElapsedRealtime;
using aidl::android::hardware::gnss::GnssClock;
+using aidl::android::hardware::gnss::GnssConstellationType;
using aidl::android::hardware::gnss::GnssData;
using aidl::android::hardware::gnss::GnssLocation;
using aidl::android::hardware::gnss::GnssMeasurement;
using aidl::android::hardware::gnss::IGnss;
using aidl::android::hardware::gnss::IGnssMeasurementCallback;
using aidl::android::hardware::gnss::SatellitePvt;
+using GnssSvInfo = aidl::android::hardware::gnss::IGnssCallback::GnssSvInfo;
+using GnssSvFlags = aidl::android::hardware::gnss::IGnssCallback::GnssSvFlags;
-using GnssSvFlags = V1_0::IGnssCallback::GnssSvFlags;
+using GnssSvFlagsV1_0 = V1_0::IGnssCallback::GnssSvFlags;
using GnssMeasurementFlagsV1_0 = V1_0::IGnssMeasurementCallback::GnssMeasurementFlags;
using GnssMeasurementFlagsV2_1 = V2_1::IGnssMeasurementCallback::GnssMeasurementFlags;
using GnssMeasurementStateV2_0 = V2_0::IGnssMeasurementCallback::GnssMeasurementState;
@@ -144,7 +147,7 @@
GnssData Utils::getMockMeasurement(const bool enableCorrVecOutputs) {
aidl::android::hardware::gnss::GnssSignalType signalType = {
- .constellation = aidl::android::hardware::gnss::GnssConstellationType::GLONASS,
+ .constellation = GnssConstellationType::GLONASS,
.carrierFrequencyHz = 1.59975e+09,
.codeType = aidl::android::hardware::gnss::GnssSignalType::CODE_TYPE_C,
};
@@ -289,6 +292,40 @@
return location;
}
+namespace {
+GnssSvInfo getMockSvInfo(int svid, GnssConstellationType type, float cN0DbHz, float basebandCN0DbHz,
+ float elevationDegrees, float azimuthDegrees, long carrierFrequencyHz) {
+ GnssSvInfo svInfo = {
+ .svid = svid,
+ .constellation = type,
+ .cN0Dbhz = cN0DbHz,
+ .basebandCN0DbHz = basebandCN0DbHz,
+ .elevationDegrees = elevationDegrees,
+ .azimuthDegrees = azimuthDegrees,
+ .carrierFrequencyHz = carrierFrequencyHz,
+ .svFlag = (int)GnssSvFlags::USED_IN_FIX | (int)GnssSvFlags::HAS_EPHEMERIS_DATA |
+ (int)GnssSvFlags::HAS_ALMANAC_DATA | (int)GnssSvFlags::HAS_CARRIER_FREQUENCY};
+ return svInfo;
+}
+} // anonymous namespace
+
+std::vector<GnssSvInfo> Utils::getMockSvInfoList() {
+ std::vector<GnssSvInfo> gnssSvInfoList = {
+ getMockSvInfo(3, GnssConstellationType::GPS, 32.5, 27.5, 59.1, 166.5, kGpsL1FreqHz),
+ getMockSvInfo(5, GnssConstellationType::GPS, 27.0, 22.0, 29.0, 56.5, kGpsL1FreqHz),
+ getMockSvInfo(17, GnssConstellationType::GPS, 30.5, 25.5, 71.0, 77.0, kGpsL5FreqHz),
+ getMockSvInfo(26, GnssConstellationType::GPS, 24.1, 19.1, 28.0, 253.0, kGpsL5FreqHz),
+ getMockSvInfo(5, GnssConstellationType::GLONASS, 20.5, 15.5, 11.5, 116.0, kGloG1FreqHz),
+ getMockSvInfo(17, GnssConstellationType::GLONASS, 21.5, 16.5, 28.5, 186.0,
+ kGloG1FreqHz),
+ getMockSvInfo(18, GnssConstellationType::GLONASS, 28.3, 25.3, 38.8, 69.0, kGloG1FreqHz),
+ getMockSvInfo(10, GnssConstellationType::GLONASS, 25.0, 20.0, 66.0, 247.0,
+ kGloG1FreqHz),
+ getMockSvInfo(3, GnssConstellationType::IRNSS, 22.0, 19.7, 35.0, 112.0, kIrnssL5FreqHz),
+ };
+ return gnssSvInfoList;
+}
+
hidl_vec<GnssSvInfoV2_1> Utils::getMockSvInfoListV2_1() {
GnssSvInfoV1_0 gnssSvInfoV1_0 = Utils::getMockSvInfoV1_0(3, V1_0::GnssConstellationType::GPS,
32.5, 59.1, 166.5, kGpsL1FreqHz);
@@ -360,15 +397,15 @@
GnssSvInfoV1_0 Utils::getMockSvInfoV1_0(int16_t svid, V1_0::GnssConstellationType type,
float cN0DbHz, float elevationDegrees, float azimuthDegrees,
float carrierFrequencyHz) {
- GnssSvInfoV1_0 svInfo = {.svid = svid,
- .constellation = type,
- .cN0Dbhz = cN0DbHz,
- .elevationDegrees = elevationDegrees,
- .azimuthDegrees = azimuthDegrees,
- .carrierFrequencyHz = carrierFrequencyHz,
- .svFlag = GnssSvFlags::USED_IN_FIX | GnssSvFlags::HAS_EPHEMERIS_DATA |
- GnssSvFlags::HAS_ALMANAC_DATA |
- GnssSvFlags::HAS_CARRIER_FREQUENCY};
+ GnssSvInfoV1_0 svInfo = {
+ .svid = svid,
+ .constellation = type,
+ .cN0Dbhz = cN0DbHz,
+ .elevationDegrees = elevationDegrees,
+ .azimuthDegrees = azimuthDegrees,
+ .carrierFrequencyHz = carrierFrequencyHz,
+ .svFlag = GnssSvFlagsV1_0::USED_IN_FIX | GnssSvFlagsV1_0::HAS_EPHEMERIS_DATA |
+ GnssSvFlagsV1_0::HAS_ALMANAC_DATA | GnssSvFlagsV1_0::HAS_CARRIER_FREQUENCY};
return svInfo;
}
diff --git a/gnss/common/utils/default/include/Utils.h b/gnss/common/utils/default/include/Utils.h
index 4500ee6..7065a6fb 100644
--- a/gnss/common/utils/default/include/Utils.h
+++ b/gnss/common/utils/default/include/Utils.h
@@ -35,9 +35,13 @@
const bool enableCorrVecOutputs);
static V2_0::IGnssMeasurementCallback::GnssData getMockMeasurementV2_0();
static V2_1::IGnssMeasurementCallback::GnssData getMockMeasurementV2_1();
+
static aidl::android::hardware::gnss::GnssLocation getMockLocation();
static V2_0::GnssLocation getMockLocationV2_0();
static V1_0::GnssLocation getMockLocationV1_0();
+
+ static std::vector<aidl::android::hardware::gnss::IGnssCallback::GnssSvInfo>
+ getMockSvInfoList();
static hidl_vec<V2_1::IGnssCallback::GnssSvInfo> getMockSvInfoListV2_1();
static V2_1::IGnssCallback::GnssSvInfo getMockSvInfoV2_1(
V2_0::IGnssCallback::GnssSvInfo gnssSvInfoV2_0, float basebandCN0DbHz);
@@ -48,6 +52,7 @@
float cN0DbHz, float elevationDegrees,
float azimuthDegrees,
float carrierFrequencyHz);
+
static hidl_vec<V2_1::IGnssAntennaInfoCallback::GnssAntennaInfo> getMockAntennaInfos();
};
diff --git a/gnss/common/utils/vts/Android.bp b/gnss/common/utils/vts/Android.bp
index 47eff2e..f92e609 100644
--- a/gnss/common/utils/vts/Android.bp
+++ b/gnss/common/utils/vts/Android.bp
@@ -44,6 +44,7 @@
"android.hardware.gnss@2.1",
"android.hardware.gnss.measurement_corrections@1.0",
"android.hardware.gnss.measurement_corrections@1.1",
+ "android.hardware.gnss-V2-cpp",
],
static_libs: [
"libgtest",
diff --git a/gnss/common/utils/vts/Utils.cpp b/gnss/common/utils/vts/Utils.cpp
index be22ff6..06bce9d 100644
--- a/gnss/common/utils/vts/Utils.cpp
+++ b/gnss/common/utils/vts/Utils.cpp
@@ -15,6 +15,7 @@
*/
#include <Utils.h>
+#include <android/hardware/gnss/IGnss.h>
#include "gtest/gtest.h"
#include <cutils/properties.h>
@@ -27,71 +28,14 @@
using namespace measurement_corrections::V1_0;
using V1_0::GnssLocationFlags;
-void Utils::checkLocation(const V1_0::GnssLocation& location, bool check_speed,
- bool check_more_accuracies) {
- EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG);
- EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE);
- if (check_speed) {
- EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_SPEED);
- }
- EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_HORIZONTAL_ACCURACY);
- // New uncertainties available in O must be provided,
- // at least when paired with modern hardware (2017+)
- if (check_more_accuracies) {
- EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY);
- if (check_speed) {
- EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY);
- if (location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) {
- EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY);
- }
- }
- }
- EXPECT_GE(location.latitudeDegrees, -90.0);
- EXPECT_LE(location.latitudeDegrees, 90.0);
- EXPECT_GE(location.longitudeDegrees, -180.0);
- EXPECT_LE(location.longitudeDegrees, 180.0);
- EXPECT_GE(location.altitudeMeters, -1000.0);
- EXPECT_LE(location.altitudeMeters, 30000.0);
- if (check_speed) {
- EXPECT_GE(location.speedMetersPerSec, 0.0);
- EXPECT_LE(location.speedMetersPerSec, 5.0); // VTS tests are stationary.
+template <>
+int64_t Utils::getLocationTimestampMillis(const android::hardware::gnss::GnssLocation& location) {
+ return location.timestampMillis;
+}
- // Non-zero speeds must be reported with an associated bearing
- if (location.speedMetersPerSec > 0.0) {
- EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING);
- }
- }
-
- /*
- * Tolerating some especially high values for accuracy estimate, in case of
- * first fix with especially poor geometry (happens occasionally)
- */
- EXPECT_GT(location.horizontalAccuracyMeters, 0.0);
- EXPECT_LE(location.horizontalAccuracyMeters, 250.0);
-
- /*
- * Some devices may define bearing as -180 to +180, others as 0 to 360.
- * Both are okay & understandable.
- */
- if (location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) {
- EXPECT_GE(location.bearingDegrees, -180.0);
- EXPECT_LE(location.bearingDegrees, 360.0);
- }
- if (location.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY) {
- EXPECT_GT(location.verticalAccuracyMeters, 0.0);
- EXPECT_LE(location.verticalAccuracyMeters, 500.0);
- }
- if (location.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY) {
- EXPECT_GT(location.speedAccuracyMetersPerSecond, 0.0);
- EXPECT_LE(location.speedAccuracyMetersPerSecond, 50.0);
- }
- if (location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY) {
- EXPECT_GT(location.bearingAccuracyDegrees, 0.0);
- EXPECT_LE(location.bearingAccuracyDegrees, 360.0);
- }
-
- // Check timestamp > 1.48e12 (47 years in msec - 1970->2017+)
- EXPECT_GT(location.timestamp, 1.48e12);
+template <>
+int64_t Utils::getLocationTimestampMillis(const V1_0::GnssLocation& location) {
+ return location.timestamp;
}
const MeasurementCorrections Utils::getMockMeasurementCorrections() {
diff --git a/gnss/common/utils/vts/include/Utils.h b/gnss/common/utils/vts/include/Utils.h
index 91c1167..40f31d2 100644
--- a/gnss/common/utils/vts/include/Utils.h
+++ b/gnss/common/utils/vts/include/Utils.h
@@ -21,6 +21,7 @@
#include <android/hardware/gnss/2.0/IGnss.h>
#include <android/hardware/gnss/measurement_corrections/1.0/IMeasurementCorrections.h>
#include <android/hardware/gnss/measurement_corrections/1.1/IMeasurementCorrections.h>
+#include <gtest/gtest.h>
namespace android {
namespace hardware {
@@ -28,8 +29,9 @@
namespace common {
struct Utils {
- static void checkLocation(const V1_0::GnssLocation& location, bool check_speed,
- bool check_more_accuracies);
+ public:
+ template <class T>
+ static void checkLocation(const T& location, bool check_speed, bool check_more_accuracies);
static const measurement_corrections::V1_0::MeasurementCorrections
getMockMeasurementCorrections();
static const measurement_corrections::V1_1::MeasurementCorrections
@@ -39,8 +41,80 @@
V2_0::GnssConstellationType constellation);
static bool isAutomotiveDevice();
+
+ private:
+ template <class T>
+ static int64_t getLocationTimestampMillis(const T&);
};
+template <class T>
+void Utils::checkLocation(const T& location, bool check_speed, bool check_more_accuracies) {
+ EXPECT_TRUE(location.gnssLocationFlags & V1_0::GnssLocationFlags::HAS_LAT_LONG);
+ EXPECT_TRUE(location.gnssLocationFlags & V1_0::GnssLocationFlags::HAS_ALTITUDE);
+ if (check_speed) {
+ EXPECT_TRUE(location.gnssLocationFlags & V1_0::GnssLocationFlags::HAS_SPEED);
+ }
+ EXPECT_TRUE(location.gnssLocationFlags & V1_0::GnssLocationFlags::HAS_HORIZONTAL_ACCURACY);
+ // New uncertainties available in O must be provided,
+ // at least when paired with modern hardware (2017+)
+ if (check_more_accuracies) {
+ EXPECT_TRUE(location.gnssLocationFlags & V1_0::GnssLocationFlags::HAS_VERTICAL_ACCURACY);
+ if (check_speed) {
+ EXPECT_TRUE(location.gnssLocationFlags & V1_0::GnssLocationFlags::HAS_SPEED_ACCURACY);
+ if (location.gnssLocationFlags & V1_0::GnssLocationFlags::HAS_BEARING) {
+ EXPECT_TRUE(location.gnssLocationFlags &
+ V1_0::GnssLocationFlags::HAS_BEARING_ACCURACY);
+ }
+ }
+ }
+ EXPECT_GE(location.latitudeDegrees, -90.0);
+ EXPECT_LE(location.latitudeDegrees, 90.0);
+ EXPECT_GE(location.longitudeDegrees, -180.0);
+ EXPECT_LE(location.longitudeDegrees, 180.0);
+ EXPECT_GE(location.altitudeMeters, -1000.0);
+ EXPECT_LE(location.altitudeMeters, 30000.0);
+ if (check_speed) {
+ EXPECT_GE(location.speedMetersPerSec, 0.0);
+ EXPECT_LE(location.speedMetersPerSec, 5.0); // VTS tests are stationary.
+
+ // Non-zero speeds must be reported with an associated bearing
+ if (location.speedMetersPerSec > 0.0) {
+ EXPECT_TRUE(location.gnssLocationFlags & V1_0::GnssLocationFlags::HAS_BEARING);
+ }
+ }
+
+ /*
+ * Tolerating some especially high values for accuracy estimate, in case of
+ * first fix with especially poor geometry (happens occasionally)
+ */
+ EXPECT_GT(location.horizontalAccuracyMeters, 0.0);
+ EXPECT_LE(location.horizontalAccuracyMeters, 250.0);
+
+ /*
+ * Some devices may define bearing as -180 to +180, others as 0 to 360.
+ * Both are okay & understandable.
+ */
+ if (location.gnssLocationFlags & V1_0::GnssLocationFlags::HAS_BEARING) {
+ EXPECT_GE(location.bearingDegrees, -180.0);
+ EXPECT_LE(location.bearingDegrees, 360.0);
+ }
+ if (location.gnssLocationFlags & V1_0::GnssLocationFlags::HAS_VERTICAL_ACCURACY) {
+ EXPECT_GT(location.verticalAccuracyMeters, 0.0);
+ EXPECT_LE(location.verticalAccuracyMeters, 500.0);
+ }
+ if (location.gnssLocationFlags & V1_0::GnssLocationFlags::HAS_SPEED_ACCURACY) {
+ EXPECT_GT(location.speedAccuracyMetersPerSecond, 0.0);
+ EXPECT_LE(location.speedAccuracyMetersPerSecond, 50.0);
+ }
+ if (location.gnssLocationFlags & V1_0::GnssLocationFlags::HAS_BEARING_ACCURACY) {
+ EXPECT_GT(location.bearingAccuracyDegrees, 0.0);
+ EXPECT_LE(location.bearingAccuracyDegrees, 360.0);
+ }
+
+ // Check timestamp > 1.48e12 (47 years in msec - 1970->2017+)
+ EXPECT_GT(getLocationTimestampMillis(location), 1.48e12);
+}
+
} // namespace common
} // namespace gnss
} // namespace hardware
diff --git a/gnss/common/utils/vts/include/v2_1/GnssCallback.h b/gnss/common/utils/vts/include/v2_1/GnssCallback.h
index ab1375d..09a67de 100644
--- a/gnss/common/utils/vts/include/v2_1/GnssCallback.h
+++ b/gnss/common/utils/vts/include/v2_1/GnssCallback.h
@@ -28,7 +28,6 @@
using android::hardware::gnss::common::GnssCallbackEventQueue;
using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrectionsCallback;
using android::hardware::gnss::V1_0::GnssLocationFlags;
-using android::hardware::gnss::V2_0::GnssConstellationType;
using GnssLocation_1_0 = android::hardware::gnss::V1_0::GnssLocation;
using GnssLocation_2_0 = android::hardware::gnss::V2_0::GnssLocation;
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCapability.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCapability.aidl
index 9f5342e..fdf1100 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCapability.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCapability.aidl
@@ -41,4 +41,5 @@
PROTECTED_CONTENTS = 4,
AUTO_LOW_LATENCY_MODE = 5,
SUSPEND = 6,
+ DISPLAY_DECORATION = 7,
}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCapability.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCapability.aidl
index eacf106..249fed0 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCapability.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCapability.aidl
@@ -75,4 +75,8 @@
* PowerMode.ON_SUSPEND and PowerMode.DOZE_SUSPEND must be supported.
*/
SUSPEND = 6,
+ /**
+ * Indicates that the display supports Composition.DISPLAY_DECORATION.
+ */
+ DISPLAY_DECORATION = 7,
}
diff --git a/health/aidl/Android.bp b/health/aidl/Android.bp
index 6e2f1d4..22bb4fa 100644
--- a/health/aidl/Android.bp
+++ b/health/aidl/Android.bp
@@ -37,7 +37,6 @@
sdk_version: "module_current",
},
ndk: {
- separate_platform_variant: false,
vndk: {
enabled: true,
},
diff --git a/health/aidl/default/Android.bp b/health/aidl/default/Android.bp
index 8aa7638..8eab997 100644
--- a/health/aidl/default/Android.bp
+++ b/health/aidl/default/Android.bp
@@ -120,6 +120,15 @@
},
}
+// Users of libhealth_aidl_impl should use this defaults.
+cc_defaults {
+ name: "libhealth_aidl_impl_user",
+ defaults: [
+ "libhealth_aidl_common_defaults",
+ "libhealth_aidl_charger_defaults",
+ ],
+}
+
// AIDL version of android.hardware.health@2.1-service.
// Default binder service of the health HAL.
cc_defaults {
@@ -127,8 +136,7 @@
relative_install_path: "hw",
vintf_fragments: ["android.hardware.health-service.example.xml"],
defaults: [
- "libhealth_aidl_common_defaults",
- "libhealth_aidl_charger_defaults",
+ "libhealth_aidl_impl_user",
],
static_libs: [
"libhealth_aidl_impl",
diff --git a/ir/aidl/Android.bp b/ir/aidl/Android.bp
index 8741157..a623491 100644
--- a/ir/aidl/Android.bp
+++ b/ir/aidl/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
aidl_interface {
name: "android.hardware.ir",
vendor_available: true,
@@ -25,7 +34,6 @@
sdk_version: "module_current",
},
ndk: {
- separate_platform_variant: false,
vndk: {
// TODO(b/206116595) enable this
enabled: false,
diff --git a/ir/aidl/default/Android.bp b/ir/aidl/default/Android.bp
index 6519664..a4fb439 100644
--- a/ir/aidl/default/Android.bp
+++ b/ir/aidl/default/Android.bp
@@ -13,6 +13,15 @@
// limitations under the License.
// Example binder service of the ir HAL.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
cc_binary {
name: "android.hardware.ir-service.example",
relative_install_path: "hw",
diff --git a/neuralnetworks/1.3/vts/functional/MemoryDomainTests.cpp b/neuralnetworks/1.3/vts/functional/MemoryDomainTests.cpp
index e2fa6e4..af3641a 100644
--- a/neuralnetworks/1.3/vts/functional/MemoryDomainTests.cpp
+++ b/neuralnetworks/1.3/vts/functional/MemoryDomainTests.cpp
@@ -1158,12 +1158,15 @@
auto [buffer, token] = allocateBuffer(preparedModel, {0}, {0}, kTestOperand.dimensions);
if (buffer == nullptr) return;
- Request::MemoryPool sharedMemory = createSharedMemoryPool(kTestOperandDataSize);
- Request::MemoryPool deviceMemory = createDeviceMemoryPool(token);
+ // Use an incompatible dimension and make sure the length matches with the bad dimension.
auto badDimensions = kTestOperand.dimensions;
badDimensions[0] = 2;
+ const uint32_t badTestOperandDataSize = kTestOperandDataSize * 2;
+
+ Request::MemoryPool sharedMemory = createSharedMemoryPool(badTestOperandDataSize);
+ Request::MemoryPool deviceMemory = createDeviceMemoryPool(token);
RequestArgument sharedMemoryArg = {
- .location = {.poolIndex = 0, .offset = 0, .length = kTestOperandDataSize},
+ .location = {.poolIndex = 0, .offset = 0, .length = badTestOperandDataSize},
.dimensions = badDimensions};
RequestArgument deviceMemoryArg = {.location = {.poolIndex = 1}};
RequestArgument deviceMemoryArgWithBadDimensions = {.location = {.poolIndex = 1},
diff --git a/neuralnetworks/OWNERS b/neuralnetworks/OWNERS
index def3ea9..04c5d72 100644
--- a/neuralnetworks/OWNERS
+++ b/neuralnetworks/OWNERS
@@ -1,10 +1,2 @@
# Bug component: 195575
-# Neuralnetworks team
-butlermichael@google.com
-dgross@google.com
-galarragas@google.com
-ianhua@google.com
-jeanluc@google.com
-miaowang@google.com
-pszczepaniak@google.com
-xusongw@google.com
+include platform/packages/modules/NeuralNetworks:/NNAPI_OWNERS # Neuralnetworks team
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataProfileInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataProfileInfo.aidl
index 3342619..c8efea0 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataProfileInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/DataProfileInfo.aidl
@@ -46,8 +46,8 @@
int maxConns;
int waitTime;
boolean enabled;
- android.hardware.radio.data.ApnTypes supportedApnTypesBitmap;
- android.hardware.radio.RadioAccessFamily bearerBitmap;
+ int supportedApnTypesBitmap;
+ int bearerBitmap;
int mtuV4;
int mtuV6;
boolean preferred;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/RadioCapability.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/RadioCapability.aidl
index d5716ac..5aaf5a7 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/RadioCapability.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/RadioCapability.aidl
@@ -36,7 +36,7 @@
parcelable RadioCapability {
int session;
int phase;
- android.hardware.radio.RadioAccessFamily raf;
+ int raf;
String logicalModemUuid;
int status;
const int PHASE_CONFIGURED = 0;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
index c618791..2b70e45 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetwork.aidl
@@ -50,12 +50,12 @@
oneway void getVoiceRegistrationState(in int serial);
oneway void isNrDualConnectivityEnabled(in int serial);
oneway void responseAcknowledgement();
- oneway void setAllowedNetworkTypesBitmap(in int serial, in android.hardware.radio.RadioAccessFamily networkTypeBitmap);
+ oneway void setAllowedNetworkTypesBitmap(in int serial, in int networkTypeBitmap);
oneway void setBandMode(in int serial, in android.hardware.radio.network.RadioBandMode mode);
oneway void setBarringPassword(in int serial, in String facility, in String oldPassword, in String newPassword);
oneway void setCdmaRoamingPreference(in int serial, in android.hardware.radio.network.CdmaRoamingType type);
oneway void setCellInfoListRate(in int serial, in int rate);
- oneway void setIndicationFilter(in int serial, in android.hardware.radio.network.IndicationFilter indicationFilter);
+ oneway void setIndicationFilter(in int serial, in int indicationFilter);
oneway void setLinkCapacityReportingCriteria(in int serial, in int hysteresisMs, in int hysteresisDlKbps, in int hysteresisUlKbps, in int[] thresholdsDownlinkKbps, in int[] thresholdsUplinkKbps, in android.hardware.radio.AccessNetwork accessNetwork);
oneway void setLocationUpdates(in int serial, in boolean enable);
oneway void setNetworkSelectionModeAutomatic(in int serial);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkIndication.aidl
index d135a69..bd03c51 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkIndication.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkIndication.aidl
@@ -44,7 +44,7 @@
oneway void networkScanResult(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.network.NetworkScanResult result);
oneway void networkStateChanged(in android.hardware.radio.RadioIndicationType type);
oneway void nitzTimeReceived(in android.hardware.radio.RadioIndicationType type, in String nitzTime, in long receivedTimeMs, in long ageMs);
- oneway void registrationFailed(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.network.CellIdentity cellIdentity, in String chosenPlmn, in android.hardware.radio.network.Domain domain, in int causeCode, in int additionalCauseCode);
+ oneway void registrationFailed(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.network.CellIdentity cellIdentity, in String chosenPlmn, in int domain, in int causeCode, in int additionalCauseCode);
oneway void restrictedStateChanged(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.network.PhoneRestrictedState state);
oneway void suppSvcNotify(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.network.SuppSvcNotification suppSvc);
oneway void voiceRadioTechChanged(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.RadioTechnology rat);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
index 8cf4c31..5f6c736 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/IRadioNetworkResponse.aidl
@@ -35,7 +35,7 @@
@VintfStability
interface IRadioNetworkResponse {
oneway void acknowledgeRequest(in int serial);
- oneway void getAllowedNetworkTypesBitmapResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.RadioAccessFamily networkTypeBitmap);
+ oneway void getAllowedNetworkTypesBitmapResponse(in android.hardware.radio.RadioResponseInfo info, in int networkTypeBitmap);
oneway void getAvailableBandModesResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.RadioBandMode[] bandModes);
oneway void getAvailableNetworksResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.OperatorInfo[] networkInfos);
oneway void getBarringInfoResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.CellIdentity cellIdentity, in android.hardware.radio.network.BarringInfo[] barringInfos);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyNumber.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyNumber.aidl
index 4f415ee..39bcf1a 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyNumber.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/EmergencyNumber.aidl
@@ -37,7 +37,7 @@
String number;
String mcc;
String mnc;
- android.hardware.radio.voice.EmergencyServiceCategory categories;
+ int categories;
String[] urns;
int sources;
const int SOURCE_NETWORK_SIGNALING = 1;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoice.aidl b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoice.aidl
index 68c82fa..34d155a 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoice.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.voice/current/android/hardware/radio/voice/IRadioVoice.aidl
@@ -37,7 +37,7 @@
oneway void acceptCall(in int serial);
oneway void conference(in int serial);
oneway void dial(in int serial, in android.hardware.radio.voice.Dial dialInfo);
- oneway void emergencyDial(in int serial, in android.hardware.radio.voice.Dial dialInfo, in android.hardware.radio.voice.EmergencyServiceCategory categories, in String[] urns, in android.hardware.radio.voice.EmergencyCallRouting routing, in boolean hasKnownUserIntentEmergency, in boolean isTesting);
+ oneway void emergencyDial(in int serial, in android.hardware.radio.voice.Dial dialInfo, in int categories, in String[] urns, in android.hardware.radio.voice.EmergencyCallRouting routing, in boolean hasKnownUserIntentEmergency, in boolean isTesting);
oneway void exitEmergencyCallbackMode(in int serial);
oneway void explicitCallTransfer(in int serial);
oneway void getCallForwardStatus(in int serial, in android.hardware.radio.voice.CallForwardInfo callInfo);
diff --git a/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl b/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl
index a1c3c27..b5cf633 100644
--- a/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl
+++ b/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl
@@ -42,7 +42,13 @@
*/
String eid;
/**
- * PortInfo contains the ICCID, logical slot ID, and port state
+ * PortInfo contains the ICCID, logical slot ID, and port state.
+ * Cardstate has no relationship with whether the slot is active or inactive. Should always
+ * report up at least 1 port otherwise the logicalSlotIndex and portActive info will be lost.
+ * For example, the pSIM can be removed, but the slot can still be active. In that case, the
+ * SIM_STATUS reported for the corresponding logical stack will show CARDSTATE_ABSENT.
+ * Similarly, even if there is no profile enabled on the eSIM, that port can still be the
+ * active port in the slot mapping.
*/
SimPortInfo[] portInfo;
}
diff --git a/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl b/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl
index 0f06119..7360202 100644
--- a/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl
+++ b/radio/aidl/android/hardware/radio/data/DataProfileInfo.aidl
@@ -93,11 +93,11 @@
/**
* Supported APN types bitmap. See ApnTypes for the value of each bit.
*/
- ApnTypes supportedApnTypesBitmap;
+ int supportedApnTypesBitmap;
/**
* The bearer bitmap. See RadioAccessFamily for the value of each bit.
*/
- RadioAccessFamily bearerBitmap;
+ int bearerBitmap;
/**
* Maximum transmission unit (MTU) size in bytes for IPv4.
*/
diff --git a/radio/aidl/android/hardware/radio/modem/RadioCapability.aidl b/radio/aidl/android/hardware/radio/modem/RadioCapability.aidl
index b7b8ef3..9bd5f21 100644
--- a/radio/aidl/android/hardware/radio/modem/RadioCapability.aidl
+++ b/radio/aidl/android/hardware/radio/modem/RadioCapability.aidl
@@ -71,7 +71,7 @@
/**
* 32-bit bitmap of RadioAccessFamily.
*/
- RadioAccessFamily raf;
+ int raf;
/**
* A UUID typically "com.xxxx.lmX" where X is the logical modem.
* RadioConst:MAX_UUID_LENGTH is the max length.
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
index aaf432a..7a22a9a 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
@@ -195,7 +195,7 @@
*
* Response function is IRadioNetworkResponse.setAllowedNetworkTypesBitmapResponse()
*/
- void setAllowedNetworkTypesBitmap(in int serial, in RadioAccessFamily networkTypeBitmap);
+ void setAllowedNetworkTypesBitmap(in int serial, in int networkTypeBitmap);
/**
* Assign a specified band for RF configuration.
@@ -253,7 +253,7 @@
*
* Response function is IRadioNetworkResponse.setIndicationFilterResponse()
*/
- void setIndicationFilter(in int serial, in IndicationFilter indicationFilter);
+ void setIndicationFilter(in int serial, in int indicationFilter);
/**
* Sets the link capacity reporting criteria. The resulting reporting criteria are the AND of
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl
index ba7610d..6863ac3 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl
@@ -136,8 +136,8 @@
* include the time spend in sleep / low power states. If it can not be guaranteed,
* there must not be any caching done at the modem and should fill in 0 for ageMs
*/
- void nitzTimeReceived(in RadioIndicationType type, in String nitzTime,
- in long receivedTimeMs, in long ageMs);
+ void nitzTimeReceived(
+ in RadioIndicationType type, in String nitzTime, in long receivedTimeMs, in long ageMs);
/**
* Report that Registration or a Location/Routing/Tracking Area update has failed.
@@ -165,7 +165,7 @@
* MAX_INT if this value is unused.
*/
void registrationFailed(in RadioIndicationType type, in CellIdentity cellIdentity,
- in String chosenPlmn, in Domain domain, in int causeCode, in int additionalCauseCode);
+ in String chosenPlmn, in int domain, in int causeCode, in int additionalCauseCode);
/**
* Indicates a restricted state change (eg, for Domain Specific Access Control).
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
index 30f4221..e650321 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
@@ -62,8 +62,7 @@
* RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
*/
- void getAllowedNetworkTypesBitmapResponse(
- in RadioResponseInfo info, in RadioAccessFamily networkTypeBitmap);
+ void getAllowedNetworkTypesBitmapResponse(in RadioResponseInfo info, in int networkTypeBitmap);
/**
* @param info Response info struct containing response type, serial no. and error
diff --git a/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl b/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl
index c731caf..7923b14 100644
--- a/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl
+++ b/radio/aidl/android/hardware/radio/sim/IRadioSim.aidl
@@ -205,6 +205,12 @@
* Open a new logical channel and select the given application. This command
* reflects TS 27.007 "open logical channel" operation (+CCHO).
*
+ * For MEP-A(Multiple enabled profile), only dedicated port 0 is ISDR selectable.
+ * e.g., Port0 - for ISDR access and Port1/Port2 - the currently active ports/subscriptions.
+ * Port 0 should be transparent to AP and iccLogicalChannel API should remain the same.
+ * Even if the ISDR request comes over port1 or port2, Modem would just internally convert the
+ * portID to port0 and add the real port index as the payload of MANAGE_CHANNEL command.
+ *
* @param serial Serial number of request.
* @param aid AID value, See ETSI 102.221 and 101.220.
* @param p2 P2 value, described in ISO 7816-4. Ignore if equal to RadioConst:P2_CONSTANT_NO_P2
diff --git a/radio/aidl/android/hardware/radio/voice/EmergencyNumber.aidl b/radio/aidl/android/hardware/radio/voice/EmergencyNumber.aidl
index aa4dde2..ddc5d76 100644
--- a/radio/aidl/android/hardware/radio/voice/EmergencyNumber.aidl
+++ b/radio/aidl/android/hardware/radio/voice/EmergencyNumber.aidl
@@ -78,7 +78,7 @@
* The bitfield of EmergencyServiceCategory(s). See EmergencyServiceCategory for the value of
* each bit.
*/
- EmergencyServiceCategory categories;
+ int categories;
/**
* The list of emergency Uniform Resource Names (URN).
*/
diff --git a/radio/aidl/android/hardware/radio/voice/IRadioVoice.aidl b/radio/aidl/android/hardware/radio/voice/IRadioVoice.aidl
index a012be4..b25e63d 100644
--- a/radio/aidl/android/hardware/radio/voice/IRadioVoice.aidl
+++ b/radio/aidl/android/hardware/radio/voice/IRadioVoice.aidl
@@ -117,9 +117,9 @@
*
* Response function is IRadioVoiceResponse.emergencyDialResponse()
*/
- void emergencyDial(in int serial, in Dial dialInfo, in EmergencyServiceCategory categories,
- in String[] urns, in EmergencyCallRouting routing,
- in boolean hasKnownUserIntentEmergency, in boolean isTesting);
+ void emergencyDial(in int serial, in Dial dialInfo, in int categories, in String[] urns,
+ in EmergencyCallRouting routing, in boolean hasKnownUserIntentEmergency,
+ in boolean isTesting);
/**
* Request the radio's system selection module to exit emergency callback mode. Radio must not
diff --git a/radio/aidl/compat/libradiocompat/RadioResponse.cpp b/radio/aidl/compat/libradiocompat/RadioResponse.cpp
index dbeb68a..dab70cc 100644
--- a/radio/aidl/compat/libradiocompat/RadioResponse.cpp
+++ b/radio/aidl/compat/libradiocompat/RadioResponse.cpp
@@ -26,7 +26,10 @@
Return<void> RadioResponse::acknowledgeRequest(int32_t serial) {
LOG_CALL << serial;
- // TODO(b/203699028): send to correct requestor or confirm if spam is not a problem
+ /* We send ACKs to all callbacks instead of the one requested it to make implementation simpler.
+ * If it turns out to be a problem, we would have to track where serials come from and make sure
+ * this tracking data (e.g. a map) doesn't grow indefinitely.
+ */
if (mDataCb) mDataCb.get()->acknowledgeRequest(serial);
if (mMessagingCb) mMessagingCb.get()->acknowledgeRequest(serial);
if (mModemCb) mModemCb.get()->acknowledgeRequest(serial);
diff --git a/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp b/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp
index 5b22dbe..b450418 100644
--- a/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp
+++ b/radio/aidl/compat/libradiocompat/config/RadioConfig.cpp
@@ -20,6 +20,8 @@
#include "debug.h"
#include "structs.h"
+#include "collections.h"
+
#define RADIO_MODULE "Config"
namespace android::hardware::radio::compat {
diff --git a/radio/aidl/compat/libradiocompat/config/structs.cpp b/radio/aidl/compat/libradiocompat/config/structs.cpp
index 9ba5623..39ad944 100644
--- a/radio/aidl/compat/libradiocompat/config/structs.cpp
+++ b/radio/aidl/compat/libradiocompat/config/structs.cpp
@@ -24,14 +24,11 @@
namespace aidl = ::aidl::android::hardware::radio::config;
-hidl_vec<uint32_t> toHidl(const std::vector<aidl::SlotPortMapping>& slotMap) {
- hidl_vec<uint32_t> out(slotMap.size());
- for (const auto& el : slotMap) {
- CHECK_GE(el.portId, 0);
- CHECK_LT(static_cast<size_t>(el.portId), out.size());
- out[el.portId] = el.physicalSlotId;
+uint32_t toHidl(const aidl::SlotPortMapping& slotPortMapping) {
+ if (slotPortMapping.portId != 0) {
+ LOG(ERROR) << "Port ID " << slotPortMapping.portId << " != 0 not supported by HIDL HAL";
}
- return out;
+ return slotPortMapping.physicalSlotId;
}
aidl::SimSlotStatus toAidl(const config::V1_0::SimSlotStatus& sst) {
diff --git a/radio/aidl/compat/libradiocompat/config/structs.h b/radio/aidl/compat/libradiocompat/config/structs.h
index b8a0385..6ea4e4a 100644
--- a/radio/aidl/compat/libradiocompat/config/structs.h
+++ b/radio/aidl/compat/libradiocompat/config/structs.h
@@ -23,8 +23,7 @@
namespace android::hardware::radio::compat {
-hidl_vec<uint32_t> //
-toHidl(const std::vector<aidl::android::hardware::radio::config::SlotPortMapping>& slotMap);
+uint32_t toHidl(const aidl::android::hardware::radio::config::SlotPortMapping& slotPortMapping);
aidl::android::hardware::radio::config::SimSlotStatus //
toAidl(const config::V1_0::SimSlotStatus& sst);
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
index ec76300..1731b78 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
@@ -41,9 +41,8 @@
::ndk::ScopedAStatus getVoiceRegistrationState(int32_t serial) override;
::ndk::ScopedAStatus isNrDualConnectivityEnabled(int32_t serial) override;
::ndk::ScopedAStatus responseAcknowledgement() override;
- ::ndk::ScopedAStatus setAllowedNetworkTypesBitmap(
- int32_t serial,
- ::aidl::android::hardware::radio::RadioAccessFamily networkTypeBitmap) override;
+ ::ndk::ScopedAStatus setAllowedNetworkTypesBitmap(int32_t serial,
+ int32_t networkTypeBitmap) override;
::ndk::ScopedAStatus setBandMode(
int32_t serial, ::aidl::android::hardware::radio::network::RadioBandMode mode) override;
::ndk::ScopedAStatus setBarringPassword(int32_t serial, const std::string& facility,
@@ -53,9 +52,7 @@
int32_t serial,
::aidl::android::hardware::radio::network::CdmaRoamingType type) override;
::ndk::ScopedAStatus setCellInfoListRate(int32_t serial, int32_t rate) override;
- ::ndk::ScopedAStatus setIndicationFilter(
- int32_t serial,
- ::aidl::android::hardware::radio::network::IndicationFilter indicationFilter) override;
+ ::ndk::ScopedAStatus setIndicationFilter(int32_t serial, int32_t indicationFilter) override;
::ndk::ScopedAStatus setLinkCapacityReportingCriteria(
int32_t serial, int32_t hysteresisMs, int32_t hysteresisDlKbps,
int32_t hysteresisUlKbps, const std::vector<int32_t>& thresholdsDownlinkKbps,
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioVoice.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioVoice.h
index 5839e3a..a0e1e82 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioVoice.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioVoice.h
@@ -31,8 +31,7 @@
int32_t serial, const ::aidl::android::hardware::radio::voice::Dial& dialInfo) override;
::ndk::ScopedAStatus emergencyDial(
int32_t serial, const ::aidl::android::hardware::radio::voice::Dial& dialInfo,
- ::aidl::android::hardware::radio::voice::EmergencyServiceCategory categories,
- const std::vector<std::string>& urns,
+ int32_t categories, const std::vector<std::string>& urns,
::aidl::android::hardware::radio::voice::EmergencyCallRouting routing,
bool hasKnownUserIntentEmergency, bool isTesting) override;
::ndk::ScopedAStatus exitEmergencyCallbackMode(int32_t serial) override;
diff --git a/radio/aidl/compat/libradiocompat/modem/structs.cpp b/radio/aidl/compat/libradiocompat/modem/structs.cpp
index 53d5753..69e651b 100644
--- a/radio/aidl/compat/libradiocompat/modem/structs.cpp
+++ b/radio/aidl/compat/libradiocompat/modem/structs.cpp
@@ -25,7 +25,6 @@
namespace android::hardware::radio::compat {
using ::aidl::android::hardware::radio::AccessNetwork;
-using ::aidl::android::hardware::radio::RadioAccessFamily;
using ::aidl::android::hardware::radio::RadioTechnology;
namespace aidl = ::aidl::android::hardware::radio::modem;
@@ -40,7 +39,7 @@
return {
.session = capa.session,
.phase = static_cast<int32_t>(capa.phase),
- .raf = RadioAccessFamily(capa.raf),
+ .raf = static_cast<int32_t>(capa.raf),
.logicalModemUuid = capa.logicalModemUuid,
.status = static_cast<int32_t>(capa.status),
};
diff --git a/radio/aidl/compat/libradiocompat/network/RadioIndication-network.cpp b/radio/aidl/compat/libradiocompat/network/RadioIndication-network.cpp
index d4cbdbc..4eb99f7 100644
--- a/radio/aidl/compat/libradiocompat/network/RadioIndication-network.cpp
+++ b/radio/aidl/compat/libradiocompat/network/RadioIndication-network.cpp
@@ -208,8 +208,8 @@
const hidl_string& chosenPlmn, hidl_bitfield<V1_5::Domain> domain, int32_t causeCode,
int32_t additionalCauseCode) {
LOG_CALL << type;
- networkCb()->registrationFailed(toAidl(type), toAidl(cellIdentity), chosenPlmn,
- aidl::Domain(domain), causeCode, additionalCauseCode);
+ networkCb()->registrationFailed(toAidl(type), toAidl(cellIdentity), chosenPlmn, domain,
+ causeCode, additionalCauseCode);
return {};
}
diff --git a/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp b/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
index 8bfa0bb..22b9ede 100644
--- a/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
+++ b/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
@@ -28,7 +28,6 @@
namespace android::hardware::radio::compat {
using ::aidl::android::hardware::radio::AccessNetwork;
-using ::aidl::android::hardware::radio::RadioAccessFamily;
using ::ndk::ScopedAStatus;
namespace aidl = ::aidl::android::hardware::radio::network;
constexpr auto ok = &ScopedAStatus::ok;
@@ -161,7 +160,7 @@
return ok();
}
-ScopedAStatus RadioNetwork::setAllowedNetworkTypesBitmap(int32_t serial, RadioAccessFamily ntype) {
+ScopedAStatus RadioNetwork::setAllowedNetworkTypesBitmap(int32_t serial, int32_t ntype) {
LOG_CALL << serial;
const auto raf = toHidlBitfield<V1_4::RadioAccessFamily>(ntype);
if (mHal1_6) {
@@ -197,7 +196,7 @@
return ok();
}
-ScopedAStatus RadioNetwork::setIndicationFilter(int32_t serial, aidl::IndicationFilter indFilter) {
+ScopedAStatus RadioNetwork::setIndicationFilter(int32_t serial, int32_t indFilter) {
LOG_CALL << serial;
mHal1_5->setIndicationFilter_1_5(serial, toHidlBitfield<V1_5::IndicationFilter>(indFilter));
return ok();
@@ -255,7 +254,13 @@
ScopedAStatus RadioNetwork::setSignalStrengthReportingCriteria(
int32_t serial, const std::vector<aidl::SignalThresholdInfo>& infos) {
LOG_CALL << serial;
- // TODO(b/203699028): how about other infos?
+ if (infos.size() == 0) {
+ LOG(ERROR) << "Threshold info array is empty - dropping setSignalStrengthReportingCriteria";
+ return ok();
+ }
+ if (infos.size() > 1) {
+ LOG(WARNING) << "Multi-element reporting criteria are not supported with HIDL HAL";
+ }
mHal1_5->setSignalStrengthReportingCriteria_1_5(serial, toHidl(infos[0]),
V1_5::AccessNetwork(infos[0].ran));
return ok();
@@ -292,18 +297,17 @@
return ok();
}
-// TODO(b/210498497): is there a cleaner way to send a response back to Android, even though these
-// methods must never be called?
-ScopedAStatus RadioNetwork::setUsageSetting(
- int32_t ser, ::aidl::android::hardware::radio::network::UsageSetting) {
- LOG_CALL << ser;
+ScopedAStatus RadioNetwork::setUsageSetting(int32_t serial, aidl::UsageSetting) {
+ LOG_CALL << serial;
LOG(ERROR) << "setUsageSetting is unsupported by HIDL HALs";
+ respond()->setUsageSettingResponse(notSupported(serial));
return ok();
}
-ScopedAStatus RadioNetwork::getUsageSetting(int32_t ser) {
- LOG_CALL << ser;
+ScopedAStatus RadioNetwork::getUsageSetting(int32_t serial) {
+ LOG_CALL << serial;
LOG(ERROR) << "getUsageSetting is unsupported by HIDL HALs";
+ respond()->getUsageSettingResponse(notSupported(serial), {}); // {} = neither voice nor data
return ok();
}
diff --git a/radio/aidl/compat/libradiocompat/network/RadioResponse-network.cpp b/radio/aidl/compat/libradiocompat/network/RadioResponse-network.cpp
index bab1d4a..5a98eb2 100644
--- a/radio/aidl/compat/libradiocompat/network/RadioResponse-network.cpp
+++ b/radio/aidl/compat/libradiocompat/network/RadioResponse-network.cpp
@@ -27,7 +27,6 @@
namespace android::hardware::radio::compat {
-using ::aidl::android::hardware::radio::RadioAccessFamily;
using ::aidl::android::hardware::radio::RadioTechnology;
using ::aidl::android::hardware::radio::RadioTechnologyFamily;
namespace aidl = ::aidl::android::hardware::radio::network;
@@ -44,16 +43,14 @@
const V1_6::RadioResponseInfo& info,
hidl_bitfield<V1_4::RadioAccessFamily> networkTypeBitmap) {
LOG_CALL << info.serial;
- networkCb()->getAllowedNetworkTypesBitmapResponse(toAidl(info),
- RadioAccessFamily(networkTypeBitmap));
+ networkCb()->getAllowedNetworkTypesBitmapResponse(toAidl(info), networkTypeBitmap);
return {};
}
Return<void> RadioResponse::getPreferredNetworkTypeResponse(const V1_0::RadioResponseInfo& info,
V1_0::PreferredNetworkType nwType) {
LOG_CALL << info.serial;
- networkCb()->getAllowedNetworkTypesBitmapResponse( //
- toAidl(info), RadioAccessFamily(getRafFromNetworkType(nwType)));
+ networkCb()->getAllowedNetworkTypesBitmapResponse(toAidl(info), getRafFromNetworkType(nwType));
return {};
}
diff --git a/radio/aidl/compat/libradiocompat/sim/structs.cpp b/radio/aidl/compat/libradiocompat/sim/structs.cpp
index 97a21a1..bfbff02 100644
--- a/radio/aidl/compat/libradiocompat/sim/structs.cpp
+++ b/radio/aidl/compat/libradiocompat/sim/structs.cpp
@@ -173,7 +173,6 @@
.atr = status.base.base.atr,
.iccid = status.base.base.iccid,
.eid = status.base.eid,
- // TODO(b/203699028): we don't know portId here (but we can get it from RadioConfig)
.slotMap = {static_cast<int32_t>(status.base.base.physicalSlotId), 0},
};
}
diff --git a/radio/aidl/compat/libradiocompat/voice/RadioVoice.cpp b/radio/aidl/compat/libradiocompat/voice/RadioVoice.cpp
index 7b1d1fa..71d1a56 100644
--- a/radio/aidl/compat/libradiocompat/voice/RadioVoice.cpp
+++ b/radio/aidl/compat/libradiocompat/voice/RadioVoice.cpp
@@ -53,7 +53,7 @@
}
ScopedAStatus RadioVoice::emergencyDial( //
- int32_t serial, const aidl::Dial& info, aidl::EmergencyServiceCategory categories,
+ int32_t serial, const aidl::Dial& info, int32_t categories,
const std::vector<std::string>& urns, aidl::EmergencyCallRouting routing,
bool knownUserIntentEmerg, bool isTesting) {
LOG_CALL << serial;
diff --git a/radio/aidl/compat/libradiocompat/voice/structs.cpp b/radio/aidl/compat/libradiocompat/voice/structs.cpp
index ae6342e..254ea20 100644
--- a/radio/aidl/compat/libradiocompat/voice/structs.cpp
+++ b/radio/aidl/compat/libradiocompat/voice/structs.cpp
@@ -147,7 +147,7 @@
.number = num.number,
.mcc = num.mcc,
.mnc = num.mnc,
- .categories = aidl::EmergencyServiceCategory(num.categories),
+ .categories = num.categories,
.urns = toAidl(num.urns),
.sources = num.sources,
};
diff --git a/radio/aidl/vts/Android.bp b/radio/aidl/vts/Android.bp
index 935d2e5..8060e4b 100644
--- a/radio/aidl/vts/Android.bp
+++ b/radio/aidl/vts/Android.bp
@@ -29,6 +29,9 @@
],
srcs: [
"radio_aidl_hal_utils.cpp",
+ "radio_config_indication.cpp",
+ "radio_config_response.cpp",
+ "radio_config_test.cpp",
"radio_data_indication.cpp",
"radio_data_response.cpp",
"radio_data_test.cpp",
diff --git a/radio/aidl/vts/VtsHalRadioTargetTest.cpp b/radio/aidl/vts/VtsHalRadioTargetTest.cpp
index e829f8e..1ebc6af 100644
--- a/radio/aidl/vts/VtsHalRadioTargetTest.cpp
+++ b/radio/aidl/vts/VtsHalRadioTargetTest.cpp
@@ -16,6 +16,7 @@
#include <android/binder_process.h>
+#include "radio_config_utils.h"
#include "radio_data_utils.h"
#include "radio_messaging_utils.h"
#include "radio_modem_utils.h"
@@ -23,6 +24,12 @@
#include "radio_sim_utils.h"
#include "radio_voice_utils.h"
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioConfigTest);
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, RadioConfigTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IRadioConfig::descriptor)),
+ android::PrintInstanceNameToString);
+
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioDataTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, RadioDataTest,
diff --git a/radio/aidl/vts/radio_aidl_hal_utils.cpp b/radio/aidl/vts/radio_aidl_hal_utils.cpp
index 14a16c0..dc61a3c 100644
--- a/radio/aidl/vts/radio_aidl_hal_utils.cpp
+++ b/radio/aidl/vts/radio_aidl_hal_utils.cpp
@@ -18,12 +18,14 @@
#include "radio_aidl_hal_utils.h"
#include <iostream>
#include "VtsCoreUtil.h"
-
-using namespace aidl::android::hardware::radio::network;
+#include "radio_config_utils.h"
+#include "radio_sim_utils.h"
#define WAIT_TIMEOUT_PERIOD 75
-aidl::android::hardware::radio::sim::CardStatus cardStatus = {};
+sim::CardStatus cardStatus = {};
+int serial = 0;
+int count_ = 0;
int GetRandomSerialNumber() {
return rand();
@@ -103,23 +105,33 @@
RegState::UNKNOWN_EM == state;
}
+bool stringEndsWith(std::string const& string, std::string const& end) {
+ if (string.size() >= end.size()) {
+ return (0 == string.compare(string.size() - end.size() - 1, end.size(), end));
+ } else {
+ return false;
+ }
+}
+
bool isServiceValidForDeviceConfiguration(std::string& serviceName) {
if (isSsSsEnabled()) {
// Device is configured as SSSS.
- if (serviceName != RADIO_SERVICE_SLOT1_NAME) {
+ if (stringEndsWith(serviceName, RADIO_SERVICE_SLOT1_NAME)) {
ALOGI("%s instance is not valid for SSSS device.", serviceName.c_str());
return false;
}
} else if (isDsDsEnabled()) {
// Device is configured as DSDS.
- if (serviceName != RADIO_SERVICE_SLOT1_NAME && serviceName != RADIO_SERVICE_SLOT2_NAME) {
+ if (!stringEndsWith(serviceName, RADIO_SERVICE_SLOT1_NAME) &&
+ !stringEndsWith(serviceName, RADIO_SERVICE_SLOT2_NAME)) {
ALOGI("%s instance is not valid for DSDS device.", serviceName.c_str());
return false;
}
} else if (isTsTsEnabled()) {
// Device is configured as TSTS.
- if (serviceName != RADIO_SERVICE_SLOT1_NAME && serviceName != RADIO_SERVICE_SLOT2_NAME &&
- serviceName != RADIO_SERVICE_SLOT3_NAME) {
+ if (!stringEndsWith(serviceName, RADIO_SERVICE_SLOT1_NAME) &&
+ !stringEndsWith(serviceName, RADIO_SERVICE_SLOT2_NAME) &&
+ !stringEndsWith(serviceName, RADIO_SERVICE_SLOT3_NAME)) {
ALOGI("%s instance is not valid for TSTS device.", serviceName.c_str());
return false;
}
@@ -130,7 +142,7 @@
/*
* Notify that the response message is received.
*/
-void RadioResponseWaiter::notify(int receivedSerial) {
+void RadioServiceTest::notify(int receivedSerial) {
std::unique_lock<std::mutex> lock(mtx_);
if (serial == receivedSerial) {
count_++;
@@ -141,7 +153,7 @@
/*
* Wait till the response message is notified or till WAIT_TIMEOUT_PERIOD.
*/
-std::cv_status RadioResponseWaiter::wait() {
+std::cv_status RadioServiceTest::wait() {
std::unique_lock<std::mutex> lock(mtx_);
std::cv_status status = std::cv_status::no_timeout;
auto now = std::chrono::system_clock::now();
@@ -158,19 +170,37 @@
/**
* Specific features on the Radio HAL rely on Radio HAL Capabilities.
* The VTS test related to those features must not run if the related capability is disabled.
- * Typical usage within VTS: if (getRadioHalCapabilities()) return;
+ * Typical usage within VTS:
+ * if (getRadioHalCapabilities()) return;
*/
-bool RadioResponseWaiter::getRadioHalCapabilities() {
- // TODO(b/210712359): implement after RadioConfig VTS is created
- /**
- // Get HalDeviceCapabilities from the radio config
- std::shared_ptr<RadioConfigResponse> radioConfigRsp = new (std::nothrow)
- RadioConfigResponse(*this); radioConfig->setResponseFunctions(radioConfigRsp, nullptr); serial =
- GetRandomSerialNumber();
-
- radioConfig->getHalDeviceCapabilities(serial);
+bool RadioServiceTest::getRadioHalCapabilities() {
+ // Get HalDeviceCapabilities from RadioConfig
+ std::shared_ptr<RadioConfigResponse> radioConfigRsp =
+ ndk::SharedRefBase::make<RadioConfigResponse>(*this);
+ std::shared_ptr<RadioConfigIndication> radioConfigInd =
+ ndk::SharedRefBase::make<RadioConfigIndication>(*this);
+ radio_config->setResponseFunctions(radioConfigRsp, radioConfigInd);
+ serial = GetRandomSerialNumber();
+ radio_config->getHalDeviceCapabilities(serial);
EXPECT_EQ(std::cv_status::no_timeout, wait());
return radioConfigRsp->modemReducedFeatureSet1;
- **/
- return true;
-}
\ No newline at end of file
+}
+
+/**
+ * Some VTS tests require the SIM card status to be present before running.
+ * Update the SIM card status, which can be accessed via the extern cardStatus.
+ */
+void RadioServiceTest::updateSimCardStatus() {
+ // Update CardStatus from RadioSim
+ std::shared_ptr<RadioSimResponse> radioSimRsp =
+ ndk::SharedRefBase::make<RadioSimResponse>(*this);
+ std::shared_ptr<RadioSimIndication> radioSimInd =
+ ndk::SharedRefBase::make<RadioSimIndication>(*this);
+ radio_sim->setResponseFunctions(radioSimRsp, radioSimInd);
+ serial = GetRandomSerialNumber();
+ radio_sim->getIccCardStatus(serial);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioSimRsp->rspInfo.type);
+ EXPECT_EQ(serial, radioSimRsp->rspInfo.serial);
+ EXPECT_EQ(RadioError::NONE, radioSimRsp->rspInfo.error);
+}
diff --git a/radio/aidl/vts/radio_aidl_hal_utils.h b/radio/aidl/vts/radio_aidl_hal_utils.h
index 2f31fa8..414ffbc 100644
--- a/radio/aidl/vts/radio_aidl_hal_utils.h
+++ b/radio/aidl/vts/radio_aidl_hal_utils.h
@@ -19,15 +19,20 @@
#include <aidl/Gtest.h>
#include <aidl/Vintf.h>
#include <aidl/android/hardware/radio/RadioError.h>
+#include <aidl/android/hardware/radio/config/IRadioConfig.h>
#include <aidl/android/hardware/radio/network/RegState.h>
#include <aidl/android/hardware/radio/sim/CardStatus.h>
+#include <aidl/android/hardware/radio/sim/IRadioSim.h>
#include <utils/Log.h>
#include <vector>
using namespace aidl::android::hardware::radio;
+using aidl::android::hardware::radio::network::RegState;
using aidl::android::hardware::radio::sim::CardStatus;
extern CardStatus cardStatus;
+extern int serial;
+extern int count_;
/*
* MACRO used to skip test case when radio response return error REQUEST_NOT_SUPPORTED
@@ -102,12 +107,12 @@
/*
* Check if voice status is in emergency only.
*/
-bool isVoiceEmergencyOnly(aidl::android::hardware::radio::network::RegState state);
+bool isVoiceEmergencyOnly(RegState state);
/*
* Check if voice status is in service.
*/
-bool isVoiceInService(aidl::android::hardware::radio::network::RegState state);
+bool isVoiceInService(RegState state);
/*
* Check if service is valid for device configuration
@@ -115,26 +120,25 @@
bool isServiceValidForDeviceConfiguration(std::string& serviceName);
/**
- * Used when waiting for an asynchronous response from the HAL.
+ * RadioServiceTest base class
*/
-class RadioResponseWaiter {
+class RadioServiceTest {
protected:
std::mutex mtx_;
std::condition_variable cv_;
- int count_;
+ std::shared_ptr<config::IRadioConfig> radio_config;
+ std::shared_ptr<sim::IRadioSim> radio_sim;
public:
- /* Serial number for radio request */
- int serial;
-
/* Used as a mechanism to inform the test about data/event callback */
void notify(int receivedSerial);
/* Test code calls this function to wait for response */
std::cv_status wait();
- // TODO(b/210712359): this probably isn't the best place to put this, but it works for now
- // since all RadioXTest extend RadioResponseWaiter
- /* Used to get the radio HAL capabilities */
+ /* Get the radio HAL capabilities */
bool getRadioHalCapabilities();
+
+ /* Update SIM card status */
+ void updateSimCardStatus();
};
diff --git a/radio/aidl/vts/radio_config_indication.cpp b/radio/aidl/vts/radio_config_indication.cpp
new file mode 100644
index 0000000..a84c20b
--- /dev/null
+++ b/radio/aidl/vts/radio_config_indication.cpp
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "radio_config_utils.h"
+
+RadioConfigIndication::RadioConfigIndication(RadioServiceTest& parent) : parent_config(parent) {}
+
+ndk::ScopedAStatus RadioConfigIndication::simSlotsStatusChanged(
+ RadioIndicationType /*type*/, const std::vector<SimSlotStatus>& /*slotStatus*/) {
+ return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_config_response.cpp b/radio/aidl/vts/radio_config_response.cpp
new file mode 100644
index 0000000..1a152fb
--- /dev/null
+++ b/radio/aidl/vts/radio_config_response.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "radio_config_utils.h"
+
+RadioConfigResponse::RadioConfigResponse(RadioServiceTest& parent) : parent_config(parent) {}
+
+ndk::ScopedAStatus RadioConfigResponse::getSimSlotsStatusResponse(
+ const RadioResponseInfo& /* info */, const std::vector<SimSlotStatus>& /* slotStatus */) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioConfigResponse::setSimSlotsMappingResponse(
+ const RadioResponseInfo& /* info */) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioConfigResponse::getPhoneCapabilityResponse(
+ const RadioResponseInfo& info, const PhoneCapability& phoneCapability) {
+ rspInfo = info;
+ phoneCap = phoneCapability;
+ parent_config.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioConfigResponse::setPreferredDataModemResponse(
+ const RadioResponseInfo& /* info */) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioConfigResponse::getNumOfLiveModemsResponse(
+ const RadioResponseInfo& /* info */, const int8_t /* numOfLiveModems */) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioConfigResponse::setNumOfLiveModemsResponse(
+ const RadioResponseInfo& /* info */) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioConfigResponse::getHalDeviceCapabilitiesResponse(
+ const RadioResponseInfo& info, bool modemReducedFeatures) {
+ modemReducedFeatureSet1 = modemReducedFeatures;
+ parent_config.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_config_test.cpp b/radio/aidl/vts/radio_config_test.cpp
new file mode 100644
index 0000000..2d7fe01
--- /dev/null
+++ b/radio/aidl/vts/radio_config_test.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+
+#include "radio_config_utils.h"
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+
+void RadioConfigTest::SetUp() {
+ std::string serviceName = GetParam();
+
+ if (!isServiceValidForDeviceConfiguration(serviceName)) {
+ ALOGI("Skipped the test due to device configuration.");
+ GTEST_SKIP();
+ }
+
+ radio_config = IRadioConfig::fromBinder(
+ ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+ ASSERT_NE(nullptr, radio_config.get());
+
+ radioRsp_config = ndk::SharedRefBase::make<RadioConfigResponse>(*this);
+ ASSERT_NE(nullptr, radioRsp_config.get());
+
+ count_ = 0;
+
+ radioInd_config = ndk::SharedRefBase::make<RadioConfigIndication>(*this);
+ ASSERT_NE(nullptr, radioInd_config.get());
+
+ radio_config->setResponseFunctions(radioRsp_config, radioInd_config);
+}
+
+/*
+ * Test IRadioConfig.getHalDeviceCapabilities() for the response returned.
+ */
+TEST_P(RadioConfigTest, getHalDeviceCapabilities) {
+ serial = GetRandomSerialNumber();
+ ndk::ScopedAStatus res = radio_config->getHalDeviceCapabilities(serial);
+ ASSERT_OK(res);
+ ALOGI("getHalDeviceCapabilities, rspInfo.error = %s\n",
+ toString(radioRsp_config->rspInfo.error).c_str());
+}
diff --git a/radio/aidl/vts/radio_config_utils.h b/radio/aidl/vts/radio_config_utils.h
new file mode 100644
index 0000000..465c106
--- /dev/null
+++ b/radio/aidl/vts/radio_config_utils.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/radio/config/BnRadioConfigIndication.h>
+#include <aidl/android/hardware/radio/config/BnRadioConfigResponse.h>
+#include <aidl/android/hardware/radio/config/IRadioConfig.h>
+
+#include "radio_aidl_hal_utils.h"
+
+using namespace aidl::android::hardware::radio::config;
+
+class RadioConfigTest;
+
+/* Callback class for radio config response */
+class RadioConfigResponse : public BnRadioConfigResponse {
+ protected:
+ RadioServiceTest& parent_config;
+
+ public:
+ RadioConfigResponse(RadioServiceTest& parent_config);
+ virtual ~RadioConfigResponse() = default;
+
+ RadioResponseInfo rspInfo;
+ PhoneCapability phoneCap;
+ bool modemReducedFeatureSet1;
+
+ virtual ndk::ScopedAStatus getSimSlotsStatusResponse(
+ const RadioResponseInfo& info, const std::vector<SimSlotStatus>& slotStatus) override;
+
+ virtual ndk::ScopedAStatus setSimSlotsMappingResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus getPhoneCapabilityResponse(
+ const RadioResponseInfo& info, const PhoneCapability& phoneCapability) override;
+
+ virtual ndk::ScopedAStatus setPreferredDataModemResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus getNumOfLiveModemsResponse(const RadioResponseInfo& info,
+ const int8_t numOfLiveModems) override;
+
+ virtual ndk::ScopedAStatus setNumOfLiveModemsResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus getHalDeviceCapabilitiesResponse(
+ const RadioResponseInfo& info, bool modemReducedFeatureSet1) override;
+};
+
+/* Callback class for radio config indication */
+class RadioConfigIndication : public BnRadioConfigIndication {
+ protected:
+ RadioServiceTest& parent_config;
+
+ public:
+ RadioConfigIndication(RadioServiceTest& parent_config);
+ virtual ~RadioConfigIndication() = default;
+
+ virtual ndk::ScopedAStatus simSlotsStatusChanged(
+ RadioIndicationType type, const std::vector<SimSlotStatus>& slotStatus) override;
+};
+
+// The main test class for Radio AIDL Config.
+class RadioConfigTest : public ::testing::TestWithParam<std::string>, public RadioServiceTest {
+ public:
+ virtual void SetUp() override;
+ ndk::ScopedAStatus updateSimCardStatus();
+
+ /* radio config service handle in RadioServiceTest */
+ /* radio config response handle */
+ std::shared_ptr<RadioConfigResponse> radioRsp_config;
+ /* radio config indication handle */
+ std::shared_ptr<RadioConfigIndication> radioInd_config;
+};
diff --git a/radio/aidl/vts/radio_data_indication.cpp b/radio/aidl/vts/radio_data_indication.cpp
index 1e02fe1..4d3c539 100644
--- a/radio/aidl/vts/radio_data_indication.cpp
+++ b/radio/aidl/vts/radio_data_indication.cpp
@@ -16,7 +16,7 @@
#include "radio_data_utils.h"
-RadioDataIndication::RadioDataIndication(RadioDataTest& parent) : parent_data(parent) {}
+RadioDataIndication::RadioDataIndication(RadioServiceTest& parent) : parent_data(parent) {}
ndk::ScopedAStatus RadioDataIndication::dataCallListChanged(
RadioIndicationType /*type*/, const std::vector<SetupDataCallResult>& /*dcList*/) {
diff --git a/radio/aidl/vts/radio_data_response.cpp b/radio/aidl/vts/radio_data_response.cpp
index 682ddfb..9b17bfb 100644
--- a/radio/aidl/vts/radio_data_response.cpp
+++ b/radio/aidl/vts/radio_data_response.cpp
@@ -16,7 +16,7 @@
#include "radio_data_utils.h"
-RadioDataResponse::RadioDataResponse(RadioResponseWaiter& parent) : parent_data(parent) {}
+RadioDataResponse::RadioDataResponse(RadioServiceTest& parent) : parent_data(parent) {}
ndk::ScopedAStatus RadioDataResponse::acknowledgeRequest(int32_t /*serial*/) {
return ndk::ScopedAStatus::ok();
diff --git a/radio/aidl/vts/radio_data_test.cpp b/radio/aidl/vts/radio_data_test.cpp
index dbf0eb7..8547e9d 100644
--- a/radio/aidl/vts/radio_data_test.cpp
+++ b/radio/aidl/vts/radio_data_test.cpp
@@ -14,10 +14,11 @@
* limitations under the License.
*/
+#include <aidl/android/hardware/radio/RadioAccessFamily.h>
#include <aidl/android/hardware/radio/config/IRadioConfig.h>
+#include <aidl/android/hardware/radio/data/ApnTypes.h>
#include <android-base/logging.h>
#include <android/binder_manager.h>
-#include <algorithm>
#include "radio_data_utils.h"
@@ -45,12 +46,17 @@
radio_data->setResponseFunctions(radioRsp_data, radioInd_data);
+ // Assert IRadioSim exists and SIM is present before testing
+ radio_sim = sim::IRadioSim::fromBinder(ndk::SpAIBinder(
+ AServiceManager_waitForService("android.hardware.radio.sim.IRadioSim/slot1")));
+ ASSERT_NE(nullptr, radio_sim.get());
+ updateSimCardStatus();
+ EXPECT_EQ(CardStatus::STATE_PRESENT, cardStatus.cardState);
+
// Assert IRadioConfig exists before testing
- std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfig> radioConfig =
- aidl::android::hardware::radio::config::IRadioConfig::fromBinder(
- ndk::SpAIBinder(AServiceManager_waitForService(
- "android.hardware.radio.config.IRadioConfig/default")));
- ASSERT_NE(nullptr, radioConfig.get());
+ radio_config = config::IRadioConfig::fromBinder(ndk::SpAIBinder(
+ AServiceManager_waitForService("android.hardware.radio.config.IRadioConfig/default")));
+ ASSERT_NE(nullptr, radio_config.get());
}
ndk::ScopedAStatus RadioDataTest::getDataCallList() {
@@ -82,10 +88,18 @@
dataProfileInfo.maxConns = 20;
dataProfileInfo.waitTime = 0;
dataProfileInfo.enabled = true;
- // TODO(b/210712359): 320 was the previous value; need to support bitmaps
- dataProfileInfo.supportedApnTypesBitmap = ApnTypes::DEFAULT;
- // TODO(b/210712359): 161543 was the previous value; need to support bitmaps
- dataProfileInfo.bearerBitmap = RadioAccessFamily::LTE;
+ dataProfileInfo.supportedApnTypesBitmap =
+ static_cast<int32_t>(ApnTypes::IMS) | static_cast<int32_t>(ApnTypes::IA);
+ dataProfileInfo.bearerBitmap = static_cast<int32_t>(RadioAccessFamily::GPRS) |
+ static_cast<int32_t>(RadioAccessFamily::EDGE) |
+ static_cast<int32_t>(RadioAccessFamily::UMTS) |
+ static_cast<int32_t>(RadioAccessFamily::HSDPA) |
+ static_cast<int32_t>(RadioAccessFamily::HSUPA) |
+ static_cast<int32_t>(RadioAccessFamily::HSPA) |
+ static_cast<int32_t>(RadioAccessFamily::EHRPD) |
+ static_cast<int32_t>(RadioAccessFamily::LTE) |
+ static_cast<int32_t>(RadioAccessFamily::HSPAP) |
+ static_cast<int32_t>(RadioAccessFamily::IWLAN);
dataProfileInfo.mtuV4 = 0;
dataProfileInfo.mtuV6 = 0;
dataProfileInfo.preferred = true;
@@ -130,11 +144,8 @@
TrafficDescriptor trafficDescriptor;
OsAppId osAppId;
std::string osAppIdString("osAppId");
- // TODO(b/210712359): there should be a cleaner way to convert this
- std::vector<unsigned char> output(osAppIdString.length());
- std::transform(osAppIdString.begin(), osAppIdString.end(), output.begin(),
- [](char c) { return static_cast<unsigned char>(c); });
- osAppId.osAppId = output;
+ std::vector<unsigned char> osAppIdVec(osAppIdString.begin(), osAppIdString.end());
+ osAppId.osAppId = osAppIdVec;
trafficDescriptor.osAppId = osAppId;
DataProfileInfo dataProfileInfo;
@@ -151,10 +162,18 @@
dataProfileInfo.maxConns = 20;
dataProfileInfo.waitTime = 0;
dataProfileInfo.enabled = true;
- // TODO(b/210712359): 320 was the previous value; need to support bitmaps
- dataProfileInfo.supportedApnTypesBitmap = ApnTypes::DEFAULT;
- // TODO(b/210712359): 161543 was the previous value; need to support bitmaps
- dataProfileInfo.bearerBitmap = RadioAccessFamily::LTE;
+ dataProfileInfo.supportedApnTypesBitmap =
+ static_cast<int32_t>(ApnTypes::IMS) | static_cast<int32_t>(ApnTypes::IA);
+ dataProfileInfo.bearerBitmap = static_cast<int32_t>(RadioAccessFamily::GPRS) |
+ static_cast<int32_t>(RadioAccessFamily::EDGE) |
+ static_cast<int32_t>(RadioAccessFamily::UMTS) |
+ static_cast<int32_t>(RadioAccessFamily::HSDPA) |
+ static_cast<int32_t>(RadioAccessFamily::HSUPA) |
+ static_cast<int32_t>(RadioAccessFamily::HSPA) |
+ static_cast<int32_t>(RadioAccessFamily::EHRPD) |
+ static_cast<int32_t>(RadioAccessFamily::LTE) |
+ static_cast<int32_t>(RadioAccessFamily::HSPAP) |
+ static_cast<int32_t>(RadioAccessFamily::IWLAN);
dataProfileInfo.mtuV4 = 0;
dataProfileInfo.mtuV6 = 0;
dataProfileInfo.preferred = true;
diff --git a/radio/aidl/vts/radio_data_utils.h b/radio/aidl/vts/radio_data_utils.h
index ada8ac1..50c7878 100644
--- a/radio/aidl/vts/radio_data_utils.h
+++ b/radio/aidl/vts/radio_data_utils.h
@@ -23,17 +23,16 @@
#include "radio_aidl_hal_utils.h"
using namespace aidl::android::hardware::radio::data;
-using aidl::android::hardware::radio::sim::CardStatus;
class RadioDataTest;
/* Callback class for radio data response */
class RadioDataResponse : public BnRadioDataResponse {
protected:
- RadioResponseWaiter& parent_data;
+ RadioServiceTest& parent_data;
public:
- RadioDataResponse(RadioResponseWaiter& parent_data);
+ RadioDataResponse(RadioServiceTest& parent_data);
virtual ~RadioDataResponse() = default;
RadioResponseInfo rspInfo;
@@ -80,10 +79,10 @@
/* Callback class for radio data indication */
class RadioDataIndication : public BnRadioDataIndication {
protected:
- RadioDataTest& parent_data;
+ RadioServiceTest& parent_data;
public:
- RadioDataIndication(RadioDataTest& parent_data);
+ RadioDataIndication(RadioServiceTest& parent_data);
virtual ~RadioDataIndication() = default;
virtual ndk::ScopedAStatus dataCallListChanged(
@@ -99,7 +98,7 @@
};
// The main test class for Radio AIDL Data.
-class RadioDataTest : public ::testing::TestWithParam<std::string>, public RadioResponseWaiter {
+class RadioDataTest : public ::testing::TestWithParam<std::string>, public RadioServiceTest {
protected:
/* Get current data call list */
ndk::ScopedAStatus getDataCallList();
diff --git a/radio/aidl/vts/radio_messaging_indication.cpp b/radio/aidl/vts/radio_messaging_indication.cpp
index 7eeb266..c69611f 100644
--- a/radio/aidl/vts/radio_messaging_indication.cpp
+++ b/radio/aidl/vts/radio_messaging_indication.cpp
@@ -16,7 +16,7 @@
#include "radio_messaging_utils.h"
-RadioMessagingIndication::RadioMessagingIndication(RadioMessagingTest& parent)
+RadioMessagingIndication::RadioMessagingIndication(RadioServiceTest& parent)
: parent_messaging(parent) {}
ndk::ScopedAStatus RadioMessagingIndication::cdmaNewSms(RadioIndicationType /*type*/,
diff --git a/radio/aidl/vts/radio_messaging_response.cpp b/radio/aidl/vts/radio_messaging_response.cpp
index d73278f..718df7e 100644
--- a/radio/aidl/vts/radio_messaging_response.cpp
+++ b/radio/aidl/vts/radio_messaging_response.cpp
@@ -16,7 +16,7 @@
#include "radio_messaging_utils.h"
-RadioMessagingResponse::RadioMessagingResponse(RadioResponseWaiter& parent)
+RadioMessagingResponse::RadioMessagingResponse(RadioServiceTest& parent)
: parent_messaging(parent) {}
ndk::ScopedAStatus RadioMessagingResponse::acknowledgeIncomingGsmSmsWithPduResponse(
diff --git a/radio/aidl/vts/radio_messaging_test.cpp b/radio/aidl/vts/radio_messaging_test.cpp
index 58aeaab..8abd91d 100644
--- a/radio/aidl/vts/radio_messaging_test.cpp
+++ b/radio/aidl/vts/radio_messaging_test.cpp
@@ -44,12 +44,17 @@
radio_messaging->setResponseFunctions(radioRsp_messaging, radioInd_messaging);
+ // Assert IRadioSim exists and SIM is present before testing
+ radio_sim = sim::IRadioSim::fromBinder(ndk::SpAIBinder(
+ AServiceManager_waitForService("android.hardware.radio.sim.IRadioSim/slot1")));
+ ASSERT_NE(nullptr, radio_sim.get());
+ updateSimCardStatus();
+ EXPECT_EQ(CardStatus::STATE_PRESENT, cardStatus.cardState);
+
// Assert IRadioConfig exists before testing
- std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfig> radioConfig =
- aidl::android::hardware::radio::config::IRadioConfig::fromBinder(
- ndk::SpAIBinder(AServiceManager_waitForService(
- "android.hardware.radio.config.IRadioConfig/default")));
- ASSERT_NE(nullptr, radioConfig.get());
+ radio_config = config::IRadioConfig::fromBinder(ndk::SpAIBinder(
+ AServiceManager_waitForService("android.hardware.radio.config.IRadioConfig/default")));
+ ASSERT_NE(nullptr, radio_config.get());
}
/*
diff --git a/radio/aidl/vts/radio_messaging_utils.h b/radio/aidl/vts/radio_messaging_utils.h
index 96cde08..7bb99cd 100644
--- a/radio/aidl/vts/radio_messaging_utils.h
+++ b/radio/aidl/vts/radio_messaging_utils.h
@@ -29,10 +29,10 @@
/* Callback class for radio messaging response */
class RadioMessagingResponse : public BnRadioMessagingResponse {
protected:
- RadioResponseWaiter& parent_messaging;
+ RadioServiceTest& parent_messaging;
public:
- RadioMessagingResponse(RadioResponseWaiter& parent_messaging);
+ RadioMessagingResponse(RadioServiceTest& parent_messaging);
virtual ~RadioMessagingResponse() = default;
RadioResponseInfo rspInfo;
@@ -110,10 +110,10 @@
/* Callback class for radio messaging indication */
class RadioMessagingIndication : public BnRadioMessagingIndication {
protected:
- RadioMessagingTest& parent_messaging;
+ RadioServiceTest& parent_messaging;
public:
- RadioMessagingIndication(RadioMessagingTest& parent_messaging);
+ RadioMessagingIndication(RadioServiceTest& parent_messaging);
virtual ~RadioMessagingIndication() = default;
virtual ndk::ScopedAStatus cdmaNewSms(RadioIndicationType type,
@@ -139,8 +139,7 @@
};
// The main test class for Radio AIDL Messaging.
-class RadioMessagingTest : public ::testing::TestWithParam<std::string>,
- public RadioResponseWaiter {
+class RadioMessagingTest : public ::testing::TestWithParam<std::string>, public RadioServiceTest {
public:
virtual void SetUp() override;
diff --git a/radio/aidl/vts/radio_modem_indication.cpp b/radio/aidl/vts/radio_modem_indication.cpp
index 17f37a8..0bfcd66 100644
--- a/radio/aidl/vts/radio_modem_indication.cpp
+++ b/radio/aidl/vts/radio_modem_indication.cpp
@@ -16,7 +16,7 @@
#include "radio_modem_utils.h"
-RadioModemIndication::RadioModemIndication(RadioModemTest& parent) : parent_modem(parent) {}
+RadioModemIndication::RadioModemIndication(RadioServiceTest& parent) : parent_modem(parent) {}
ndk::ScopedAStatus RadioModemIndication::hardwareConfigChanged(
RadioIndicationType /*type*/, const std::vector<HardwareConfig>& /*configs*/) {
diff --git a/radio/aidl/vts/radio_modem_response.cpp b/radio/aidl/vts/radio_modem_response.cpp
index 7ac590f..53bfab4 100644
--- a/radio/aidl/vts/radio_modem_response.cpp
+++ b/radio/aidl/vts/radio_modem_response.cpp
@@ -16,7 +16,7 @@
#include "radio_modem_utils.h"
-RadioModemResponse::RadioModemResponse(RadioResponseWaiter& parent) : parent_modem(parent) {}
+RadioModemResponse::RadioModemResponse(RadioServiceTest& parent) : parent_modem(parent) {}
ndk::ScopedAStatus RadioModemResponse::acknowledgeRequest(int32_t /*serial*/) {
return ndk::ScopedAStatus::ok();
diff --git a/radio/aidl/vts/radio_modem_test.cpp b/radio/aidl/vts/radio_modem_test.cpp
index 406927f..b40bb7b 100644
--- a/radio/aidl/vts/radio_modem_test.cpp
+++ b/radio/aidl/vts/radio_modem_test.cpp
@@ -44,12 +44,17 @@
radio_modem->setResponseFunctions(radioRsp_modem, radioInd_modem);
+ // Assert IRadioSim exists and SIM is present before testing
+ radio_sim = sim::IRadioSim::fromBinder(ndk::SpAIBinder(
+ AServiceManager_waitForService("android.hardware.radio.sim.IRadioSim/slot1")));
+ ASSERT_NE(nullptr, radio_sim.get());
+ updateSimCardStatus();
+ EXPECT_EQ(CardStatus::STATE_PRESENT, cardStatus.cardState);
+
// Assert IRadioConfig exists before testing
- std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfig> radioConfig =
- aidl::android::hardware::radio::config::IRadioConfig::fromBinder(
- ndk::SpAIBinder(AServiceManager_waitForService(
- "android.hardware.radio.config.IRadioConfig/default")));
- ASSERT_NE(nullptr, radioConfig.get());
+ radio_config = config::IRadioConfig::fromBinder(ndk::SpAIBinder(
+ AServiceManager_waitForService("android.hardware.radio.config.IRadioConfig/default")));
+ ASSERT_NE(nullptr, radio_config.get());
}
/*
diff --git a/radio/aidl/vts/radio_modem_utils.h b/radio/aidl/vts/radio_modem_utils.h
index cd9a30d..8779e0c 100644
--- a/radio/aidl/vts/radio_modem_utils.h
+++ b/radio/aidl/vts/radio_modem_utils.h
@@ -22,7 +22,6 @@
#include "radio_aidl_hal_utils.h"
-using namespace aidl::android::hardware::radio::config;
using namespace aidl::android::hardware::radio::modem;
class RadioModemTest;
@@ -30,10 +29,10 @@
/* Callback class for radio modem response */
class RadioModemResponse : public BnRadioModemResponse {
protected:
- RadioResponseWaiter& parent_modem;
+ RadioServiceTest& parent_modem;
public:
- RadioModemResponse(RadioResponseWaiter& parent_modem);
+ RadioModemResponse(RadioServiceTest& parent_modem);
virtual ~RadioModemResponse() = default;
RadioResponseInfo rspInfo;
@@ -87,10 +86,10 @@
/* Callback class for radio modem indication */
class RadioModemIndication : public BnRadioModemIndication {
protected:
- RadioModemTest& parent_modem;
+ RadioServiceTest& parent_modem;
public:
- RadioModemIndication(RadioModemTest& parent_modem);
+ RadioModemIndication(RadioServiceTest& parent_modem);
virtual ~RadioModemIndication() = default;
virtual ndk::ScopedAStatus hardwareConfigChanged(
@@ -109,7 +108,7 @@
};
// The main test class for Radio AIDL Modem.
-class RadioModemTest : public ::testing::TestWithParam<std::string>, public RadioResponseWaiter {
+class RadioModemTest : public ::testing::TestWithParam<std::string>, public RadioServiceTest {
public:
virtual void SetUp() override;
diff --git a/radio/aidl/vts/radio_network_indication.cpp b/radio/aidl/vts/radio_network_indication.cpp
index 7bed759..7acbff4 100644
--- a/radio/aidl/vts/radio_network_indication.cpp
+++ b/radio/aidl/vts/radio_network_indication.cpp
@@ -16,7 +16,7 @@
#include "radio_network_utils.h"
-RadioNetworkIndication::RadioNetworkIndication(RadioNetworkTest& parent) : parent_network(parent) {}
+RadioNetworkIndication::RadioNetworkIndication(RadioServiceTest& parent) : parent_network(parent) {}
ndk::ScopedAStatus RadioNetworkIndication::barringInfoChanged(
RadioIndicationType /*type*/, const CellIdentity& /*cellIdentity*/,
@@ -72,7 +72,7 @@
ndk::ScopedAStatus RadioNetworkIndication::registrationFailed(RadioIndicationType /*type*/,
const CellIdentity& /*cellIdentity*/,
const std::string& /*chosenPlmn*/,
- Domain /*domain*/,
+ int32_t /*domain*/,
int32_t /*causeCode*/,
int32_t /*additionalCauseCode*/) {
return ndk::ScopedAStatus::ok();
diff --git a/radio/aidl/vts/radio_network_response.cpp b/radio/aidl/vts/radio_network_response.cpp
index b242341..ccae0f3 100644
--- a/radio/aidl/vts/radio_network_response.cpp
+++ b/radio/aidl/vts/radio_network_response.cpp
@@ -16,14 +16,14 @@
#include "radio_network_utils.h"
-RadioNetworkResponse::RadioNetworkResponse(RadioResponseWaiter& parent) : parent_network(parent) {}
+RadioNetworkResponse::RadioNetworkResponse(RadioServiceTest& parent) : parent_network(parent) {}
ndk::ScopedAStatus RadioNetworkResponse::acknowledgeRequest(int32_t /*serial*/) {
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus RadioNetworkResponse::getAllowedNetworkTypesBitmapResponse(
- const RadioResponseInfo& info, const RadioAccessFamily networkTypeBitmap) {
+ const RadioResponseInfo& info, const int32_t networkTypeBitmap) {
rspInfo = info;
networkTypeBitmapResponse = networkTypeBitmap;
parent_network.notify(info.serial);
@@ -112,7 +112,7 @@
ndk::ScopedAStatus RadioNetworkResponse::getVoiceRegistrationStateResponse(
const RadioResponseInfo& info, const RegStateResult& regResponse) {
rspInfo = info;
- regStateResp.regState = regResponse.regState;
+ voiceRegResp.regState = regResponse.regState;
parent_network.notify(info.serial);
return ndk::ScopedAStatus::ok();
}
diff --git a/radio/aidl/vts/radio_network_test.cpp b/radio/aidl/vts/radio_network_test.cpp
index 1cdbb6d..93c4c35 100644
--- a/radio/aidl/vts/radio_network_test.cpp
+++ b/radio/aidl/vts/radio_network_test.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <aidl/android/hardware/radio/RadioAccessFamily.h>
#include <aidl/android/hardware/radio/config/IRadioConfig.h>
#include <android-base/logging.h>
#include <android/binder_manager.h>
@@ -44,12 +45,17 @@
radio_network->setResponseFunctions(radioRsp_network, radioInd_network);
+ // Assert IRadioSim exists and SIM is present before testing
+ radio_sim = sim::IRadioSim::fromBinder(ndk::SpAIBinder(
+ AServiceManager_waitForService("android.hardware.radio.sim.IRadioSim/slot1")));
+ ASSERT_NE(nullptr, radio_sim.get());
+ updateSimCardStatus();
+ EXPECT_EQ(CardStatus::STATE_PRESENT, cardStatus.cardState);
+
// Assert IRadioConfig exists before testing
- std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfig> radioConfig =
- aidl::android::hardware::radio::config::IRadioConfig::fromBinder(
- ndk::SpAIBinder(AServiceManager_waitForService(
- "android.hardware.radio.config.IRadioConfig/default")));
- ASSERT_NE(nullptr, radioConfig.get());
+ radio_config = config::IRadioConfig::fromBinder(ndk::SpAIBinder(
+ AServiceManager_waitForService("android.hardware.radio.config.IRadioConfig/default")));
+ ASSERT_NE(nullptr, radio_config.get());
}
/*
@@ -57,7 +63,7 @@
*/
TEST_P(RadioNetworkTest, setAllowedNetworkTypesBitmap) {
serial = GetRandomSerialNumber();
- RadioAccessFamily allowedNetworkTypesBitmap = RadioAccessFamily::LTE;
+ int32_t allowedNetworkTypesBitmap = static_cast<int32_t>(RadioAccessFamily::LTE);
radio_network->setAllowedNetworkTypesBitmap(serial, allowedNetworkTypesBitmap);
@@ -77,7 +83,7 @@
*/
TEST_P(RadioNetworkTest, getAllowedNetworkTypesBitmap) {
serial = GetRandomSerialNumber();
- RadioAccessFamily allowedNetworkTypesBitmap = RadioAccessFamily::LTE;
+ int32_t allowedNetworkTypesBitmap = static_cast<int32_t>(RadioAccessFamily::LTE);
radio_network->setAllowedNetworkTypesBitmap(serial, allowedNetworkTypesBitmap);
diff --git a/radio/aidl/vts/radio_network_utils.h b/radio/aidl/vts/radio_network_utils.h
index caa1ecc..9f76769 100644
--- a/radio/aidl/vts/radio_network_utils.h
+++ b/radio/aidl/vts/radio_network_utils.h
@@ -29,18 +29,18 @@
/* Callback class for radio network response */
class RadioNetworkResponse : public BnRadioNetworkResponse {
protected:
- RadioResponseWaiter& parent_network;
+ RadioServiceTest& parent_network;
public:
- RadioNetworkResponse(RadioResponseWaiter& parent_network);
+ RadioNetworkResponse(RadioServiceTest& parent_network);
virtual ~RadioNetworkResponse() = default;
RadioResponseInfo rspInfo;
std::vector<RadioBandMode> radioBandModes;
std::vector<OperatorInfo> networkInfos;
bool isNrDualConnectivityEnabled;
- RadioAccessFamily networkTypeBitmapResponse;
- RegStateResult regStateResp;
+ int networkTypeBitmapResponse;
+ RegStateResult voiceRegResp;
CellIdentity barringCellIdentity;
std::vector<BarringInfo> barringInfos;
UsageSetting usageSetting;
@@ -48,7 +48,7 @@
virtual ndk::ScopedAStatus acknowledgeRequest(int32_t serial) override;
virtual ndk::ScopedAStatus getAllowedNetworkTypesBitmapResponse(
- const RadioResponseInfo& info, const RadioAccessFamily networkTypeBitmap) override;
+ const RadioResponseInfo& info, const int32_t networkTypeBitmap) override;
virtual ndk::ScopedAStatus getAvailableBandModesResponse(
const RadioResponseInfo& info, const std::vector<RadioBandMode>& bandModes) override;
@@ -150,10 +150,10 @@
/* Callback class for radio network indication */
class RadioNetworkIndication : public BnRadioNetworkIndication {
protected:
- RadioNetworkTest& parent_network;
+ RadioServiceTest& parent_network;
public:
- RadioNetworkIndication(RadioNetworkTest& parent_network);
+ RadioNetworkIndication(RadioServiceTest& parent_network);
virtual ~RadioNetworkIndication() = default;
virtual ndk::ScopedAStatus barringInfoChanged(
@@ -187,7 +187,7 @@
virtual ndk::ScopedAStatus registrationFailed(RadioIndicationType type,
const CellIdentity& cellIdentity,
- const std::string& chosenPlmn, Domain domain,
+ const std::string& chosenPlmn, int32_t domain,
int32_t causeCode,
int32_t additionalCauseCode) override;
@@ -202,7 +202,7 @@
};
// The main test class for Radio AIDL Network.
-class RadioNetworkTest : public ::testing::TestWithParam<std::string>, public RadioResponseWaiter {
+class RadioNetworkTest : public ::testing::TestWithParam<std::string>, public RadioServiceTest {
public:
virtual void SetUp() override;
diff --git a/radio/aidl/vts/radio_sim_indication.cpp b/radio/aidl/vts/radio_sim_indication.cpp
index 0385845..c03d947 100644
--- a/radio/aidl/vts/radio_sim_indication.cpp
+++ b/radio/aidl/vts/radio_sim_indication.cpp
@@ -16,7 +16,7 @@
#include "radio_sim_utils.h"
-RadioSimIndication::RadioSimIndication(RadioSimTest& parent) : parent_sim(parent) {}
+RadioSimIndication::RadioSimIndication(RadioServiceTest& parent) : parent_sim(parent) {}
ndk::ScopedAStatus RadioSimIndication::carrierInfoForImsiEncryption(RadioIndicationType /*info*/) {
return ndk::ScopedAStatus::ok();
diff --git a/radio/aidl/vts/radio_sim_response.cpp b/radio/aidl/vts/radio_sim_response.cpp
index 2c796fa..a783f43 100644
--- a/radio/aidl/vts/radio_sim_response.cpp
+++ b/radio/aidl/vts/radio_sim_response.cpp
@@ -16,7 +16,7 @@
#include "radio_sim_utils.h"
-RadioSimResponse::RadioSimResponse(RadioResponseWaiter& parent) : parent_sim(parent) {}
+RadioSimResponse::RadioSimResponse(RadioServiceTest& parent) : parent_sim(parent) {}
ndk::ScopedAStatus RadioSimResponse::acknowledgeRequest(int32_t /*serial*/) {
return ndk::ScopedAStatus::ok();
diff --git a/radio/aidl/vts/radio_sim_test.cpp b/radio/aidl/vts/radio_sim_test.cpp
index c70219f..5db77f6 100644
--- a/radio/aidl/vts/radio_sim_test.cpp
+++ b/radio/aidl/vts/radio_sim_test.cpp
@@ -43,20 +43,23 @@
ASSERT_NE(nullptr, radioInd_sim.get());
radio_sim->setResponseFunctions(radioRsp_sim, radioInd_sim);
+ // Assert SIM is present before testing
+ updateSimCardStatus();
+ EXPECT_EQ(CardStatus::STATE_PRESENT, cardStatus.cardState);
// Assert IRadioConfig exists before testing
- std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfig> radioConfig =
- aidl::android::hardware::radio::config::IRadioConfig::fromBinder(
- ndk::SpAIBinder(AServiceManager_waitForService(
- "android.hardware.radio.config.IRadioConfig/default")));
- ASSERT_NE(nullptr, radioConfig.get());
+ radio_config = config::IRadioConfig::fromBinder(ndk::SpAIBinder(
+ AServiceManager_waitForService("android.hardware.radio.config.IRadioConfig/default")));
+ ASSERT_NE(nullptr, radio_config.get());
}
-ndk::ScopedAStatus RadioSimTest::updateSimCardStatus() {
+void RadioSimTest::updateSimCardStatus() {
serial = GetRandomSerialNumber();
radio_sim->getIccCardStatus(serial);
EXPECT_EQ(std::cv_status::no_timeout, wait());
- return ndk::ScopedAStatus::ok();
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_sim->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_sim->rspInfo.serial);
+ EXPECT_EQ(RadioError::NONE, radioRsp_sim->rspInfo.error);
}
/*
diff --git a/radio/aidl/vts/radio_sim_utils.h b/radio/aidl/vts/radio_sim_utils.h
index 6cb6790..b5e365d 100644
--- a/radio/aidl/vts/radio_sim_utils.h
+++ b/radio/aidl/vts/radio_sim_utils.h
@@ -29,10 +29,10 @@
/* Callback class for radio SIM response */
class RadioSimResponse : public BnRadioSimResponse {
protected:
- RadioResponseWaiter& parent_sim;
+ RadioServiceTest& parent_sim;
public:
- RadioSimResponse(RadioResponseWaiter& parent_sim);
+ RadioSimResponse(RadioServiceTest& parent_sim);
virtual ~RadioSimResponse() = default;
RadioResponseInfo rspInfo;
@@ -152,10 +152,10 @@
/* Callback class for radio SIM indication */
class RadioSimIndication : public BnRadioSimIndication {
protected:
- RadioSimTest& parent_sim;
+ RadioServiceTest& parent_sim;
public:
- RadioSimIndication(RadioSimTest& parent_sim);
+ RadioSimIndication(RadioServiceTest& parent_sim);
virtual ~RadioSimIndication() = default;
virtual ndk::ScopedAStatus carrierInfoForImsiEncryption(RadioIndicationType info) override;
@@ -190,16 +190,14 @@
};
// The main test class for Radio AIDL SIM.
-class RadioSimTest : public ::testing::TestWithParam<std::string>, public RadioResponseWaiter {
- protected:
- /* Update Sim Card Status */
- virtual ndk::ScopedAStatus updateSimCardStatus();
-
+class RadioSimTest : public ::testing::TestWithParam<std::string>, public RadioServiceTest {
public:
virtual void SetUp() override;
- /* radio SIM service handle */
- std::shared_ptr<IRadioSim> radio_sim;
+ /* Override updateSimCardStatus in RadioServiceTest to not call setResponseFunctions */
+ void updateSimCardStatus();
+
+ /* radio SIM service handle in RadioServiceTest */
/* radio SIM response handle */
std::shared_ptr<RadioSimResponse> radioRsp_sim;
/* radio SIM indication handle */
diff --git a/radio/aidl/vts/radio_voice_indication.cpp b/radio/aidl/vts/radio_voice_indication.cpp
index 2c46817..d814c18 100644
--- a/radio/aidl/vts/radio_voice_indication.cpp
+++ b/radio/aidl/vts/radio_voice_indication.cpp
@@ -16,7 +16,7 @@
#include "radio_voice_utils.h"
-RadioVoiceIndication::RadioVoiceIndication(RadioVoiceTest& parent) : parent_voice(parent) {}
+RadioVoiceIndication::RadioVoiceIndication(RadioServiceTest& parent) : parent_voice(parent) {}
ndk::ScopedAStatus RadioVoiceIndication::callRing(RadioIndicationType /*type*/, bool /*isGsm*/,
const CdmaSignalInfoRecord& /*record*/) {
diff --git a/radio/aidl/vts/radio_voice_response.cpp b/radio/aidl/vts/radio_voice_response.cpp
index ca350c6..a491613 100644
--- a/radio/aidl/vts/radio_voice_response.cpp
+++ b/radio/aidl/vts/radio_voice_response.cpp
@@ -16,7 +16,7 @@
#include "radio_voice_utils.h"
-RadioVoiceResponse::RadioVoiceResponse(RadioResponseWaiter& parent) : parent_voice(parent) {}
+RadioVoiceResponse::RadioVoiceResponse(RadioServiceTest& parent) : parent_voice(parent) {}
ndk::ScopedAStatus RadioVoiceResponse::acceptCallResponse(const RadioResponseInfo& /*info*/) {
return ndk::ScopedAStatus::ok();
diff --git a/radio/aidl/vts/radio_voice_test.cpp b/radio/aidl/vts/radio_voice_test.cpp
index 201f14c..717f3f0 100644
--- a/radio/aidl/vts/radio_voice_test.cpp
+++ b/radio/aidl/vts/radio_voice_test.cpp
@@ -15,6 +15,7 @@
*/
#include <aidl/android/hardware/radio/config/IRadioConfig.h>
+#include <aidl/android/hardware/radio/voice/EmergencyServiceCategory.h>
#include <android-base/logging.h>
#include <android/binder_manager.h>
@@ -44,12 +45,26 @@
radio_voice->setResponseFunctions(radioRsp_voice, radioInd_voice);
+ // Assert IRadioSim exists and SIM is present before testing
+ radio_sim = sim::IRadioSim::fromBinder(ndk::SpAIBinder(
+ AServiceManager_waitForService("android.hardware.radio.sim.IRadioSim/slot1")));
+ ASSERT_NE(nullptr, radio_sim.get());
+ updateSimCardStatus();
+ EXPECT_EQ(CardStatus::STATE_PRESENT, cardStatus.cardState);
+
// Assert IRadioConfig exists before testing
- std::shared_ptr<aidl::android::hardware::radio::config::IRadioConfig> radioConfig =
- aidl::android::hardware::radio::config::IRadioConfig::fromBinder(
- ndk::SpAIBinder(AServiceManager_waitForService(
- "android.hardware.radio.config.IRadioConfig/default")));
- ASSERT_NE(nullptr, radioConfig.get());
+ radio_config = config::IRadioConfig::fromBinder(ndk::SpAIBinder(
+ AServiceManager_waitForService("android.hardware.radio.config.IRadioConfig/default")));
+ ASSERT_NE(nullptr, radio_config.get());
+
+ if (isDsDsEnabled() || isTsTsEnabled()) {
+ radio_network = IRadioNetwork::fromBinder(ndk::SpAIBinder(AServiceManager_waitForService(
+ "android.hardware.radio.network.IRadioNetwork/slot1")));
+ ASSERT_NE(nullptr, radio_network.get());
+ radioRsp_network = ndk::SharedRefBase::make<RadioNetworkResponse>(*this);
+ radioInd_network = ndk::SharedRefBase::make<RadioNetworkIndication>(*this);
+ radio_network->setResponseFunctions(radioRsp_network, radioInd_network);
+ }
}
ndk::ScopedAStatus RadioVoiceTest::clearPotentialEstablishedCalls() {
@@ -95,7 +110,7 @@
Dial dialInfo;
dialInfo.address = std::string("911");
- EmergencyServiceCategory categories = EmergencyServiceCategory::UNSPECIFIED;
+ int32_t categories = static_cast<int32_t>(EmergencyServiceCategory::UNSPECIFIED);
std::vector<std::string> urns = {""};
EmergencyCallRouting routing = EmergencyCallRouting::UNKNOWN;
@@ -112,16 +127,13 @@
// In DSDS or TSTS, we only check the result if the current slot is IN_SERVICE
// or Emergency_Only.
if (isDsDsEnabled() || isTsTsEnabled()) {
- // TODO(b/210712359): maybe create a local RadioNetwork instance
- /**
serial = GetRandomSerialNumber();
- radio_v1_6->getVoiceRegistrationState(serial);
+ radio_network->getVoiceRegistrationState(serial);
EXPECT_EQ(std::cv_status::no_timeout, wait());
- if (isVoiceEmergencyOnly(radioRsp_v1_6->voiceRegResp.regState) ||
- isVoiceInService(radioRsp_v1_6->voiceRegResp.regState)) {
+ if (isVoiceEmergencyOnly(radioRsp_network->voiceRegResp.regState) ||
+ isVoiceInService(radioRsp_network->voiceRegResp.regState)) {
EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
}
- **/
} else {
EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
}
@@ -152,7 +164,7 @@
Dial dialInfo;
dialInfo.address = std::string("911");
- EmergencyServiceCategory categories = EmergencyServiceCategory::AMBULANCE;
+ int32_t categories = static_cast<int32_t>(EmergencyServiceCategory::AMBULANCE);
std::vector<std::string> urns = {"urn:service:sos.ambulance"};
EmergencyCallRouting routing = EmergencyCallRouting::UNKNOWN;
@@ -170,16 +182,13 @@
// In DSDS or TSTS, we only check the result if the current slot is IN_SERVICE
// or Emergency_Only.
if (isDsDsEnabled() || isTsTsEnabled()) {
- // TODO(b/210712359): maybe create a local RadioNetwork instance
- /**
serial = GetRandomSerialNumber();
- radio_v1_6->getVoiceRegistrationState_1_6(serial);
+ radio_network->getVoiceRegistrationState(serial);
EXPECT_EQ(std::cv_status::no_timeout, wait());
- if (isVoiceEmergencyOnly(radioRsp_v1_6->voiceRegResp.regState) ||
- isVoiceInService(radioRsp_v1_6->voiceRegResp.regState)) {
+ if (isVoiceEmergencyOnly(radioRsp_network->voiceRegResp.regState) ||
+ isVoiceInService(radioRsp_network->voiceRegResp.regState)) {
EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
}
- **/
} else {
EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
}
@@ -209,7 +218,7 @@
Dial dialInfo;
dialInfo.address = std::string("911");
- EmergencyServiceCategory categories = EmergencyServiceCategory::UNSPECIFIED;
+ int32_t categories = static_cast<int32_t>(EmergencyServiceCategory::UNSPECIFIED);
std::vector<std::string> urns = {""};
EmergencyCallRouting routing = EmergencyCallRouting::EMERGENCY;
@@ -227,16 +236,13 @@
// In DSDS or TSTS, we only check the result if the current slot is IN_SERVICE
// or Emergency_Only.
if (isDsDsEnabled() || isTsTsEnabled()) {
- // TODO(b/210712359): maybe create a local RadioNetwork instance
- /**
serial = GetRandomSerialNumber();
- radio_v1_6->getVoiceRegistrationState_1_6(serial);
+ radio_network->getVoiceRegistrationState(serial);
EXPECT_EQ(std::cv_status::no_timeout, wait());
- if (isVoiceEmergencyOnly(radioRsp_v1_6->voiceRegResp.regState) ||
- isVoiceInService(radioRsp_v1_6->voiceRegResp.regState)) {
+ if (isVoiceEmergencyOnly(radioRsp_network->voiceRegResp.regState) ||
+ isVoiceInService(radioRsp_network->voiceRegResp.regState)) {
EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
}
- **/
} else {
EXPECT_EQ(RadioError::NONE, rspEmergencyDial);
}
diff --git a/radio/aidl/vts/radio_voice_utils.h b/radio/aidl/vts/radio_voice_utils.h
index a676a7f..d61bf1e 100644
--- a/radio/aidl/vts/radio_voice_utils.h
+++ b/radio/aidl/vts/radio_voice_utils.h
@@ -21,6 +21,7 @@
#include <aidl/android/hardware/radio/voice/IRadioVoice.h>
#include "radio_aidl_hal_utils.h"
+#include "radio_network_utils.h"
using namespace aidl::android::hardware::radio::voice;
@@ -29,10 +30,10 @@
/* Callback class for radio voice response */
class RadioVoiceResponse : public BnRadioVoiceResponse {
protected:
- RadioResponseWaiter& parent_voice;
+ RadioServiceTest& parent_voice;
public:
- RadioVoiceResponse(RadioResponseWaiter& parent_voice);
+ RadioVoiceResponse(RadioServiceTest& parent_voice);
virtual ~RadioVoiceResponse() = default;
RadioResponseInfo rspInfo;
@@ -130,10 +131,10 @@
/* Callback class for radio voice indication */
class RadioVoiceIndication : public BnRadioVoiceIndication {
protected:
- RadioVoiceTest& parent_voice;
+ RadioServiceTest& parent_voice;
public:
- RadioVoiceIndication(RadioVoiceTest& parent_voice);
+ RadioVoiceIndication(RadioServiceTest& parent_voice);
virtual ~RadioVoiceIndication() = default;
virtual ndk::ScopedAStatus callRing(RadioIndicationType type, bool isGsm,
@@ -175,10 +176,13 @@
};
// The main test class for Radio AIDL Voice.
-class RadioVoiceTest : public ::testing::TestWithParam<std::string>, public RadioResponseWaiter {
+class RadioVoiceTest : public ::testing::TestWithParam<std::string>, public RadioServiceTest {
protected:
/* Clear Potential Established Calls */
virtual ndk::ScopedAStatus clearPotentialEstablishedCalls();
+ std::shared_ptr<network::IRadioNetwork> radio_network;
+ std::shared_ptr<RadioNetworkResponse> radioRsp_network;
+ std::shared_ptr<RadioNetworkIndication> radioInd_network;
public:
virtual void SetUp() override;
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 3695f1e..02462fc 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -537,6 +537,9 @@
Status result;
if (!output) return ErrorCode::UNEXPECTED_NULL_POINTER;
+ EXPECT_NE(op_, nullptr);
+ if (!op_) return ErrorCode::UNEXPECTED_NULL_POINTER;
+
std::vector<uint8_t> o_put;
result = op_->update(vector<uint8_t>(input.begin(), input.end()), {}, {}, &o_put);
diff --git a/sensors/aidl/Android.bp b/sensors/aidl/Android.bp
new file mode 100644
index 0000000..fd1ac44
--- /dev/null
+++ b/sensors/aidl/Android.bp
@@ -0,0 +1,25 @@
+// This is the expected build file, but it may not be right in all cases
+
+aidl_interface {
+ name: "android.hardware.sensors",
+ vendor_available: true,
+ srcs: ["android/hardware/sensors/*.aidl"],
+ imports: [
+ "android.hardware.common-V2",
+ "android.hardware.common.fmq-V1",
+ ],
+ stability: "vintf",
+ backend: {
+ cpp: {
+ enabled: false,
+ },
+ java: {
+ enabled: false,
+ },
+ ndk: {
+ vndk: {
+ enabled: true,
+ },
+ },
+ },
+}
diff --git a/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/AdditionalInfo.aidl b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/AdditionalInfo.aidl
new file mode 100644
index 0000000..5184723
--- /dev/null
+++ b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/AdditionalInfo.aidl
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.sensors;
+@FixedSize @VintfStability
+parcelable AdditionalInfo {
+ android.hardware.sensors.AdditionalInfo.AdditionalInfoType type;
+ int serial;
+ android.hardware.sensors.AdditionalInfo.AdditionalInfoPayload payload;
+ @FixedSize @VintfStability
+ union AdditionalInfoPayload {
+ android.hardware.sensors.AdditionalInfo.AdditionalInfoPayload.Int32Values dataInt32;
+ android.hardware.sensors.AdditionalInfo.AdditionalInfoPayload.FloatValues dataFloat;
+ @FixedSize @VintfStability
+ parcelable Int32Values {
+ int[14] values;
+ }
+ @FixedSize @VintfStability
+ parcelable FloatValues {
+ float[14] values;
+ }
+ }
+ @Backing(type="int") @VintfStability
+ enum AdditionalInfoType {
+ AINFO_BEGIN = 0,
+ AINFO_END = 1,
+ AINFO_UNTRACKED_DELAY = 65536,
+ AINFO_INTERNAL_TEMPERATURE = 65537,
+ AINFO_VEC3_CALIBRATION = 65538,
+ AINFO_SENSOR_PLACEMENT = 65539,
+ AINFO_SAMPLING = 65540,
+ AINFO_CHANNEL_NOISE = 131072,
+ AINFO_CHANNEL_SAMPLER = 131073,
+ AINFO_CHANNEL_FILTER = 131074,
+ AINFO_CHANNEL_LINEAR_TRANSFORM = 131075,
+ AINFO_CHANNEL_NONLINEAR_MAP = 131076,
+ AINFO_CHANNEL_RESAMPLER = 131077,
+ AINFO_LOCAL_GEOMAGNETIC_FIELD = 196608,
+ AINFO_LOCAL_GRAVITY = 196609,
+ AINFO_DOCK_STATE = 196610,
+ AINFO_HIGH_PERFORMANCE_MODE = 196611,
+ AINFO_MAGNETIC_FIELD_CALIBRATION = 196612,
+ AINFO_CUSTOM_START = 268435456,
+ AINFO_DEBUGGING_START = 1073741824,
+ }
+}
diff --git a/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/DynamicSensorInfo.aidl b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/DynamicSensorInfo.aidl
new file mode 100644
index 0000000..0c9a493
--- /dev/null
+++ b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/DynamicSensorInfo.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.sensors;
+@FixedSize @VintfStability
+parcelable DynamicSensorInfo {
+ boolean connected;
+ int sensorHandle;
+ android.hardware.sensors.DynamicSensorInfo.Uuid uuid;
+ @FixedSize @VintfStability
+ parcelable Uuid {
+ byte[16] values;
+ }
+}
diff --git a/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/Event.aidl b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/Event.aidl
new file mode 100644
index 0000000..186b2be
--- /dev/null
+++ b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/Event.aidl
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.sensors;
+@FixedSize @VintfStability
+parcelable Event {
+ long timestamp;
+ int sensorHandle;
+ android.hardware.sensors.SensorType sensorType;
+ android.hardware.sensors.Event.EventPayload payload;
+ @FixedSize @VintfStability
+ union EventPayload {
+ android.hardware.sensors.Event.EventPayload.Vec3 vec3;
+ android.hardware.sensors.Event.EventPayload.Vec4 vec4;
+ android.hardware.sensors.Event.EventPayload.Uncal uncal;
+ android.hardware.sensors.Event.EventPayload.MetaData meta;
+ float scalar;
+ long stepCount;
+ android.hardware.sensors.Event.EventPayload.HeartRate heartRate;
+ android.hardware.sensors.Event.EventPayload.Pose6Dof pose6DOF;
+ android.hardware.sensors.DynamicSensorInfo dynamic;
+ android.hardware.sensors.AdditionalInfo additional;
+ android.hardware.sensors.Event.EventPayload.Data data;
+ @FixedSize @VintfStability
+ parcelable Vec4 {
+ float x;
+ float y;
+ float z;
+ float w;
+ }
+ @FixedSize @VintfStability
+ parcelable Vec3 {
+ float x;
+ float y;
+ float z;
+ android.hardware.sensors.SensorStatus status;
+ }
+ @FixedSize @VintfStability
+ parcelable Uncal {
+ float x;
+ float y;
+ float z;
+ float xBias;
+ float yBias;
+ float zBias;
+ }
+ @FixedSize @VintfStability
+ parcelable HeartRate {
+ float bpm;
+ android.hardware.sensors.SensorStatus status;
+ }
+ @FixedSize @VintfStability
+ parcelable MetaData {
+ android.hardware.sensors.Event.EventPayload.MetaData.MetaDataEventType what;
+ @Backing(type="int") @VintfStability
+ enum MetaDataEventType {
+ META_DATA_FLUSH_COMPLETE = 1,
+ }
+ }
+ @FixedSize @VintfStability
+ parcelable Pose6Dof {
+ float[15] values;
+ }
+ @FixedSize @VintfStability
+ parcelable Data {
+ float[16] values;
+ }
+ }
+}
diff --git a/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/ISensors.aidl b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/ISensors.aidl
new file mode 100644
index 0000000..f60f5bb
--- /dev/null
+++ b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/ISensors.aidl
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.sensors;
+@VintfStability
+interface ISensors {
+ void activate(in int sensorHandle, in boolean enabled);
+ void batch(in int sensorHandle, in long samplingPeriodNs, in long maxReportLatencyNs);
+ int configDirectReport(in int sensorHandle, in int channelHandle, in android.hardware.sensors.ISensors.RateLevel rate);
+ void flush(in int sensorHandle);
+ android.hardware.sensors.SensorInfo[] getSensorsList();
+ void initialize(in android.hardware.common.fmq.MQDescriptor<android.hardware.sensors.Event,android.hardware.common.fmq.SynchronizedReadWrite> eventQueueDescriptor, in android.hardware.common.fmq.MQDescriptor<int,android.hardware.common.fmq.SynchronizedReadWrite> wakeLockDescriptor, in android.hardware.sensors.ISensorsCallback sensorsCallback);
+ void injectSensorData(in android.hardware.sensors.Event event);
+ int registerDirectChannel(in android.hardware.sensors.ISensors.SharedMemInfo mem);
+ void setOperationMode(in android.hardware.sensors.ISensors.OperationMode mode);
+ void unregisterDirectChannel(in int channelHandle);
+ const int ERROR_NO_MEMORY = -12;
+ const int ERROR_BAD_VALUE = -22;
+ const int WAKE_LOCK_TIMEOUT_SECONDS = 1;
+ const int EVENT_QUEUE_FLAG_BITS_READ_AND_PROCESS = 1;
+ const int EVENT_QUEUE_FLAG_BITS_EVENTS_READ = 2;
+ const int WAKE_LOCK_QUEUE_FLAG_BITS_DATA_WRITTEN = 1;
+ const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_FIELD = 0;
+ const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_REPORT_TOKEN = 4;
+ const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_SENSOR_TYPE = 8;
+ const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_ATOMIC_COUNTER = 12;
+ const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_TIMESTAMP = 16;
+ const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_DATA = 24;
+ const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_RESERVED = 88;
+ const int DIRECT_REPORT_SENSOR_EVENT_TOTAL_LENGTH = 104;
+ @Backing(type="int") @VintfStability
+ enum RateLevel {
+ STOP = 0,
+ NORMAL = 1,
+ FAST = 2,
+ VERY_FAST = 3,
+ }
+ @Backing(type="int") @VintfStability
+ enum OperationMode {
+ NORMAL = 0,
+ DATA_INJECTION = 1,
+ }
+ @VintfStability
+ parcelable SharedMemInfo {
+ android.hardware.sensors.ISensors.SharedMemInfo.SharedMemType type;
+ android.hardware.sensors.ISensors.SharedMemInfo.SharedMemFormat format;
+ int size;
+ android.hardware.common.NativeHandle memoryHandle;
+ @Backing(type="int") @VintfStability
+ enum SharedMemFormat {
+ SENSORS_EVENT = 1,
+ }
+ @Backing(type="int") @VintfStability
+ enum SharedMemType {
+ ASHMEM = 1,
+ GRALLOC = 2,
+ }
+ }
+}
diff --git a/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/ISensorsCallback.aidl b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/ISensorsCallback.aidl
new file mode 100644
index 0000000..78ab567
--- /dev/null
+++ b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/ISensorsCallback.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.sensors;
+@VintfStability
+interface ISensorsCallback {
+ void onDynamicSensorsConnected(in android.hardware.sensors.SensorInfo[] sensorInfos);
+ void onDynamicSensorsDisconnected(in int[] sensorHandles);
+}
diff --git a/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorInfo.aidl b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorInfo.aidl
new file mode 100644
index 0000000..996be3d
--- /dev/null
+++ b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorInfo.aidl
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.sensors;
+@VintfStability
+parcelable SensorInfo {
+ int sensorHandle;
+ String name;
+ String vendor;
+ int version;
+ android.hardware.sensors.SensorType type;
+ String typeAsString;
+ float maxRange;
+ float resolution;
+ float power;
+ int minDelayUs;
+ int fifoReservedEventCount;
+ int fifoMaxEventCount;
+ String requiredPermission;
+ int maxDelayUs;
+ int flags;
+ const int SENSOR_FLAG_BITS_WAKE_UP = 1;
+ const int SENSOR_FLAG_BITS_CONTINUOUS_MODE = 0;
+ const int SENSOR_FLAG_BITS_ON_CHANGE_MODE = 2;
+ const int SENSOR_FLAG_BITS_ONE_SHOT_MODE = 4;
+ const int SENSOR_FLAG_BITS_SPECIAL_REPORTING_MODE = 6;
+ const int SENSOR_FLAG_BITS_DATA_INJECTION = 16;
+ const int SENSOR_FLAG_BITS_DYNAMIC_SENSOR = 32;
+ const int SENSOR_FLAG_BITS_ADDITIONAL_INFO = 64;
+ const int SENSOR_FLAG_BITS_DIRECT_CHANNEL_ASHMEM = 1024;
+ const int SENSOR_FLAG_BITS_DIRECT_CHANNEL_GRALLOC = 2048;
+ const int SENSOR_FLAG_BITS_MASK_REPORTING_MODE = 14;
+ const int SENSOR_FLAG_BITS_MASK_DIRECT_REPORT = 896;
+ const int SENSOR_FLAG_BITS_MASK_DIRECT_CHANNEL = 3072;
+ const int SENSOR_FLAG_SHIFT_REPORTING_MODE = 1;
+ const int SENSOR_FLAG_SHIFT_DATA_INJECTION = 4;
+ const int SENSOR_FLAG_SHIFT_DYNAMIC_SENSOR = 5;
+ const int SENSOR_FLAG_SHIFT_ADDITIONAL_INFO = 6;
+ const int SENSOR_FLAG_SHIFT_DIRECT_REPORT = 7;
+ const int SENSOR_FLAG_SHIFT_DIRECT_CHANNEL = 10;
+}
diff --git a/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorStatus.aidl b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorStatus.aidl
new file mode 100644
index 0000000..4521710
--- /dev/null
+++ b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorStatus.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.sensors;
+@Backing(type="byte") @VintfStability
+enum SensorStatus {
+ NO_CONTACT = -1,
+ UNRELIABLE = 0,
+ ACCURACY_LOW = 1,
+ ACCURACY_MEDIUM = 2,
+ ACCURACY_HIGH = 3,
+}
diff --git a/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorType.aidl b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorType.aidl
new file mode 100644
index 0000000..4f3b5b2
--- /dev/null
+++ b/sensors/aidl/aidl_api/android.hardware.sensors/current/android/hardware/sensors/SensorType.aidl
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.sensors;
+@Backing(type="int") @VintfStability
+enum SensorType {
+ META_DATA = 0,
+ ACCELEROMETER = 1,
+ MAGNETIC_FIELD = 2,
+ ORIENTATION = 3,
+ GYROSCOPE = 4,
+ LIGHT = 5,
+ PRESSURE = 6,
+ PROXIMITY = 8,
+ GRAVITY = 9,
+ LINEAR_ACCELERATION = 10,
+ ROTATION_VECTOR = 11,
+ RELATIVE_HUMIDITY = 12,
+ AMBIENT_TEMPERATURE = 13,
+ MAGNETIC_FIELD_UNCALIBRATED = 14,
+ GAME_ROTATION_VECTOR = 15,
+ GYROSCOPE_UNCALIBRATED = 16,
+ SIGNIFICANT_MOTION = 17,
+ STEP_DETECTOR = 18,
+ STEP_COUNTER = 19,
+ GEOMAGNETIC_ROTATION_VECTOR = 20,
+ HEART_RATE = 21,
+ TILT_DETECTOR = 22,
+ WAKE_GESTURE = 23,
+ GLANCE_GESTURE = 24,
+ PICK_UP_GESTURE = 25,
+ WRIST_TILT_GESTURE = 26,
+ DEVICE_ORIENTATION = 27,
+ POSE_6DOF = 28,
+ STATIONARY_DETECT = 29,
+ MOTION_DETECT = 30,
+ HEART_BEAT = 31,
+ DYNAMIC_SENSOR_META = 32,
+ ADDITIONAL_INFO = 33,
+ LOW_LATENCY_OFFBODY_DETECT = 34,
+ ACCELEROMETER_UNCALIBRATED = 35,
+ HINGE_ANGLE = 36,
+ DEVICE_PRIVATE_BASE = 65536,
+}
diff --git a/sensors/aidl/android/hardware/sensors/AdditionalInfo.aidl b/sensors/aidl/android/hardware/sensors/AdditionalInfo.aidl
new file mode 100644
index 0000000..9fe2d39
--- /dev/null
+++ b/sensors/aidl/android/hardware/sensors/AdditionalInfo.aidl
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.sensors;
+
+@FixedSize
+@VintfStability
+parcelable AdditionalInfo {
+ /**
+ * type of payload data, see AdditionalInfoType
+ */
+ AdditionalInfoType type;
+
+ /**
+ * sequence number of this frame for this type
+ */
+ int serial;
+
+ AdditionalInfoPayload payload;
+
+ @FixedSize
+ @VintfStability
+ union AdditionalInfoPayload {
+ Int32Values dataInt32;
+ FloatValues dataFloat;
+
+ @FixedSize
+ @VintfStability
+ parcelable Int32Values {
+ int[14] values;
+ }
+
+ @FixedSize
+ @VintfStability
+ parcelable FloatValues {
+ float[14] values;
+ }
+ }
+
+ @VintfStability
+ @Backing(type="int")
+ enum AdditionalInfoType {
+ /**
+ * Marks the beginning of additional information frames
+ */
+ AINFO_BEGIN = 0,
+
+ /**
+ * Marks the end of additional information frames
+ */
+ AINFO_END = 1,
+
+ /**
+ * Estimation of the delay that is not tracked by sensor timestamps. This
+ * includes delay introduced by sensor front-end filtering, data transport,
+ * etc.
+ * float[2]: delay in seconds, standard deviation of estimated value
+ */
+ AINFO_UNTRACKED_DELAY = 0x10000,
+
+ /**
+ * float: Celsius temperature
+ */
+ AINFO_INTERNAL_TEMPERATURE,
+
+ /**
+ * First three rows of a homogeneous matrix, which represents calibration to
+ * a three-element vector raw sensor reading.
+ * float[12]: 3x4 matrix in row major order
+ */
+ AINFO_VEC3_CALIBRATION,
+
+ /**
+ * Provides the orientation and location of the sensor element in terms of
+ * the Android coordinate system. This data is given as a 3x4 matrix
+ * consisting of a 3x3 rotation matrix (R) concatenated with a 3x1 location
+ * vector (t). The rotation matrix provides the orientation of the Android
+ * device coordinate frame relative to the local coordinate frame of the
+ * sensor. Note that assuming the axes conventions of the sensor are the
+ * same as Android, this is the inverse of the matrix applied to raw
+ * samples read from the sensor to convert them into the Android
+ * representation. The location vector represents the translation from the
+ * origin of the Android sensor coordinate system to the geometric center
+ * of the sensor, specified in millimeters (mm).
+ *
+ * float[12]: 3x4 matrix in row major order [R; t]
+ *
+ * Example:
+ * This raw buffer: {0, 1, 0, 0, -1, 0, 0, 10, 0, 0, 1, -2.5}
+ * Corresponds to this 3x4 matrix:
+ * 0 1 0 0
+ * -1 0 0 10
+ * 0 0 1 -2.5
+ * The sensor is oriented such that:
+ * - the device X axis corresponds to the sensor's local -Y axis
+ * - the device Y axis corresponds to the sensor's local X axis
+ * - the device Z axis and sensor's local Z axis are equivalent
+ * In other words, if viewing the origin of the Android coordinate
+ * system from the positive Z direction, the device coordinate frame is
+ * to be rotated 90 degrees counter-clockwise about the Z axis to align
+ * with the sensor's local coordinate frame. Equivalently, a vector in
+ * the Android coordinate frame may be multiplied with R to rotate it
+ * 90 degrees clockwise (270 degrees counter-clockwise), yielding its
+ * representation in the sensor's coordinate frame.
+ * Relative to the origin of the Android coordinate system, the physical
+ * center of the sensor is located 10mm in the positive Y direction, and
+ * 2.5mm in the negative Z direction.
+ */
+ AINFO_SENSOR_PLACEMENT,
+
+ /**
+ * float[2]: raw sample period in seconds,
+ * standard deviation of sampling period
+ */
+ AINFO_SAMPLING,
+
+ /**
+ * int32_t: noise type
+ * float[n]: parameters
+ */
+ AINFO_CHANNEL_NOISE = 0x20000,
+
+ /**
+ * float[3]: sample period, standard deviation of sample period,
+ * quantization unit
+ */
+ AINFO_CHANNEL_SAMPLER,
+
+ /**
+ * Represents a filter:
+ * \sum_j a_j y[n-j] == \sum_i b_i x[n-i]
+ *
+ * int32_t[3]: number of feedforward coeffients M,
+ * number of feedback coefficients N (for FIR filter, N = 1).
+ * bit mask that represents which element the filter is applied
+ * to. (bit 0==1 means this filter applies to vector element 0).
+ * float[M+N]: filter coefficients (b0, b1, ..., b_{M-1}), then
+ * (a0, a1, ..., a_{N-1}), a0 is always 1.
+ *
+ * Multiple frames may be needed for higher number of taps.
+ */
+ AINFO_CHANNEL_FILTER,
+
+ /**
+ * int32_t[2]: size in (row, column) ... 1st frame
+ * float[n]: matrix element values in row major order.
+ */
+ AINFO_CHANNEL_LINEAR_TRANSFORM,
+
+ /**
+ * int32_t[2]: extrapolate method, interpolate method
+ * float[n]: mapping key points in pairs, (in, out)...
+ * (may be used to model saturation).
+ */
+ AINFO_CHANNEL_NONLINEAR_MAP,
+
+ /**
+ * int32_t: resample method (0-th order, 1st order...)
+ * float[1]: resample ratio (upsampling if < 1.0, downsampling if > 1.0).
+ */
+ AINFO_CHANNEL_RESAMPLER,
+
+ /**
+ * Operation environment parameters section
+ * Types in the following section is sent down (instead of reported from)
+ * device as additional information to aid sensor operation. Data is sent
+ * via injectSensorData() function to sensor handle -1 denoting all sensors
+ * in device.
+ *
+ *
+ * Local geomagnetic field information based on device geo location. This
+ * type is primarily for for magnetic field calibration and rotation vector
+ * sensor fusion.
+ * float[3]: strength (uT), declination and inclination angle (rad).
+ */
+ AINFO_LOCAL_GEOMAGNETIC_FIELD = 0x30000,
+
+ /**
+ * Local gravitational acceleration strength at device geo location.
+ * float: gravitational acceleration norm in m/s^2.
+ */
+ AINFO_LOCAL_GRAVITY,
+
+ /**
+ * Device dock state.
+ * int32_t: dock state following Android API Intent.EXTRA_DOCK_STATE
+ * definition, undefined value is ignored.
+ */
+ AINFO_DOCK_STATE,
+
+ /**
+ * High performance mode hint. Device is able to use up more power and take
+ * more resources to improve throughput and latency in high performance mode.
+ * One possible use case is virtual reality, when sensor latency need to be
+ * carefully controlled.
+ * int32_t: 1 or 0, denote if device is in/out of high performance mode,
+ * other values is ignored.
+ */
+ AINFO_HIGH_PERFORMANCE_MODE,
+
+ /**
+ * Magnetic field calibration hint. Device is notified when manually
+ * triggered magnetic field calibration procedure is started or stopped. The
+ * calibration procedure is assumed timed out after 1 minute from start,
+ * even if an explicit stop is not received.
+ *
+ * int32_t: 1 for start, 0 for stop, other value is ignored.
+ */
+ AINFO_MAGNETIC_FIELD_CALIBRATION,
+
+ /**
+ * Custom information
+ */
+ AINFO_CUSTOM_START = 0x10000000,
+
+ /**
+ * Debugging
+ */
+ AINFO_DEBUGGING_START = 0x40000000,
+ }
+}
diff --git a/sensors/aidl/android/hardware/sensors/DynamicSensorInfo.aidl b/sensors/aidl/android/hardware/sensors/DynamicSensorInfo.aidl
new file mode 100644
index 0000000..4b14ed0
--- /dev/null
+++ b/sensors/aidl/android/hardware/sensors/DynamicSensorInfo.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.sensors;
+
+@VintfStability
+@FixedSize
+parcelable DynamicSensorInfo {
+ boolean connected;
+
+ int sensorHandle;
+
+ /**
+ * UUID of a dynamic sensor (using RFC 4122 byte order)
+ * For UUID 12345678-90AB-CDEF-1122-334455667788 the uuid field is
+ * initialized as:
+ * {0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x11, ...}
+ */
+ Uuid uuid;
+
+ @FixedSize
+ @VintfStability
+ parcelable Uuid {
+ byte[16] values;
+ }
+}
diff --git a/sensors/aidl/android/hardware/sensors/Event.aidl b/sensors/aidl/android/hardware/sensors/Event.aidl
new file mode 100644
index 0000000..6ef9acb
--- /dev/null
+++ b/sensors/aidl/android/hardware/sensors/Event.aidl
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.sensors;
+
+import android.hardware.sensors.AdditionalInfo;
+import android.hardware.sensors.DynamicSensorInfo;
+import android.hardware.sensors.SensorStatus;
+import android.hardware.sensors.SensorType;
+
+@VintfStability
+@FixedSize
+parcelable Event {
+ /**
+ * Time measured in nanoseconds, in "elapsedRealtimeNano()'s" timebase.
+ */
+ long timestamp;
+
+ /**
+ * sensor identifier
+ */
+ int sensorHandle;
+
+ SensorType sensorType;
+
+ /**
+ * Union discriminated on sensorType
+ */
+ EventPayload payload;
+
+ /*
+ * acceleration values are in meter per second per second (m/s^2)
+ * magnetic vector values are in micro-Tesla (uT)
+ * orientation values are in degrees
+ * gyroscope values are in rad/s
+ * temperature is in degrees centigrade (Celsius)
+ * distance in centimeters
+ * light in SI lux units
+ * pressure in hectopascal (hPa)
+ * relative humidity in percent
+ */
+ @VintfStability
+ @FixedSize
+ union EventPayload {
+ /**
+ * SensorType::ACCELEROMETER, SensorType::MAGNETIC_FIELD,
+ * SensorType::ORIENTATION, SensorType::GYROSCOPE, SensorType::GRAVITY,
+ * SensorType::LINEAR_ACCELERATION
+ */
+ Vec3 vec3;
+
+ /**
+ * SensorType::GAME_ROTATION_VECTOR
+ */
+ Vec4 vec4;
+
+ /**
+ * SensorType::MAGNETIC_FIELD_UNCALIBRATED,
+ * SensorType::GYROSCOPE_UNCALIBRATED
+ * SensorType::ACCELEROMETER_UNCALIBRATED
+ */
+ Uncal uncal;
+
+ /**
+ * SensorType::META_DATA
+ */
+ MetaData meta;
+
+ /**
+ * SensorType::DEVICE_ORIENTATION, SensorType::LIGHT, SensorType::PRESSURE,
+ * SensorType::TEMPERATURE, SensorType::PROXIMITY,
+ * SensorType::RELATIVE_HUMIDITY, SensorType::AMBIENT_TEMPERATURE,
+ * SensorType::SIGNIFICANT_MOTION, SensorType::STEP_DETECTOR,
+ * SensorType::TILT_DETECTOR, SensorType::WAKE_GESTURE,
+ * SensorType::GLANCE_GESTURE, SensorType::PICK_UP_GESTURE,
+ * SensorType::WRIST_TILT_GESTURE, SensorType::STATIONARY_DETECT,
+ * SensorType::MOTION_DETECT, SensorType::HEART_BEAT,
+ * SensorType::LOW_LATENCY_OFFBODY_DETECT
+ */
+ float scalar;
+
+ /**
+ * SensorType::STEP_COUNTER
+ */
+ long stepCount;
+
+ /**
+ * SensorType::HEART_RATE
+ */
+ HeartRate heartRate;
+
+ /**
+ * SensorType::POSE_6DOF
+ */
+ Pose6Dof pose6DOF;
+
+ /**
+ * SensorType::DYNAMIC_SENSOR_META
+ */
+ DynamicSensorInfo dynamic;
+
+ /**
+ * SensorType::ADDITIONAL_INFO
+ */
+ AdditionalInfo additional;
+
+ /**
+ * The following sensors should use the data field:
+ * - Undefined/custom sensor type >= SensorType::DEVICE_PRIVATE_BASE
+ * - SensorType::ROTATION_VECTOR, SensorType::GEOMAGNETIC_ROTATION_VECTOR:
+ * - These are Vec4 types with an additional float accuracy field,
+ * where data[4] is the estimated heading accuracy in radians
+ * (-1 if unavailable, and invalid if not in the range (0, 2 * pi]).
+ */
+ Data data;
+
+ @FixedSize
+ @VintfStability
+ parcelable Vec4 {
+ float x;
+ float y;
+ float z;
+ float w;
+ }
+
+ @FixedSize
+ @VintfStability
+ parcelable Vec3 {
+ float x;
+ float y;
+ float z;
+ SensorStatus status;
+ }
+
+ @FixedSize
+ @VintfStability
+ parcelable Uncal {
+ float x;
+ float y;
+ float z;
+ float xBias;
+ float yBias;
+ float zBias;
+ }
+
+ @FixedSize
+ @VintfStability
+ parcelable HeartRate {
+ /**
+ * Heart rate in beats per minute.
+ * Set to 0 when status is SensorStatus::UNRELIABLE or
+ * SensorStatus::NO_CONTACT
+ */
+ float bpm;
+ /**
+ * Status of the heart rate sensor for this reading.
+ */
+ SensorStatus status;
+ }
+
+ @FixedSize
+ @VintfStability
+ parcelable MetaData {
+ MetaDataEventType what;
+
+ @VintfStability
+ @Backing(type="int")
+ enum MetaDataEventType {
+ META_DATA_FLUSH_COMPLETE = 1,
+ }
+ }
+
+ @FixedSize
+ @VintfStability
+ parcelable Pose6Dof {
+ float[15] values;
+ }
+
+ @FixedSize
+ @VintfStability
+ parcelable Data {
+ float[16] values;
+ }
+ }
+}
diff --git a/sensors/aidl/android/hardware/sensors/ISensors.aidl b/sensors/aidl/android/hardware/sensors/ISensors.aidl
new file mode 100644
index 0000000..2ac1884
--- /dev/null
+++ b/sensors/aidl/android/hardware/sensors/ISensors.aidl
@@ -0,0 +1,375 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.sensors;
+
+import android.hardware.common.NativeHandle;
+import android.hardware.common.fmq.MQDescriptor;
+import android.hardware.common.fmq.SynchronizedReadWrite;
+import android.hardware.sensors.Event;
+import android.hardware.sensors.ISensorsCallback;
+import android.hardware.sensors.SensorInfo;
+
+@VintfStability
+interface ISensors {
+ /**
+ * Activate/de-activate one sensor.
+ *
+ * After sensor de-activation, existing sensor events that have not
+ * been written to the event queue must be abandoned immediately so that
+ * subsequent activations do not get stale sensor events (events
+ * that are generated prior to the latter activation).
+ *
+ * @param sensorHandle is the handle of the sensor to change.
+ * @param enabled set to true to enable, or false to disable the sensor.
+ * @return Status::ok on success
+ * EX_ILLEGAL_ARGUMENT if the sensorHandle is invalid.
+ */
+ void activate(in int sensorHandle, in boolean enabled);
+
+ /**
+ * Sets a sensor’s parameters, including sampling frequency and maximum
+ * report latency. This function can be called while the sensor is
+ * activated, in which case it must not cause any sensor measurements to
+ * be lost: transitioning from one sampling rate to the other cannot cause
+ * lost events, nor can transitioning from a high maximum report latency to
+ * a low maximum report latency.
+ *
+ * @param sensorHandle handle of sensor to be changed.
+ * @param samplingPeriodNs specifies sensor sample period in nanoseconds.
+ * @param maxReportLatencyNs allowed delay time before an event is sampled
+ * to time of report.
+ * @return Status::ok on success
+ * EX_ILLEGAL_ARGUMENT if any parameters are invalid.
+ */
+ void batch(in int sensorHandle, in long samplingPeriodNs, in long maxReportLatencyNs);
+
+ /**
+ * Configure direct sensor event report in direct channel.
+ *
+ * This function start, modify rate or stop direct report of a sensor in a
+ * certain direct channel.
+ *
+ * @param sensorHandle handle of sensor to be configured. When combined
+ * with STOP rate, sensorHandle can be -1 to denote all active sensors
+ * in the direct channel specified by channel Handle.
+ * @param channelHandle handle of direct channel to be configured.
+ * @param rate rate level, see RateLevel enum.
+ * @param out reportToken The report token, ignored if rate is STOP.
+ * See SharedMemFormat.
+ * @return The direct report token to identify multiple sensors of the same type in a single
+ * direct channel.
+ * @return Status::ok on success
+ * EX_ILLEGAL_ARGUMENT if the parameter is invalid (e.g. unsupported rate level
+ * for sensor, channelHandle does not exist, etc).
+ * EX_UNSUPPORTED_OPERATION if this functionality is unsupported.
+ */
+ int configDirectReport(in int sensorHandle, in int channelHandle, in RateLevel rate);
+
+ /**
+ * Trigger a flush of internal FIFO.
+ *
+ * Flush adds a FLUSH_COMPLETE metadata event to the end of the "batch mode"
+ * FIFO for the specified sensor and flushes the FIFO. If the FIFO is empty
+ * or if the sensor doesn't support batching (FIFO size zero), return
+ * SUCCESS and add a trivial FLUSH_COMPLETE event added to the event stream.
+ * This applies to all sensors other than one-shot sensors. If the sensor
+ * is a one-shot sensor, flush must return EX_ILLEGAL_ARGUMENT and not generate any
+ * flush complete metadata. If the sensor is not active at the time flush()
+ * is called, flush() return EX_ILLEGAL_ARGUMENT.
+ *
+ * @param sensorHandle handle of sensor to be flushed.
+ * @return Status::ok on success
+ * EX_ILLEGAL_ARGUMENT if the sensorHandle is invalid.
+ */
+ void flush(in int sensorHandle);
+
+ /**
+ * Enumerate all available (static) sensors.
+ *
+ * The SensorInfo for each sensor returned by getSensorsList must be stable
+ * from the initial call to getSensorsList after a device boot until the
+ * entire system restarts. The SensorInfo for each sensor must not change
+ * between subsequent calls to getSensorsList, even across restarts of the
+ * HAL and its dependencies (for example, the sensor handle for a given
+ * sensor must not change across HAL restarts).
+ */
+ SensorInfo[] getSensorsList();
+
+ /**
+ * Initialize the Sensors HAL's Fast Message Queues (FMQ) and callback.
+ *
+ * The Fast Message Queues (FMQ) that are used to send data between the
+ * framework and the HAL. The callback is used by the HAL to notify the
+ * framework of asynchronous events, such as a dynamic sensor connection.
+ *
+ * The Event FMQ is used to transport sensor events from the HAL to the
+ * framework. The Event FMQ is created using the eventQueueDescriptor.
+ * Data may only be written to the Event FMQ. Data must not be read from
+ * the Event FMQ since the framework is the only reader. Upon receiving
+ * sensor events, the HAL writes the sensor events to the Event FMQ.
+ *
+ * Once the HAL is finished writing sensor events to the Event FMQ, the HAL
+ * must notify the framework that sensor events are available to be read and
+ * processed. This is accomplished by either:
+ * 1) Calling the Event FMQ’s EventFlag::wake() function with
+ * EventQueueFlagBits::READ_AND_PROCESS
+ * 2) Setting the write notification in the Event FMQ’s writeBlocking()
+ * function to EventQueueFlagBits::READ_AND_PROCESS.
+ *
+ * If the Event FMQ’s writeBlocking() function is used, the read
+ * notification must be set to EventQueueFlagBits::EVENTS_READ in order to
+ * be notified and unblocked when the framework has successfully read events
+ * from the Event FMQ.
+ *
+ * The Wake Lock FMQ is used by the framework to notify the HAL when it is
+ * safe to release its wake_lock. When the framework receives WAKE_UP events
+ * from the Event FMQ and the framework has acquired a wake_lock, the
+ * framework must write the number of WAKE_UP events processed to the Wake
+ * Lock FMQ. When the HAL reads the data from the Wake Lock FMQ, the HAL
+ * decrements its current count of unprocessed WAKE_UP events and releases
+ * its wake_lock if the current count of unprocessed WAKE_UP events is
+ * zero. It is important to note that the HAL must acquire the wake lock and
+ * update its internal state regarding the number of outstanding WAKE_UP
+ * events _before_ posting the event to the Wake Lock FMQ, in order to avoid
+ * a race condition that can lead to loss of wake lock synchronization with
+ * the framework.
+ *
+ * The framework must use the WAKE_LOCK_QUEUE_FLAG_BITS_DATA_WRITTEN value to
+ * notify the HAL that data has been written to the Wake Lock FMQ and must
+ * be read by HAL.
+ *
+ * The ISensorsCallback is used by the HAL to notify the framework of
+ * asynchronous events, such as a dynamic sensor connection.
+ *
+ * The name of any wake_lock acquired by the Sensors HAL for WAKE_UP events
+ * must begin with "SensorsHAL_WAKEUP".
+ *
+ * If WAKE_LOCK_TIMEOUT_SECONDS has elapsed since the most recent WAKE_UP
+ * event was written to the Event FMQ without receiving a message on the
+ * Wake Lock FMQ, then any held wake_lock for WAKE_UP events must be
+ * released.
+ *
+ * If either the Event FMQ or the Wake Lock FMQ is already initialized when
+ * initialize is invoked, then both existing FMQs must be discarded and the
+ * new descriptors must be used to create new FMQs within the HAL. The
+ * number of outstanding WAKE_UP events should also be reset to zero, and
+ * any outstanding wake_locks held as a result of WAKE_UP events should be
+ * released.
+ *
+ * All active sensor requests and direct channels must be closed and
+ * properly cleaned up when initialize is called in order to ensure that the
+ * HAL and framework's state is consistent (e.g. after a runtime restart).
+ *
+ * initialize must be thread safe and prevent concurrent calls
+ * to initialize from simultaneously modifying state.
+ *
+ * @param eventQueueDescriptor Fast Message Queue descriptor that is used to
+ * create the Event FMQ which is where sensor events are written. The
+ * descriptor is obtained from the framework's FMQ that is used to read
+ * sensor events.
+ * @param wakeLockDescriptor Fast Message Queue descriptor that is used to
+ * create the Wake Lock FMQ which is where wake_lock events are read
+ * from. The descriptor is obtained from the framework's FMQ that is
+ * used to write wake_lock events.
+ * @param sensorsCallback sensors callback that receives asynchronous data
+ * from the Sensors HAL.
+ * @return Status::ok on success
+ * EX_ILLEGAL_ARGUMENT if the descriptor is invalid (such as null).
+ */
+ void initialize(in MQDescriptor<Event, SynchronizedReadWrite> eventQueueDescriptor,
+ in MQDescriptor<int, SynchronizedReadWrite> wakeLockDescriptor,
+ in ISensorsCallback sensorsCallback);
+
+ /**
+ * Inject a single sensor event or push operation environment parameters to
+ * device.
+ *
+ * When device is in NORMAL mode, this function is called to push operation
+ * environment data to device. In this operation, Event is always of
+ * SensorType::AdditionalInfo type. See operation environment parameters
+ * section in AdditionalInfoType.
+ *
+ * When device is in DATA_INJECTION mode, this function is also used for
+ * injecting sensor events.
+ *
+ * Regardless of OperationMode, injected SensorType::ADDITIONAL_INFO
+ * type events should not be routed back to the sensor event queue.
+ *
+ * @see AdditionalInfoType
+ * @see OperationMode
+ * @param event sensor event to be injected
+ * @return Status::ok on success
+ * EX_UNSUPPORTED_OPERATION if this functionality is unsupported.
+ * EX_SECURITY if the operation is not allowed.
+ * EX_SERVICE_SPECIFIC on error
+ * - ERROR_BAD_VALUE if the sensor event cannot be injected.
+ */
+ void injectSensorData(in Event event);
+
+ /**
+ * Register direct report channel.
+ *
+ * Register a direct channel with supplied shared memory information. Upon
+ * return, the sensor hardware is responsible for resetting the memory
+ * content to initial value (depending on memory format settings).
+ *
+ * @param mem shared memory info data structure.
+ * @param out channelHandle The registered channel handle.
+ * @return The direct channel handle, which is positive if successfully registered, and -1
+ * otherwise.
+ * @return Status::ok on success
+ * EX_ILLEGAL_ARGUMENT if the shared memory information is not consistent.
+ * EX_UNSUPPORTED_OPERATION if this functionality is unsupported.
+ * EX_SERVICE_SPECIFIC on error
+ * - ERROR_NO_MEMORY if shared memory cannot be used by sensor system.
+ */
+ int registerDirectChannel(in SharedMemInfo mem);
+
+ /**
+ * Place the module in a specific mode.
+ *
+ * @see OperationMode
+ * @param mode The operation mode.
+ * @return Status::ok on success
+ * EX_UNSUPPORTED_OPERATION if requested mode is not supported.
+ * EX_SECURITY if the operation is not allowed.
+ */
+ void setOperationMode(in OperationMode mode);
+
+ /**
+ * Unregister direct report channel.
+ *
+ * Unregister a direct channel previously registered using
+ * registerDirectChannel, and remove all active sensor report configured in
+ * still active sensor report configured in the direct channel.
+ *
+ * @param channelHandle handle of direct channel to be unregistered.
+ * @return Status::ok on success
+ * EX_UNSUPPORTED_OPERATION if direct report is not supported.
+ */
+ void unregisterDirectChannel(in int channelHandle);
+
+ /**
+ * Direct report rate level definition. Except for SENSOR_DIRECT_RATE_STOP, each
+ * rate level covers the range (55%, 220%] * nominal report rate. For example,
+ * if config direct report specify a rate level SENSOR_DIRECT_RATE_FAST, it is
+ * legal for sensor hardware to report event at a rate greater than 110Hz, and
+ * less or equal to 440Hz. Note that rate has to remain steady without variation
+ * before new rate level is configured, i.e. if a sensor is configured to
+ * SENSOR_DIRECT_RATE_FAST and starts to report event at 256Hz, it cannot
+ * change rate to 128Hz after a few seconds of running even if 128Hz is also in
+ * the legal range of SENSOR_DIRECT_RATE_FAST. Thus, it is recommended to
+ * associate report rate with RateLvel statically for single sensor.
+ */
+ @VintfStability
+ @Backing(type="int")
+ enum RateLevel {
+ STOP,
+ NORMAL,
+ FAST,
+ VERY_FAST,
+ }
+
+ @VintfStability
+ @Backing(type="int")
+ enum OperationMode {
+ // Normal operation. Default state of the module.
+ NORMAL = 0,
+ // Loopback mode. Data is injected for the supported sensors by the sensor service in this
+ // mode.
+ DATA_INJECTION = 1,
+ }
+
+ @VintfStability
+ parcelable SharedMemInfo {
+ SharedMemType type;
+ SharedMemFormat format;
+ int size;
+ NativeHandle memoryHandle;
+
+ @VintfStability
+ @Backing(type="int")
+ enum SharedMemFormat {
+ SENSORS_EVENT = 1,
+ }
+
+ @VintfStability
+ @Backing(type="int")
+ enum SharedMemType {
+ ASHMEM = 1,
+ GRALLOC,
+ }
+ }
+
+ /**
+ * Error codes that are used as service specific errors with the AIDL return
+ * value EX_SERVICE_SPECIFIC.
+ */
+ const int ERROR_NO_MEMORY = -12;
+ const int ERROR_BAD_VALUE = -22;
+
+ /**
+ * The maximum number of seconds to wait for a message on the Wake Lock FMQ
+ * before automatically releasing any wake_lock held for a WAKE_UP event.
+ */
+ const int WAKE_LOCK_TIMEOUT_SECONDS = 1;
+
+ /**
+ * Used to notify the Event FMQ that events should be read and processed.
+ */
+ const int EVENT_QUEUE_FLAG_BITS_READ_AND_PROCESS = 1 << 0;
+
+ /**
+ * Used by the framework to signal to the HAL when events have been
+ * successfully read from the Event FMQ.
+ *
+ * If the MessageQueue::writeBlocking function is being used to write sensor
+ * events to the Event FMQ, then the readNotification parameter must be set
+ * to EVENTS_READ.
+ */
+ const int EVENT_QUEUE_FLAG_BITS_EVENTS_READ = 1 << 1;
+
+ /**
+ * Used to notify the HAL that the framework has written data to the Wake
+ * Lock FMQ.
+ */
+ const int WAKE_LOCK_QUEUE_FLAG_BITS_DATA_WRITTEN = 1 << 0;
+
+ /**
+ * Constants related to direct sensor events. The following table illustrates the
+ * data format.
+ *
+ * Offset Type Name
+ * -----------------------------------
+ * 0x0000 int32_t Size (always DIRECT_REPORT_SENSOR_EVENT_TOTAL_LENGTH)
+ * 0x0004 int32_t Sensor report token
+ * 0x0008 int32_t Type (see SensorType.aidl)
+ * 0x000C uint32_t Atomic counter
+ * 0x0010 int64_t Timestamp (see Event.aidl)
+ * 0x0018 float[16]/ Data
+ * int64_t[8]
+ * 0x0058 int32_t[4] Reserved (set to zero)
+ */
+ const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_FIELD = 0x0;
+ const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_REPORT_TOKEN = 0x4;
+ const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_SENSOR_TYPE = 0x8;
+ const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_ATOMIC_COUNTER = 0xC;
+ const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_TIMESTAMP = 0x10;
+ const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_DATA = 0x18;
+ const int DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_RESERVED = 0x58;
+ const int DIRECT_REPORT_SENSOR_EVENT_TOTAL_LENGTH = 104;
+}
diff --git a/sensors/aidl/android/hardware/sensors/ISensorsCallback.aidl b/sensors/aidl/android/hardware/sensors/ISensorsCallback.aidl
new file mode 100644
index 0000000..01bae52
--- /dev/null
+++ b/sensors/aidl/android/hardware/sensors/ISensorsCallback.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.sensors;
+
+import android.hardware.sensors.SensorInfo;
+
+@VintfStability
+interface ISensorsCallback {
+ /**
+ * Notify the framework that new dynamic sensors have been connected.
+ *
+ * If a dynamic sensor was previously connected and has not been
+ * disconnected, then that sensor must not be included in sensorInfos.
+ *
+ * @param sensorInfos vector of SensorInfo for each dynamic sensor that
+ * was connected.
+ */
+ void onDynamicSensorsConnected(in SensorInfo[] sensorInfos);
+
+ /**
+ * Notify the framework that previously connected dynamic sensors have been
+ * disconnected.
+ *
+ * If a dynamic sensor was previously disconnected and has not been
+ * reconnected, then that sensor must not be included in sensorHandles.
+ *
+ * The HAL must ensure that all sensor events from departing dynamic
+ * sensors have been written to the Event FMQ before calling
+ * onDynamicSensorsDisconnected.
+ *
+ * @param sensorHandles vector of sensor handles for each dynamic sensors
+ * that was disconnected.
+ */
+ void onDynamicSensorsDisconnected(in int[] sensorHandles);
+}
diff --git a/sensors/aidl/android/hardware/sensors/SensorInfo.aidl b/sensors/aidl/android/hardware/sensors/SensorInfo.aidl
new file mode 100644
index 0000000..35caf8b
--- /dev/null
+++ b/sensors/aidl/android/hardware/sensors/SensorInfo.aidl
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.sensors;
+
+import android.hardware.sensors.SensorType;
+
+@VintfStability
+parcelable SensorInfo {
+ /**
+ * handle that identifies this sensors. This handle is used to reference
+ * this sensor throughout the HAL API.
+ */
+ int sensorHandle;
+
+ /**
+ * Name of this sensor.
+ * All sensors of the same "type" must have a different "name".
+ */
+ String name;
+
+ /**
+ * vendor of the hardware part
+ */
+ String vendor;
+
+ /**
+ * version of the hardware part + driver. The value of this field
+ * must increase when the driver is updated in a way that changes the
+ * output of this sensor. This is important for fused sensors when the
+ * fusion algorithm is updated.
+ */
+ int version;
+
+ /**
+ * this sensor's type.
+ */
+ SensorType type;
+
+ /**
+ * type of this sensor as a string.
+ *
+ * When defining an OEM specific sensor or sensor manufacturer specific
+ * sensor, use your reserve domain name as a prefix.
+ * e.g. com.google.glass.onheaddetector
+ *
+ * For sensors of known type defined in SensorType (value <
+ * SensorType::DEVICE_PRIVATE_BASE), this can be an empty string.
+ */
+ String typeAsString;
+
+ /**
+ * maximum range of this sensor's value in SI units
+ */
+ float maxRange;
+
+ /**
+ * smallest difference between two values reported by this sensor
+ */
+ float resolution;
+
+ /**
+ * rough estimate of this sensor's power consumption in mA
+ */
+ float power;
+
+ /**
+ * this value depends on the reporting mode:
+ *
+ * continuous: minimum sample period allowed in microseconds
+ * on-change : 0
+ * one-shot :-1
+ * special : 0, unless otherwise noted
+ */
+ int minDelayUs;
+
+ /**
+ * number of events reserved for this sensor in the batch mode FIFO.
+ * If there is a dedicated FIFO for this sensor, then this is the
+ * size of this FIFO. If the FIFO is shared with other sensors,
+ * this is the size reserved for that sensor and it can be zero.
+ */
+ int fifoReservedEventCount;
+
+ /**
+ * maximum number of events of this sensor that could be batched.
+ * This is especially relevant when the FIFO is shared between
+ * several sensors; this value is then set to the size of that FIFO.
+ */
+ int fifoMaxEventCount;
+
+ /**
+ * permission required to see this sensor, register to it and receive data.
+ * Set to "" if no permission is required. Some sensor types like the
+ * heart rate monitor have a mandatory require_permission.
+ * For sensors that always require a specific permission, like the heart
+ * rate monitor, the android framework might overwrite this string
+ * automatically.
+ */
+ String requiredPermission;
+
+ /**
+ * This value is defined only for continuous mode and on-change sensors.
+ * It is the delay between two sensor events corresponding to the lowest
+ * frequency that this sensor supports. When lower frequencies are requested
+ * through batch()/setDelay() the events will be generated at this frequency
+ * instead.
+ * It can be used by the framework or applications to estimate when the
+ * batch FIFO may be full.
+ *
+ * continuous, on-change: maximum sampling period allowed in microseconds.
+ * one-shot, special : 0
+ */
+ int maxDelayUs;
+
+ /**
+ * Bitmasks defined in SENSOR_FLAG_BITS_* below.
+ */
+ int flags;
+
+ /**
+ * Whether this sensor wakes up the AP from suspend mode when data is
+ * available. Whenever sensor events are delivered from a wake_up sensor,
+ * the driver needs to hold a wake_lock till the events are read by the
+ * SensorService i.e. till ISensors::poll() is called the next time.
+ * Once poll is called again it means events have been read by the
+ * SensorService, the driver can safely release the wake_lock. SensorService
+ * will continue to hold a wake_lock till the app actually reads the events.
+ */
+ const int SENSOR_FLAG_BITS_WAKE_UP = 1;
+
+ /**
+ * Reporting modes for various sensors. Each sensor will have exactly one of
+ * these modes set.
+ * The least significant 2nd, 3rd and 4th bits are used to represent four
+ * possible reporting modes.
+ */
+ const int SENSOR_FLAG_BITS_CONTINUOUS_MODE = 0;
+ const int SENSOR_FLAG_BITS_ON_CHANGE_MODE = 2;
+ const int SENSOR_FLAG_BITS_ONE_SHOT_MODE = 4;
+ const int SENSOR_FLAG_BITS_SPECIAL_REPORTING_MODE = 6;
+
+ /**
+ * Set this flag if the sensor supports data_injection mode and allows data
+ * to be injected from the SensorService. When in data_injection ONLY
+ * sensors with this flag set are injected sensor data and only sensors with
+ * this flag set are activated. Eg: Accelerometer and Step Counter sensors
+ * can be set with this flag and SensorService will inject accelerometer
+ * data and read the corresponding step counts.
+ */
+ const int SENSOR_FLAG_BITS_DATA_INJECTION = 0x10;
+
+ /**
+ * Set this flag if the sensor is a dynamically connected sensor. See
+ * DynamicSensorInfo and DYNAMIC_SENSOR_META for details.
+ */
+ const int SENSOR_FLAG_BITS_DYNAMIC_SENSOR = 0x20;
+
+ /**
+ * Set this flag if sensor additional information is supported.
+ * See ADDITIONAL_INFO and AdditionalInfo for details.
+ */
+ const int SENSOR_FLAG_BITS_ADDITIONAL_INFO = 0x40;
+
+ /**
+ * Set this flag if sensor suppor direct channel backed by ashmem.
+ * See SharedMemType and registerDirectChannel for more details.
+ */
+ const int SENSOR_FLAG_BITS_DIRECT_CHANNEL_ASHMEM = 0x400;
+
+ /**
+ * Set this flag if sensor suppor direct channel backed by gralloc HAL memory.
+ * See SharedMemType and registerDirectChannel for more details.
+ */
+ const int SENSOR_FLAG_BITS_DIRECT_CHANNEL_GRALLOC = 0x800;
+
+ /**
+ * Flags mask for reporting mode of sensor.
+ */
+ const int SENSOR_FLAG_BITS_MASK_REPORTING_MODE = 0xE;
+
+ /**
+ * Flags mask for direct report maximum rate level support.
+ * See RateLevel.
+ */
+ const int SENSOR_FLAG_BITS_MASK_DIRECT_REPORT = 0x380;
+
+ /**
+ * Flags mask for all direct channel support bits.
+ * See SharedMemType.
+ */
+ const int SENSOR_FLAG_BITS_MASK_DIRECT_CHANNEL = 0xC00;
+
+ /**
+ * Defines the number of bits different pieces of information are shifted in the
+ * SENSOR_FLAG_BITS_* bitmask.
+ */
+ const int SENSOR_FLAG_SHIFT_REPORTING_MODE = 1;
+ const int SENSOR_FLAG_SHIFT_DATA_INJECTION = 4;
+ const int SENSOR_FLAG_SHIFT_DYNAMIC_SENSOR = 5;
+ const int SENSOR_FLAG_SHIFT_ADDITIONAL_INFO = 6;
+ const int SENSOR_FLAG_SHIFT_DIRECT_REPORT = 7;
+ const int SENSOR_FLAG_SHIFT_DIRECT_CHANNEL = 10;
+}
diff --git a/sensors/aidl/android/hardware/sensors/SensorStatus.aidl b/sensors/aidl/android/hardware/sensors/SensorStatus.aidl
new file mode 100644
index 0000000..0fd8697
--- /dev/null
+++ b/sensors/aidl/android/hardware/sensors/SensorStatus.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.sensors;
+
+@VintfStability
+@Backing(type="byte")
+enum SensorStatus {
+ NO_CONTACT = -1,
+ UNRELIABLE = 0,
+ ACCURACY_LOW = 1,
+ ACCURACY_MEDIUM = 2,
+ ACCURACY_HIGH = 3,
+}
diff --git a/sensors/aidl/android/hardware/sensors/SensorType.aidl b/sensors/aidl/android/hardware/sensors/SensorType.aidl
new file mode 100644
index 0000000..95c7a6a
--- /dev/null
+++ b/sensors/aidl/android/hardware/sensors/SensorType.aidl
@@ -0,0 +1,641 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.sensors;
+
+@VintfStability
+@Backing(type="int")
+enum SensorType {
+ /**
+ * META_DATA is a special event type used to populate the MetaData
+ * structure. It doesn't correspond to a physical sensor. Events of this
+ * type exist only inside the HAL, their primary purpose is to signal the
+ * completion of a flush request.
+ */
+ META_DATA = 0,
+
+ /**
+ * ACCELEROMETER
+ * reporting-mode: continuous
+ *
+ * All values are in SI units (m/s^2) and measure the acceleration of the
+ * device minus the acceleration due to gravity.
+ *
+ * Implement the non-wake-up version of this sensor and implement the
+ * wake-up version if the system possesses a wake up fifo.
+ */
+ ACCELEROMETER = 1,
+
+ /**
+ * MAGNETIC_FIELD
+ * reporting-mode: continuous
+ *
+ * All values are in micro-Tesla (uT) and measure the geomagnetic
+ * field in the X, Y and Z axis.
+ *
+ * Implement the non-wake-up version of this sensor and implement the
+ * wake-up version if the system possesses a wake up fifo.
+ */
+ MAGNETIC_FIELD = 2,
+
+ /**
+ * ORIENTATION
+ * reporting-mode: continuous
+ *
+ * All values are angles in degrees.
+ *
+ * Orientation sensors return sensor events for all 3 axes at a constant
+ * rate defined by setDelay().
+ *
+ * Implement the non-wake-up version of this sensor and implement the
+ * wake-up version if the system possesses a wake up fifo.
+ */
+ ORIENTATION = 3,
+
+ /**
+ * GYROSCOPE
+ * reporting-mode: continuous
+ *
+ * All values are in radians/second and measure the rate of rotation
+ * around the X, Y and Z axis.
+ *
+ * Implement the non-wake-up version of this sensor and implement the
+ * wake-up version if the system possesses a wake up fifo.
+ */
+ GYROSCOPE = 4,
+
+ /**
+ * LIGHT
+ * reporting-mode: on-change
+ *
+ * The light sensor value is returned in SI lux units.
+ *
+ * Both wake-up and non wake-up versions are useful.
+ */
+ LIGHT = 5,
+
+ /**
+ * PRESSURE
+ * reporting-mode: continuous
+ *
+ * The pressure sensor return the athmospheric pressure in hectopascal (hPa)
+ *
+ * Implement the non-wake-up version of this sensor and implement the
+ * wake-up version if the system possesses a wake up fifo.
+ */
+ PRESSURE = 6,
+
+ /**
+ * PROXIMITY
+ * reporting-mode: on-change
+ *
+ * The proximity sensor which turns the screen off and back on during calls
+ * is the wake-up proximity sensor. Implement wake-up proximity sensor
+ * before implementing a non wake-up proximity sensor. For the wake-up
+ * proximity sensor set the flag SENSOR_FLAG_WAKE_UP.
+ * The value corresponds to the distance to the nearest object in
+ * centimeters.
+ */
+ PROXIMITY = 8,
+
+ /**
+ * GRAVITY
+ * reporting-mode: continuous
+ *
+ * A gravity output indicates the direction of and magnitude of gravity in
+ * the devices's coordinates.
+ *
+ * Implement the non-wake-up version of this sensor and implement the
+ * wake-up version if the system possesses a wake up fifo.
+ */
+ GRAVITY = 9,
+
+ /**
+ * LINEAR_ACCELERATION
+ * reporting-mode: continuous
+ *
+ * Indicates the linear acceleration of the device in device coordinates,
+ * not including gravity.
+ *
+ * Implement the non-wake-up version of this sensor and implement the
+ * wake-up version if the system possesses a wake up fifo.
+ */
+ LINEAR_ACCELERATION = 10,
+
+ /**
+ * ROTATION_VECTOR
+ * reporting-mode: continuous
+ *
+ * The rotation vector symbolizes the orientation of the device relative to
+ * the East-North-Up coordinates frame.
+ *
+ * Implement the non-wake-up version of this sensor and implement the
+ * wake-up version if the system possesses a wake up fifo.
+ */
+ ROTATION_VECTOR = 11,
+
+ /**
+ * RELATIVE_HUMIDITY
+ * reporting-mode: on-change
+ *
+ * A relative humidity sensor measures relative ambient air humidity and
+ * returns a value in percent.
+ *
+ * Both wake-up and non wake-up versions are useful.
+ */
+ RELATIVE_HUMIDITY = 12,
+
+ /**
+ * AMBIENT_TEMPERATURE
+ * reporting-mode: on-change
+ *
+ * The ambient (room) temperature in degree Celsius.
+ *
+ * Both wake-up and non wake-up versions are useful.
+ */
+ AMBIENT_TEMPERATURE = 13,
+
+ /**
+ * MAGNETIC_FIELD_UNCALIBRATED
+ * reporting-mode: continuous
+ *
+ * Similar to MAGNETIC_FIELD, but the hard iron calibration is
+ * reported separately instead of being included in the measurement.
+ *
+ * Implement the non-wake-up version of this sensor and implement the
+ * wake-up version if the system possesses a wake up fifo.
+ */
+ MAGNETIC_FIELD_UNCALIBRATED = 14,
+
+ /**
+ * GAME_ROTATION_VECTOR
+ * reporting-mode: continuous
+ *
+ * Similar to ROTATION_VECTOR, but not using the geomagnetic
+ * field.
+ *
+ * Implement the non-wake-up version of this sensor and implement the
+ * wake-up version if the system possesses a wake up fifo.
+ */
+ GAME_ROTATION_VECTOR = 15,
+
+ /**
+ * GYROSCOPE_UNCALIBRATED
+ * reporting-mode: continuous
+ *
+ * All values are in radians/second and measure the rate of rotation
+ * around the X, Y and Z axis.
+ *
+ * Implement the non-wake-up version of this sensor and implement the
+ * wake-up version if the system possesses a wake up fifo.
+ */
+ GYROSCOPE_UNCALIBRATED = 16,
+
+ /**
+ * SIGNIFICANT_MOTION
+ * reporting-mode: one-shot
+ *
+ * A sensor of this type triggers an event each time significant motion
+ * is detected and automatically disables itself.
+ * For Significant Motion sensor to be useful, it must be defined as a
+ * wake-up sensor. (set SENSOR_FLAG_WAKE_UP). Implement the wake-up
+ * significant motion sensor. A non wake-up version is not useful.
+ * The only allowed value to return is 1.0.
+ */
+ SIGNIFICANT_MOTION = 17,
+
+ /**
+ * STEP_DETECTOR
+ * reporting-mode: special
+ *
+ * A sensor of this type triggers an event each time a step is taken
+ * by the user. The only allowed value to return is 1.0 and an event
+ * is generated for each step.
+ *
+ * Both wake-up and non wake-up versions are useful.
+ */
+ STEP_DETECTOR = 18,
+
+ /**
+ * STEP_COUNTER
+ * reporting-mode: on-change
+ *
+ * A sensor of this type returns the number of steps taken by the user since
+ * the last reboot while activated. The value is returned as a uint64_t and
+ * is reset to zero only on a system / android reboot.
+ *
+ * Implement the non-wake-up version of this sensor and implement the
+ * wake-up version if the system possesses a wake up fifo.
+ */
+ STEP_COUNTER = 19,
+
+ /**
+ * GEOMAGNETIC_ROTATION_VECTOR
+ * reporting-mode: continuous
+ *
+ * Similar to ROTATION_VECTOR, but using a magnetometer instead
+ * of using a gyroscope.
+ *
+ * Implement the non-wake-up version of this sensor and implement the
+ * wake-up version if the system possesses a wake up fifo.
+ */
+ GEOMAGNETIC_ROTATION_VECTOR = 20,
+
+ /**
+ * HEART_RATE
+ * reporting-mode: on-change
+ *
+ * A sensor of this type returns the current heart rate.
+ * The events contain the current heart rate in beats per minute (BPM) and
+ * the status of the sensor during the measurement. See "HeartRate" below
+ * for more details.
+ *
+ * Because this sensor is on-change, events must be generated when and only
+ * when heart_rate.bpm or heart_rate.status have changed since the last
+ * event. In particular, upon the first activation, unless the device is
+ * known to not be on the body, the status field of the first event must be
+ * set to SensorStatus::UNRELIABLE. The event should be generated no faster
+ * than every period_ns passed to setDelay() or to batch().
+ * See the definition of the on-change reporting mode for more information.
+ *
+ * SensorInfo.requiredPermission must be set to
+ * SENSOR_PERMISSION_BODY_SENSORS.
+ *
+ * Both wake-up and non wake-up versions are useful.
+ */
+ HEART_RATE = 21,
+
+ /**
+ * WAKE_UP_TILT_DETECTOR
+ * reporting-mode: special (setDelay has no impact)
+ *
+ * A sensor of this type generates an event each time a tilt event is
+ * detected. A tilt event must be generated if the direction of the
+ * 2-seconds window average gravity changed by at least 35 degrees since the
+ * activation or the last trigger of the sensor.
+ *
+ * reference_estimated_gravity = average of accelerometer measurements over
+ * the first 1 second after activation or the estimated gravity at the last
+ * trigger.
+ *
+ * current_estimated_gravity = average of accelerometer measurements over
+ * the last 2 seconds.
+ *
+ * trigger when
+ * angle(reference_estimated_gravity, current_estimated_gravity)
+ * > 35 degrees
+ *
+ * Large accelerations without a change in phone orientation must not
+ * trigger a tilt event.
+ * For example, a sharp turn or strong acceleration while driving a car
+ * must not trigger a tilt event, even though the angle of the average
+ * acceleration might vary by more than 35 degrees.
+ *
+ * Typically, this sensor is implemented with the help of only an
+ * accelerometer. Other sensors can be used as well if they do not increase
+ * the power consumption significantly. This is a low power sensor that
+ * must allow the AP to go into suspend mode. Do not emulate this sensor
+ * in the HAL.
+ * Like other wake up sensors, the driver is expected to a hold a wake_lock
+ * with a timeout of 200 ms while reporting this event. The only allowed
+ * return value is 1.0.
+ *
+ * Implement only the wake-up version of this sensor.
+ */
+ TILT_DETECTOR = 22,
+
+ /**
+ * WAKE_GESTURE
+ * reporting-mode: one-shot
+ *
+ * A sensor enabling waking up the device based on a device specific motion.
+ *
+ * When this sensor triggers, the device behaves as if the power button was
+ * pressed, turning the screen on. This behavior (turning on the screen when
+ * this sensor triggers) might be deactivated by the user in the device
+ * settings. Changes in settings do not impact the behavior of the sensor:
+ * only whether the framework turns the screen on when it triggers.
+ *
+ * The actual gesture to be detected is not specified, and can be chosen by
+ * the manufacturer of the device.
+ * This sensor must be low power, as it is likely to be activated 24/7.
+ * The only allowed value to return is 1.0.
+ *
+ * Implement only the wake-up version of this sensor.
+ */
+ WAKE_GESTURE = 23,
+
+ /**
+ * GLANCE_GESTURE
+ * reporting-mode: one-shot
+ *
+ * A sensor enabling briefly turning the screen on to enable the user to
+ * glance content on screen based on a specific motion. The device must
+ * turn the screen off after a few moments.
+ *
+ * When this sensor triggers, the device turns the screen on momentarily
+ * to allow the user to glance notifications or other content while the
+ * device remains locked in a non-interactive state (dozing). This behavior
+ * (briefly turning on the screen when this sensor triggers) might be
+ * deactivated by the user in the device settings.
+ * Changes in settings do not impact the behavior of the sensor: only
+ * whether the framework briefly turns the screen on when it triggers.
+ *
+ * The actual gesture to be detected is not specified, and can be chosen by
+ * the manufacturer of the device.
+ * This sensor must be low power, as it is likely to be activated 24/7.
+ * The only allowed value to return is 1.0.
+ *
+ * Implement only the wake-up version of this sensor.
+ */
+ GLANCE_GESTURE = 24,
+
+ /**
+ * PICK_UP_GESTURE
+ * reporting-mode: one-shot
+ *
+ * A sensor of this type triggers when the device is picked up regardless of
+ * wherever is was before (desk, pocket, bag). The only allowed return value
+ * is 1.0. This sensor de-activates itself immediately after it triggers.
+ *
+ * Implement only the wake-up version of this sensor.
+ */
+ PICK_UP_GESTURE = 25,
+
+ /**
+ * WRIST_TILT_GESTURE
+ * trigger-mode: special
+ * wake-up sensor: yes
+ *
+ * A sensor of this type triggers an event each time a tilt of the
+ * wrist-worn device is detected.
+ *
+ * This sensor must be low power, as it is likely to be activated 24/7.
+ * The only allowed value to return is 1.0.
+ *
+ * Implement only the wake-up version of this sensor.
+ */
+ WRIST_TILT_GESTURE = 26,
+
+ /**
+ * DEVICE_ORIENTATION
+ * reporting-mode: on-change
+ *
+ * The current orientation of the device. The value is reported in
+ * the "scalar" element of the EventPayload in Event. The
+ * only values that can be reported are (please refer to Android Sensor
+ * Coordinate System to understand the X and Y axis direction with respect
+ * to default orientation):
+ * - 0: device is in default orientation (Y axis is vertical and points up)
+ * - 1: device is rotated 90 degrees counter-clockwise from default
+ * orientation (X axis is vertical and points up)
+ * - 2: device is rotated 180 degrees from default orientation (Y axis is
+ * vertical and points down)
+ * - 3: device is rotated 90 degrees clockwise from default orientation
+ * (X axis is vertical and points down)
+ *
+ * Moving the device to an orientation where the Z axis is vertical (either
+ * up or down) must not cause a new event to be reported.
+ *
+ * To improve the user experience of this sensor, it is recommended to
+ * implement some physical (i.e., rotation angle) and temporal (i.e., delay)
+ * hysteresis. In other words, minor or transient rotations must not cause
+ * a new event to be reported.
+ *
+ * This is a low power sensor that intended to reduce interrupts of
+ * application processor and thus allow it to go sleep. Use hardware
+ * implementation based on low power consumption sensors, such as
+ * accelerometer. Device must not emulate this sensor in the HAL.
+ *
+ * Both wake-up and non wake-up versions are useful.
+ */
+ DEVICE_ORIENTATION = 27,
+
+ /**
+ * POSE_6DOF
+ * trigger-mode: continuous
+ *
+ * A sensor of this type returns the pose of the device.
+ * Pose of the device is defined as the orientation of the device from a
+ * Earth Centered Earth Fixed frame and the translation from an arbitrary
+ * point at subscription.
+ *
+ * This sensor can be high power. It can use any and all of the following
+ * . Accelerometer
+ * . Gyroscope
+ * . Camera
+ * . Depth Camera
+ *
+ */
+ POSE_6DOF = 28,
+
+ /**
+ * STATIONARY_DETECT
+ * trigger mode: one shot
+ *
+ * A sensor of this type returns an event if the device is still/stationary
+ * for a while. The period of time to monitor for stationarity must be
+ * greater than 5 seconds. The latency must be less than 10 seconds.
+ *
+ * Stationarity here refers to absolute stationarity. eg: device on desk.
+ *
+ * The only allowed value to return is 1.0.
+ */
+ STATIONARY_DETECT = 29,
+
+ /**
+ * MOTION_DETECT
+ * trigger mode: one shot
+ *
+ * A sensor of this type returns an event if the device is not still for
+ * for a while. The period of time to monitor for stationarity must be
+ * greater than 5 seconds. The latency must be less than 10 seconds.
+ *
+ * Motion here refers to any mechanism in which the device is causes to be
+ * moved in its inertial frame. eg: Pickin up the device and walking with it
+ * to a nearby room may trigger motion wherewas keeping the device on a
+ * table on a smooth train moving at constant velocity may not trigger
+ * motion.
+ *
+ * The only allowed value to return is 1.0.
+ */
+ MOTION_DETECT = 30,
+
+ /**
+ * HEART_BEAT
+ * trigger mode: continuous
+ *
+ * A sensor of this type returns an event everytime a hear beat peak is
+ * detected.
+ *
+ * Peak here ideally corresponds to the positive peak in the QRS complex of
+ * and ECG signal.
+ *
+ * The sensor is not expected to be optimized for latency. As a guide, a
+ * latency of up to 10 seconds is acceptable. However, the timestamp attached
+ * to the event must be accuratly correspond to the time the peak occurred.
+ *
+ * The sensor event contains a parameter for the confidence in the detection
+ * of the peak where 0.0 represent no information at all, and 1.0 represents
+ * certainty.
+ */
+ HEART_BEAT = 31,
+
+ /**
+ * DYNAMIC_SENSOR_META
+ * trigger-mode: special
+ * wake-up sensor: yes
+ *
+ * A sensor event of this type is received when a dynamic sensor is added to
+ * or removed from the system. At most one sensor of this type can be
+ * present in one sensor HAL implementation and presence of a sensor of this
+ * type in sensor HAL implementation indicates that this sensor HAL supports
+ * dynamic sensor feature. Operations, such as batch, activate and setDelay,
+ * to this special purpose sensor must be treated as no-op and return
+ * successful; flush() also has to generate flush complete event as if this
+ * is a sensor that does not support batching.
+ *
+ * A dynamic sensor connection indicates connection of a physical device or
+ * instantiation of a virtual sensor backed by algorithm; and a dynamic
+ * sensor disconnection indicates the opposite. A sensor event of
+ * DYNAMIC_SENSOR_META type should be delivered regardless of
+ * the activation status of the sensor in the event of dynamic sensor
+ * connection and disconnection. In the sensor event, besides the common
+ * data entries, "dynamic_sensor_meta", which includes fields for connection
+ * status, handle of the sensor involved, pointer to sensor_t structure and
+ * a uuid field, must be populated.
+ *
+ * At a dynamic sensor connection event, fields of sensor_t structure
+ * referenced by a pointer in dynamic_sensor_meta must be filled as if it
+ * was regular sensors. Sensor HAL is responsible for recovery of memory if
+ * the corresponding data is dynamicially allocated. However, the
+ * pointer must be valid until the first activate call to the sensor
+ * reported in this connection event. At a dynamic sensor disconnection,
+ * the sensor_t pointer must be NULL.
+ *
+ * The sensor handle assigned to dynamic sensors must never be the same as
+ * that of any regular static sensors, and must be unique until next boot.
+ * In another word, if a handle h is used for a dynamic sensor A, that same
+ * number cannot be used for the same dynamic sensor A or another dynamic
+ * sensor B even after disconnection of A until reboot.
+ *
+ * The UUID field will be used for identifying the sensor in addition to
+ * name, vendor and version and type. For physical sensors of the same
+ * model, all sensors will have the same values in sensor_t, but the UUID
+ * must be unique and persistent for each individual unit. An all zero
+ * UUID indicates it is not possible to differentiate individual sensor
+ * unit.
+ *
+ */
+ DYNAMIC_SENSOR_META = 32,
+
+ /**
+ * ADDITIONAL_INFO
+ * reporting-mode: N/A
+ *
+ * This sensor type is for delivering additional sensor information aside
+ * from sensor event data.
+ * Additional information may include sensor front-end group delay, internal
+ * calibration parameters, noise level metrics, device internal temperature,
+ * etc.
+ *
+ * This type will never bind to a sensor. In other words, no sensor in the
+ * sensor list can have the type SENSOR_TYPE_ADDITIONAL_INFO. If a
+ * sensor HAL supports sensor additional information feature, it reports
+ * sensor_event_t with "sensor" field set to handle of the reporting sensor
+ * and "type" field set to ADDITIONAL_INFO. Delivery of
+ * additional information events is triggered under two conditions: an
+ * enable activate() call or a flush() call to the corresponding sensor.
+ * Besides, time varying parameters can update infrequently without being
+ * triggered. Device is responsible to control update rate. The recommend
+ * update rate is less than 1/1000 of sensor event rate or less than once
+ * per minute in average.
+ *
+ * A single additional information report consists of multiple frames.
+ * Sequences of these frames are ordered using timestamps, which means the
+ * timestamps of sequential frames have to be at least 1 nanosecond apart
+ * from each other. Each frame is a sensor_event_t delivered through the HAL
+ * interface, with related data stored in the "additional_info" field, which
+ * is of type additional_info_event_t.
+ * The "type" field of additional_info_event_t denotes the nature of the
+ * payload data (see additional_info_type_t).
+ * The "serial" field is used to keep the sequence of payload data that
+ * spans multiple frames. The first frame of the entire report is always of
+ * type AINFO_BEGIN, and the last frame is always AINFO_END.
+ *
+ * If flush() was triggering the report, all additional information frames
+ * must be delivered after flush complete event.
+ */
+ ADDITIONAL_INFO = 33,
+
+ /**
+ * LOW_LATENCY_OFFBODY_DETECT
+ * trigger-mode: on-change
+ * wake-up sensor: yes
+ *
+ * A sensor of this type is defined for devices that are supposed to be worn
+ * by the user in the normal use case (such as a watch, wristband, etc) and
+ * is not yet defined for other device.
+ *
+ * A sensor of this type triggers an event each time the wearable device
+ * is removed from the body and each time it's put back onto the body.
+ * It must be low-latency and be able to detect the on-body to off-body
+ * transition within one second (event delivery time included),
+ * and 3-second latency to determine the off-body to on-body transition
+ * (event delivery time included).
+ *
+ * There are only two valid event values for the sensor to return :
+ * 0.0 for off-body
+ * 1.0 for on-body
+ *
+ */
+ LOW_LATENCY_OFFBODY_DETECT = 34,
+
+ /**
+ * ACCELEROMETER_UNCALIBRATED
+ * reporting-mode: continuous
+ *
+ * All values are in SI units (m/s^2) and measure the acceleration of the
+ * device minus the acceleration due to gravity.
+ *
+ * Implement the non-wake-up version of this sensor and implement the
+ * wake-up version if the system possesses a wake up fifo.
+ */
+ ACCELEROMETER_UNCALIBRATED = 35,
+
+ /**
+ * HINGE_ANGLE
+ * reporting-mode: on-change
+ * wake-up sensor: yes
+ *
+ * A sensor of this type measures the angle, in degrees, between two
+ * integral parts of the device. Movement of a hinge measured by this sensor
+ * type is expected to alter the ways in which the user may interact with
+ * the device, for example by unfolding or revealing a display.
+ *
+ * Sensor data is output using EventPayload.scalar.
+ *
+ * Implement wake-up proximity sensor before implementing a non wake-up
+ * proximity sensor.
+ */
+ HINGE_ANGLE = 36,
+
+ /**
+ * Base for device manufacturers private sensor types.
+ * These sensor types can't be exposed in the SDK.
+ */
+ DEVICE_PRIVATE_BASE = 0x10000,
+}
diff --git a/sensors/aidl/default/Android.bp b/sensors/aidl/default/Android.bp
new file mode 100644
index 0000000..49841a4
--- /dev/null
+++ b/sensors/aidl/default/Android.bp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_library_static {
+ name: "libsensorsexampleimpl",
+ vendor: true,
+ shared_libs: [
+ "libbase",
+ "libfmq",
+ "libpower",
+ "libbinder_ndk",
+ "android.hardware.sensors-V1-ndk",
+ ],
+ export_include_dirs: ["include"],
+ srcs: [
+ "Sensors.cpp",
+ "Sensor.cpp",
+ ],
+ visibility: [
+ ":__subpackages__",
+ "//hardware/interfaces/tests/extension/sensors:__subpackages__",
+ ],
+}
+
+cc_binary {
+ name: "android.hardware.sensors-service.example",
+ relative_install_path: "hw",
+ init_rc: ["sensors-default.rc"],
+ vintf_fragments: ["sensors-default.xml"],
+ vendor: true,
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "libfmq",
+ "libpower",
+ "libcutils",
+ "liblog",
+ "libutils",
+ "android.hardware.sensors-V1-ndk",
+ ],
+ static_libs: [
+ "libsensorsexampleimpl",
+ ],
+ srcs: ["main.cpp"],
+}
diff --git a/sensors/aidl/default/Sensor.cpp b/sensors/aidl/default/Sensor.cpp
new file mode 100644
index 0000000..50d8841
--- /dev/null
+++ b/sensors/aidl/default/Sensor.cpp
@@ -0,0 +1,434 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "sensors-impl/Sensor.h"
+
+#include "utils/SystemClock.h"
+
+#include <cmath>
+
+using ::ndk::ScopedAStatus;
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace sensors {
+
+static constexpr int32_t kDefaultMaxDelayUs = 10 * 1000 * 1000;
+
+Sensor::Sensor(ISensorsEventCallback* callback)
+ : mIsEnabled(false),
+ mSamplingPeriodNs(0),
+ mLastSampleTimeNs(0),
+ mCallback(callback),
+ mMode(OperationMode::NORMAL) {
+ mRunThread = std::thread(startThread, this);
+}
+
+Sensor::~Sensor() {
+ std::unique_lock<std::mutex> lock(mRunMutex);
+ mStopThread = true;
+ mIsEnabled = false;
+ mWaitCV.notify_all();
+ lock.release();
+ mRunThread.join();
+}
+
+const SensorInfo& Sensor::getSensorInfo() const {
+ return mSensorInfo;
+}
+
+void Sensor::batch(int64_t samplingPeriodNs) {
+ if (samplingPeriodNs < mSensorInfo.minDelayUs * 1000ll) {
+ samplingPeriodNs = mSensorInfo.minDelayUs * 1000ll;
+ } else if (samplingPeriodNs > mSensorInfo.maxDelayUs * 1000ll) {
+ samplingPeriodNs = mSensorInfo.maxDelayUs * 1000ll;
+ }
+
+ 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) {
+ std::unique_lock<std::mutex> lock(mRunMutex);
+ mIsEnabled = enable;
+ mWaitCV.notify_all();
+ }
+}
+
+ScopedAStatus Sensor::flush() {
+ // Only generate a flush complete event if the sensor is enabled and if the sensor is not a
+ // one-shot sensor.
+ if (!mIsEnabled ||
+ (mSensorInfo.flags & static_cast<uint32_t>(SensorInfo::SENSOR_FLAG_BITS_ONE_SHOT_MODE))) {
+ return ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(BnSensors::ERROR_BAD_VALUE));
+ }
+
+ // Note: If a sensor supports batching, write all of the currently batched events for the sensor
+ // to the Event FMQ prior to writing the flush complete event.
+ Event ev;
+ ev.sensorHandle = mSensorInfo.sensorHandle;
+ ev.sensorType = SensorType::META_DATA;
+ EventPayload::MetaData meta = {
+ .what = MetaDataEventType::META_DATA_FLUSH_COMPLETE,
+ };
+ ev.payload.set<EventPayload::Tag::meta>(meta);
+ std::vector<Event> evs{ev};
+ mCallback->postEvents(evs, isWakeUpSensor());
+
+ return ScopedAStatus::ok();
+}
+
+void Sensor::startThread(Sensor* sensor) {
+ sensor->run();
+}
+
+void Sensor::run() {
+ std::unique_lock<std::mutex> runLock(mRunMutex);
+ constexpr int64_t kNanosecondsInSeconds = 1000 * 1000 * 1000;
+
+ while (!mStopThread) {
+ if (!mIsEnabled || mMode == OperationMode::DATA_INJECTION) {
+ mWaitCV.wait(runLock, [&] {
+ return ((mIsEnabled && mMode == OperationMode::NORMAL) || mStopThread);
+ });
+ } else {
+ timespec curTime;
+ clock_gettime(CLOCK_BOOTTIME, &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(), isWakeUpSensor());
+ }
+
+ mWaitCV.wait_for(runLock, std::chrono::nanoseconds(nextSampleTime - now));
+ }
+ }
+}
+
+bool Sensor::isWakeUpSensor() {
+ return mSensorInfo.flags & static_cast<uint32_t>(SensorInfo::SENSOR_FLAG_BITS_WAKE_UP);
+}
+
+std::vector<Event> Sensor::readEvents() {
+ std::vector<Event> events;
+ Event event;
+ event.sensorHandle = mSensorInfo.sensorHandle;
+ event.sensorType = mSensorInfo.type;
+ event.timestamp = ::android::elapsedRealtimeNano();
+ memset(&event.payload, 0, sizeof(event.payload));
+ readEventPayload(event.payload);
+ events.push_back(event);
+ return events;
+}
+
+void Sensor::setOperationMode(OperationMode mode) {
+ if (mMode != mode) {
+ std::unique_lock<std::mutex> lock(mRunMutex);
+ mMode = mode;
+ mWaitCV.notify_all();
+ }
+}
+
+bool Sensor::supportsDataInjection() const {
+ return mSensorInfo.flags & static_cast<uint32_t>(SensorInfo::SENSOR_FLAG_BITS_DATA_INJECTION);
+}
+
+ScopedAStatus Sensor::injectEvent(const Event& event) {
+ if (event.sensorType == SensorType::ADDITIONAL_INFO) {
+ return ScopedAStatus::ok();
+ // When in OperationMode::NORMAL, SensorType::ADDITIONAL_INFO is used to push operation
+ // environment data into the device.
+ }
+
+ if (!supportsDataInjection()) {
+ return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ }
+
+ if (mMode == OperationMode::DATA_INJECTION) {
+ mCallback->postEvents(std::vector<Event>{event}, isWakeUpSensor());
+ return ScopedAStatus::ok();
+ }
+
+ return ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(BnSensors::ERROR_BAD_VALUE));
+}
+
+OnChangeSensor::OnChangeSensor(ISensorsEventCallback* callback)
+ : Sensor(callback), mPreviousEventSet(false) {}
+
+void OnChangeSensor::activate(bool enable) {
+ Sensor::activate(enable);
+ if (!enable) {
+ mPreviousEventSet = false;
+ }
+}
+
+std::vector<Event> OnChangeSensor::readEvents() {
+ std::vector<Event> events = Sensor::readEvents();
+ std::vector<Event> outputEvents;
+
+ for (auto iter = events.begin(); iter != events.end(); ++iter) {
+ Event ev = *iter;
+ if (!mPreviousEventSet ||
+ memcmp(&mPreviousEvent.payload, &ev.payload, sizeof(ev.payload)) != 0) {
+ outputEvents.push_back(ev);
+ mPreviousEvent = ev;
+ mPreviousEventSet = true;
+ }
+ }
+ return outputEvents;
+}
+
+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.minDelayUs = 10 * 1000; // microseconds
+ mSensorInfo.maxDelayUs = kDefaultMaxDelayUs;
+ mSensorInfo.fifoReservedEventCount = 0;
+ mSensorInfo.fifoMaxEventCount = 0;
+ mSensorInfo.requiredPermission = "";
+ mSensorInfo.flags = static_cast<uint32_t>(SensorInfo::SENSOR_FLAG_BITS_DATA_INJECTION);
+};
+
+void AccelSensor::readEventPayload(EventPayload& payload) {
+ EventPayload::Vec3 vec3 = {
+ .x = 0,
+ .y = 0,
+ .z = -9.8,
+ .status = SensorStatus::ACCURACY_HIGH,
+ };
+ payload.set<EventPayload::Tag::vec3>(vec3);
+}
+
+PressureSensor::PressureSensor(int32_t sensorHandle, ISensorsEventCallback* callback)
+ : Sensor(callback) {
+ mSensorInfo.sensorHandle = sensorHandle;
+ mSensorInfo.name = "Pressure Sensor";
+ mSensorInfo.vendor = "Vendor String";
+ mSensorInfo.version = 1;
+ mSensorInfo.type = SensorType::PRESSURE;
+ mSensorInfo.typeAsString = "";
+ mSensorInfo.maxRange = 1100.0f; // hPa
+ mSensorInfo.resolution = 0.005f; // hPa
+ mSensorInfo.power = 0.001f; // mA
+ mSensorInfo.minDelayUs = 100 * 1000; // microseconds
+ mSensorInfo.maxDelayUs = kDefaultMaxDelayUs;
+ mSensorInfo.fifoReservedEventCount = 0;
+ mSensorInfo.fifoMaxEventCount = 0;
+ mSensorInfo.requiredPermission = "";
+ mSensorInfo.flags = 0;
+};
+
+void PressureSensor::readEventPayload(EventPayload& payload) {
+ payload.set<EventPayload::Tag::scalar>(1013.25f);
+}
+
+MagnetometerSensor::MagnetometerSensor(int32_t sensorHandle, ISensorsEventCallback* callback)
+ : Sensor(callback) {
+ mSensorInfo.sensorHandle = sensorHandle;
+ mSensorInfo.name = "Magnetic Field Sensor";
+ mSensorInfo.vendor = "Vendor String";
+ mSensorInfo.version = 1;
+ mSensorInfo.type = SensorType::MAGNETIC_FIELD;
+ mSensorInfo.typeAsString = "";
+ mSensorInfo.maxRange = 1300.0f;
+ mSensorInfo.resolution = 0.01f;
+ mSensorInfo.power = 0.001f; // mA
+ mSensorInfo.minDelayUs = 20 * 1000; // microseconds
+ mSensorInfo.maxDelayUs = kDefaultMaxDelayUs;
+ mSensorInfo.fifoReservedEventCount = 0;
+ mSensorInfo.fifoMaxEventCount = 0;
+ mSensorInfo.requiredPermission = "";
+ mSensorInfo.flags = 0;
+};
+
+void MagnetometerSensor::readEventPayload(EventPayload& payload) {
+ EventPayload::Vec3 vec3 = {
+ .x = 100.0,
+ .y = 0,
+ .z = 50.0,
+ .status = SensorStatus::ACCURACY_HIGH,
+ };
+ payload.set<EventPayload::Tag::vec3>(vec3);
+}
+
+LightSensor::LightSensor(int32_t sensorHandle, ISensorsEventCallback* callback)
+ : OnChangeSensor(callback) {
+ mSensorInfo.sensorHandle = sensorHandle;
+ mSensorInfo.name = "Light Sensor";
+ mSensorInfo.vendor = "Vendor String";
+ mSensorInfo.version = 1;
+ mSensorInfo.type = SensorType::LIGHT;
+ mSensorInfo.typeAsString = "";
+ mSensorInfo.maxRange = 43000.0f;
+ mSensorInfo.resolution = 10.0f;
+ mSensorInfo.power = 0.001f; // mA
+ mSensorInfo.minDelayUs = 200 * 1000; // microseconds
+ mSensorInfo.maxDelayUs = kDefaultMaxDelayUs;
+ mSensorInfo.fifoReservedEventCount = 0;
+ mSensorInfo.fifoMaxEventCount = 0;
+ mSensorInfo.requiredPermission = "";
+ mSensorInfo.flags = static_cast<uint32_t>(SensorInfo::SENSOR_FLAG_BITS_ON_CHANGE_MODE);
+};
+
+void LightSensor::readEventPayload(EventPayload& payload) {
+ payload.set<EventPayload::Tag::scalar>(80.0f);
+}
+
+ProximitySensor::ProximitySensor(int32_t sensorHandle, ISensorsEventCallback* callback)
+ : OnChangeSensor(callback) {
+ mSensorInfo.sensorHandle = sensorHandle;
+ mSensorInfo.name = "Proximity Sensor";
+ mSensorInfo.vendor = "Vendor String";
+ mSensorInfo.version = 1;
+ mSensorInfo.type = SensorType::PROXIMITY;
+ mSensorInfo.typeAsString = "";
+ mSensorInfo.maxRange = 5.0f;
+ mSensorInfo.resolution = 1.0f;
+ mSensorInfo.power = 0.012f; // mA
+ mSensorInfo.minDelayUs = 200 * 1000; // microseconds
+ mSensorInfo.maxDelayUs = kDefaultMaxDelayUs;
+ mSensorInfo.fifoReservedEventCount = 0;
+ mSensorInfo.fifoMaxEventCount = 0;
+ mSensorInfo.requiredPermission = "";
+ mSensorInfo.flags = static_cast<uint32_t>(SensorInfo::SENSOR_FLAG_BITS_ON_CHANGE_MODE |
+ SensorInfo::SENSOR_FLAG_BITS_WAKE_UP);
+};
+
+void ProximitySensor::readEventPayload(EventPayload& payload) {
+ payload.set<EventPayload::Tag::scalar>(2.5f);
+}
+
+GyroSensor::GyroSensor(int32_t sensorHandle, ISensorsEventCallback* callback) : Sensor(callback) {
+ mSensorInfo.sensorHandle = sensorHandle;
+ mSensorInfo.name = "Gyro Sensor";
+ mSensorInfo.vendor = "Vendor String";
+ mSensorInfo.version = 1;
+ mSensorInfo.type = SensorType::GYROSCOPE;
+ mSensorInfo.typeAsString = "";
+ mSensorInfo.maxRange = 1000.0f * M_PI / 180.0f;
+ mSensorInfo.resolution = 1000.0f * M_PI / (180.0f * 32768.0f);
+ mSensorInfo.power = 0.001f;
+ mSensorInfo.minDelayUs = 10 * 1000; // microseconds
+ mSensorInfo.maxDelayUs = kDefaultMaxDelayUs;
+ mSensorInfo.fifoReservedEventCount = 0;
+ mSensorInfo.fifoMaxEventCount = 0;
+ mSensorInfo.requiredPermission = "";
+ mSensorInfo.flags = 0;
+};
+
+void GyroSensor::readEventPayload(EventPayload& payload) {
+ EventPayload::Vec3 vec3 = {
+ .x = 0,
+ .y = 0,
+ .z = 0,
+ .status = SensorStatus::ACCURACY_HIGH,
+ };
+ payload.set<EventPayload::Tag::vec3>(vec3);
+}
+
+AmbientTempSensor::AmbientTempSensor(int32_t sensorHandle, ISensorsEventCallback* callback)
+ : OnChangeSensor(callback) {
+ mSensorInfo.sensorHandle = sensorHandle;
+ mSensorInfo.name = "Ambient Temp Sensor";
+ mSensorInfo.vendor = "Vendor String";
+ mSensorInfo.version = 1;
+ mSensorInfo.type = SensorType::AMBIENT_TEMPERATURE;
+ mSensorInfo.typeAsString = "";
+ mSensorInfo.maxRange = 80.0f;
+ mSensorInfo.resolution = 0.01f;
+ mSensorInfo.power = 0.001f;
+ mSensorInfo.minDelayUs = 40 * 1000; // microseconds
+ mSensorInfo.maxDelayUs = kDefaultMaxDelayUs;
+ mSensorInfo.fifoReservedEventCount = 0;
+ mSensorInfo.fifoMaxEventCount = 0;
+ mSensorInfo.requiredPermission = "";
+ mSensorInfo.flags = static_cast<uint32_t>(SensorInfo::SENSOR_FLAG_BITS_ON_CHANGE_MODE);
+};
+
+void AmbientTempSensor::readEventPayload(EventPayload& payload) {
+ payload.set<EventPayload::Tag::scalar>(40.0f);
+}
+
+RelativeHumiditySensor::RelativeHumiditySensor(int32_t sensorHandle,
+ ISensorsEventCallback* callback)
+ : OnChangeSensor(callback) {
+ mSensorInfo.sensorHandle = sensorHandle;
+ mSensorInfo.name = "Relative Humidity Sensor";
+ mSensorInfo.vendor = "Vendor String";
+ mSensorInfo.version = 1;
+ mSensorInfo.type = SensorType::RELATIVE_HUMIDITY;
+ mSensorInfo.typeAsString = "";
+ mSensorInfo.maxRange = 100.0f;
+ mSensorInfo.resolution = 0.1f;
+ mSensorInfo.power = 0.001f;
+ mSensorInfo.minDelayUs = 40 * 1000; // microseconds
+ mSensorInfo.maxDelayUs = kDefaultMaxDelayUs;
+ mSensorInfo.fifoReservedEventCount = 0;
+ mSensorInfo.fifoMaxEventCount = 0;
+ mSensorInfo.requiredPermission = "";
+ mSensorInfo.flags = static_cast<uint32_t>(SensorInfo::SENSOR_FLAG_BITS_ON_CHANGE_MODE);
+}
+
+void RelativeHumiditySensor::readEventPayload(EventPayload& payload) {
+ payload.set<EventPayload::Tag::scalar>(50.0f);
+}
+
+HingeAngleSensor::HingeAngleSensor(int32_t sensorHandle, ISensorsEventCallback* callback)
+ : OnChangeSensor(callback) {
+ mSensorInfo.sensorHandle = sensorHandle;
+ mSensorInfo.name = "Hinge Angle Sensor";
+ mSensorInfo.vendor = "Vendor String";
+ mSensorInfo.version = 1;
+ mSensorInfo.type = SensorType::HINGE_ANGLE;
+ mSensorInfo.typeAsString = "";
+ mSensorInfo.maxRange = 360.0f;
+ mSensorInfo.resolution = 1.0f;
+ mSensorInfo.power = 0.001f;
+ mSensorInfo.minDelayUs = 40 * 1000; // microseconds
+ mSensorInfo.maxDelayUs = kDefaultMaxDelayUs;
+ mSensorInfo.fifoReservedEventCount = 0;
+ mSensorInfo.fifoMaxEventCount = 0;
+ mSensorInfo.requiredPermission = "";
+ mSensorInfo.flags = static_cast<uint32_t>(SensorInfo::SENSOR_FLAG_BITS_ON_CHANGE_MODE |
+ SensorInfo::SENSOR_FLAG_BITS_WAKE_UP |
+ SensorInfo::SENSOR_FLAG_BITS_DATA_INJECTION);
+}
+
+void HingeAngleSensor::readEventPayload(EventPayload& payload) {
+ payload.set<EventPayload::Tag::scalar>(180.0f);
+}
+
+} // namespace sensors
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/sensors/aidl/default/Sensors.cpp b/sensors/aidl/default/Sensors.cpp
new file mode 100644
index 0000000..65dd304
--- /dev/null
+++ b/sensors/aidl/default/Sensors.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "sensors-impl/Sensors.h"
+
+#include <aidl/android/hardware/common/fmq/SynchronizedReadWrite.h>
+
+using ::aidl::android::hardware::common::fmq::MQDescriptor;
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::aidl::android::hardware::sensors::Event;
+using ::aidl::android::hardware::sensors::ISensors;
+using ::aidl::android::hardware::sensors::ISensorsCallback;
+using ::aidl::android::hardware::sensors::SensorInfo;
+using ::ndk::ScopedAStatus;
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace sensors {
+
+ScopedAStatus Sensors::activate(int32_t in_sensorHandle, bool in_enabled) {
+ auto sensor = mSensors.find(in_sensorHandle);
+ if (sensor != mSensors.end()) {
+ sensor->second->activate(in_enabled);
+ return ScopedAStatus::ok();
+ }
+
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+}
+
+ScopedAStatus Sensors::batch(int32_t in_sensorHandle, int64_t in_samplingPeriodNs,
+ int64_t /* in_maxReportLatencyNs */) {
+ auto sensor = mSensors.find(in_sensorHandle);
+ if (sensor != mSensors.end()) {
+ sensor->second->batch(in_samplingPeriodNs);
+ return ScopedAStatus::ok();
+ }
+
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+}
+
+ScopedAStatus Sensors::configDirectReport(int32_t /* in_sensorHandle */,
+ int32_t /* in_channelHandle */,
+ ISensors::RateLevel /* in_rate */,
+ int32_t* _aidl_return) {
+ *_aidl_return = EX_UNSUPPORTED_OPERATION;
+
+ return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ScopedAStatus Sensors::flush(int32_t in_sensorHandle) {
+ auto sensor = mSensors.find(in_sensorHandle);
+ if (sensor != mSensors.end()) {
+ return sensor->second->flush();
+ }
+
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+}
+
+ScopedAStatus Sensors::getSensorsList(std::vector<SensorInfo>* _aidl_return) {
+ for (const auto& sensor : mSensors) {
+ _aidl_return->push_back(sensor.second->getSensorInfo());
+ }
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Sensors::initialize(
+ const MQDescriptor<Event, SynchronizedReadWrite>& in_eventQueueDescriptor,
+ const MQDescriptor<int32_t, SynchronizedReadWrite>& in_wakeLockDescriptor,
+ const std::shared_ptr<::aidl::android::hardware::sensors::ISensorsCallback>&
+ in_sensorsCallback) {
+ ScopedAStatus result = ScopedAStatus::ok();
+
+ mEventQueue = std::make_unique<AidlMessageQueue<Event, SynchronizedReadWrite>>(
+ in_eventQueueDescriptor, true /* resetPointers */);
+
+ // Ensure that all sensors are disabled.
+ for (auto sensor : mSensors) {
+ sensor.second->activate(false);
+ }
+
+ // Stop the Wake Lock thread if it is currently running
+ if (mReadWakeLockQueueRun.load()) {
+ mReadWakeLockQueueRun = false;
+ mWakeLockThread.join();
+ }
+
+ // Save a reference to the callback
+ mCallback = in_sensorsCallback;
+
+ // 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 = ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+
+ // 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<AidlMessageQueue<int32_t, SynchronizedReadWrite>>(
+ in_wakeLockDescriptor, true /* resetPointers */);
+
+ if (!mCallback || !mEventQueue || !mWakeLockQueue || mEventQueueFlag == nullptr) {
+ result = ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+
+ // Start the thread to read events from the Wake Lock FMQ
+ mReadWakeLockQueueRun = true;
+ mWakeLockThread = std::thread(startReadWakeLockThread, this);
+ return result;
+}
+
+ScopedAStatus Sensors::injectSensorData(const Event& in_event) {
+ auto sensor = mSensors.find(in_event.sensorHandle);
+ if (sensor != mSensors.end()) {
+ return sensor->second->injectEvent(in_event);
+ }
+ return ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(ERROR_BAD_VALUE));
+}
+
+ScopedAStatus Sensors::registerDirectChannel(const ISensors::SharedMemInfo& /* in_mem */,
+ int32_t* _aidl_return) {
+ *_aidl_return = EX_UNSUPPORTED_OPERATION;
+
+ return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ScopedAStatus Sensors::setOperationMode(OperationMode in_mode) {
+ for (auto sensor : mSensors) {
+ sensor.second->setOperationMode(in_mode);
+ }
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Sensors::unregisterDirectChannel(int32_t /* in_channelHandle */) {
+ return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+} // namespace sensors
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/sensors/aidl/default/include/sensors-impl/Sensor.h b/sensors/aidl/default/include/sensors-impl/Sensor.h
new file mode 100644
index 0000000..e6cd3e6
--- /dev/null
+++ b/sensors/aidl/default/include/sensors-impl/Sensor.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <thread>
+
+#include <aidl/android/hardware/sensors/BnSensors.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace sensors {
+
+class ISensorsEventCallback {
+ public:
+ using Event = ::aidl::android::hardware::sensors::Event;
+
+ virtual ~ISensorsEventCallback(){};
+ virtual void postEvents(const std::vector<Event>& events, bool wakeup) = 0;
+};
+
+class Sensor {
+ public:
+ using OperationMode = ::aidl::android::hardware::sensors::ISensors::OperationMode;
+ using Event = ::aidl::android::hardware::sensors::Event;
+ using EventPayload = ::aidl::android::hardware::sensors::Event::EventPayload;
+ using SensorInfo = ::aidl::android::hardware::sensors::SensorInfo;
+ using SensorType = ::aidl::android::hardware::sensors::SensorType;
+ using MetaDataEventType =
+ ::aidl::android::hardware::sensors::Event::EventPayload::MetaData::MetaDataEventType;
+
+ Sensor(ISensorsEventCallback* callback);
+ virtual ~Sensor();
+
+ const SensorInfo& getSensorInfo() const;
+ void batch(int64_t samplingPeriodNs);
+ virtual void activate(bool enable);
+ ndk::ScopedAStatus flush();
+
+ void setOperationMode(OperationMode mode);
+ bool supportsDataInjection() const;
+ ndk::ScopedAStatus injectEvent(const Event& event);
+
+ protected:
+ void run();
+ virtual std::vector<Event> readEvents();
+ virtual void readEventPayload(EventPayload&) = 0;
+ static void startThread(Sensor* sensor);
+
+ bool isWakeUpSensor();
+
+ bool mIsEnabled;
+ int64_t mSamplingPeriodNs;
+ int64_t mLastSampleTimeNs;
+ SensorInfo mSensorInfo;
+
+ std::atomic_bool mStopThread;
+ std::condition_variable mWaitCV;
+ std::mutex mRunMutex;
+ std::thread mRunThread;
+
+ ISensorsEventCallback* mCallback;
+
+ OperationMode mMode;
+};
+
+class OnChangeSensor : public Sensor {
+ public:
+ OnChangeSensor(ISensorsEventCallback* callback);
+
+ virtual void activate(bool enable) override;
+
+ protected:
+ virtual std::vector<Event> readEvents() override;
+
+ protected:
+ Event mPreviousEvent;
+ bool mPreviousEventSet;
+};
+
+class AccelSensor : public Sensor {
+ public:
+ AccelSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
+
+ protected:
+ virtual void readEventPayload(EventPayload& payload) override;
+};
+
+class GyroSensor : public Sensor {
+ public:
+ GyroSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
+
+ protected:
+ virtual void readEventPayload(EventPayload& payload) override;
+};
+
+class AmbientTempSensor : public OnChangeSensor {
+ public:
+ AmbientTempSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
+
+ protected:
+ virtual void readEventPayload(EventPayload& payload) override;
+};
+
+class PressureSensor : public Sensor {
+ public:
+ PressureSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
+
+ protected:
+ virtual void readEventPayload(EventPayload& payload) override;
+};
+
+class MagnetometerSensor : public Sensor {
+ public:
+ MagnetometerSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
+
+ protected:
+ virtual void readEventPayload(EventPayload& payload) override;
+};
+
+class LightSensor : public OnChangeSensor {
+ public:
+ LightSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
+
+ protected:
+ virtual void readEventPayload(EventPayload& payload) override;
+};
+
+class ProximitySensor : public OnChangeSensor {
+ public:
+ ProximitySensor(int32_t sensorHandle, ISensorsEventCallback* callback);
+
+ protected:
+ virtual void readEventPayload(EventPayload& payload) override;
+};
+
+class RelativeHumiditySensor : public OnChangeSensor {
+ public:
+ RelativeHumiditySensor(int32_t sensorHandle, ISensorsEventCallback* callback);
+
+ protected:
+ virtual void readEventPayload(EventPayload& payload) override;
+};
+
+class HingeAngleSensor : public OnChangeSensor {
+ public:
+ HingeAngleSensor(int32_t sensorHandle, ISensorsEventCallback* callback);
+
+ protected:
+ virtual void readEventPayload(EventPayload& payload) override;
+};
+
+} // namespace sensors
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/sensors/aidl/default/include/sensors-impl/Sensors.h b/sensors/aidl/default/include/sensors-impl/Sensors.h
new file mode 100644
index 0000000..e270d96
--- /dev/null
+++ b/sensors/aidl/default/include/sensors-impl/Sensors.h
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/common/fmq/SynchronizedReadWrite.h>
+#include <aidl/android/hardware/sensors/BnSensors.h>
+#include <fmq/AidlMessageQueue.h>
+#include <hardware_legacy/power.h>
+#include <map>
+#include "Sensor.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace sensors {
+
+using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::android::AidlMessageQueue;
+using ::android::OK;
+using ::android::status_t;
+using ::android::hardware::EventFlag;
+
+class Sensors : public BnSensors, public ISensorsEventCallback {
+ static constexpr const char* kWakeLockName = "SensorsHAL_WAKEUP";
+
+ public:
+ Sensors()
+ : mEventQueueFlag(nullptr),
+ mNextHandle(1),
+ mOutstandingWakeUpEvents(0),
+ mReadWakeLockQueueRun(false),
+ mAutoReleaseWakeLockTime(0),
+ mHasWakeLock(false) {
+ AddSensor<AccelSensor>();
+ AddSensor<GyroSensor>();
+ AddSensor<AmbientTempSensor>();
+ AddSensor<PressureSensor>();
+ AddSensor<MagnetometerSensor>();
+ AddSensor<LightSensor>();
+ AddSensor<ProximitySensor>();
+ AddSensor<RelativeHumiditySensor>();
+ AddSensor<HingeAngleSensor>();
+ }
+
+ virtual ~Sensors() {
+ deleteEventFlag();
+ mReadWakeLockQueueRun = false;
+ mWakeLockThread.join();
+ }
+
+ ::ndk::ScopedAStatus activate(int32_t in_sensorHandle, bool in_enabled) override;
+ ::ndk::ScopedAStatus batch(int32_t in_sensorHandle, int64_t in_samplingPeriodNs,
+ int64_t in_maxReportLatencyNs) override;
+ ::ndk::ScopedAStatus configDirectReport(
+ int32_t in_sensorHandle, int32_t in_channelHandle,
+ ::aidl::android::hardware::sensors::ISensors::RateLevel in_rate,
+ int32_t* _aidl_return) override;
+ ::ndk::ScopedAStatus flush(int32_t in_sensorHandle) override;
+ ::ndk::ScopedAStatus getSensorsList(
+ std::vector<::aidl::android::hardware::sensors::SensorInfo>* _aidl_return) override;
+ ::ndk::ScopedAStatus initialize(
+ const ::aidl::android::hardware::common::fmq::MQDescriptor<
+ ::aidl::android::hardware::sensors::Event,
+ ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>&
+ in_eventQueueDescriptor,
+ const ::aidl::android::hardware::common::fmq::MQDescriptor<
+ int32_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>&
+ in_wakeLockDescriptor,
+ const std::shared_ptr<::aidl::android::hardware::sensors::ISensorsCallback>&
+ in_sensorsCallback) override;
+ ::ndk::ScopedAStatus injectSensorData(
+ const ::aidl::android::hardware::sensors::Event& in_event) override;
+ ::ndk::ScopedAStatus registerDirectChannel(
+ const ::aidl::android::hardware::sensors::ISensors::SharedMemInfo& in_mem,
+ int32_t* _aidl_return) override;
+ ::ndk::ScopedAStatus setOperationMode(
+ ::aidl::android::hardware::sensors::ISensors::OperationMode in_mode) override;
+ ::ndk::ScopedAStatus unregisterDirectChannel(int32_t in_channelHandle) override;
+
+ void postEvents(const std::vector<Event>& events, bool wakeup) override {
+ std::lock_guard<std::mutex> lock(mWriteLock);
+ if (mEventQueue == nullptr) {
+ return;
+ }
+ if (mEventQueue->write(&events.front(), events.size())) {
+ mEventQueueFlag->wake(
+ static_cast<uint32_t>(BnSensors::EVENT_QUEUE_FLAG_BITS_READ_AND_PROCESS));
+
+ if (wakeup) {
+ // Keep track of the number of outstanding WAKE_UP events in order to properly hold
+ // a wake lock until the framework has secured a wake lock
+ updateWakeLock(events.size(), 0 /* eventsHandled */);
+ }
+ }
+ }
+
+ protected:
+ // Add a new sensor
+ template <class SensorType>
+ void AddSensor() {
+ std::shared_ptr<SensorType> sensor =
+ std::make_shared<SensorType>(mNextHandle++ /* sensorHandle */, this /* callback */);
+ mSensors[sensor->getSensorInfo().sensorHandle] = sensor;
+ }
+
+ // Utility function to delete the Event Flag
+ void deleteEventFlag() {
+ if (mEventQueueFlag != nullptr) {
+ status_t status = EventFlag::deleteEventFlag(&mEventQueueFlag);
+ if (status != OK) {
+ ALOGI("Failed to delete event flag: %d", status);
+ }
+ }
+ }
+
+ static void startReadWakeLockThread(Sensors* sensors) { sensors->readWakeLockFMQ(); }
+
+ // Function to read the Wake Lock FMQ and release the wake lock when appropriate
+ void readWakeLockFMQ() {
+ while (mReadWakeLockQueueRun.load()) {
+ constexpr int64_t kReadTimeoutNs = 500 * 1000 * 1000; // 500 ms
+ int32_t eventsHandled = 0;
+
+ // Read events from the Wake Lock FMQ. Timeout after a reasonable amount of time to
+ // ensure that any held wake lock is able to be released if it is held for too long.
+ mWakeLockQueue->readBlocking(
+ &eventsHandled, 1 /* count */, 0 /* readNotification */,
+ static_cast<uint32_t>(WAKE_LOCK_QUEUE_FLAG_BITS_DATA_WRITTEN), kReadTimeoutNs);
+ updateWakeLock(0 /* eventsWritten */, eventsHandled);
+ }
+ }
+
+ /**
+ * Responsible for acquiring and releasing a wake lock when there are unhandled WAKE_UP events
+ */
+ void updateWakeLock(int32_t eventsWritten, int32_t eventsHandled) {
+ std::lock_guard<std::mutex> lock(mWakeLockLock);
+ int32_t newVal = mOutstandingWakeUpEvents + eventsWritten - eventsHandled;
+ if (newVal < 0) {
+ mOutstandingWakeUpEvents = 0;
+ } else {
+ mOutstandingWakeUpEvents = newVal;
+ }
+
+ if (eventsWritten > 0) {
+ // Update the time at which the last WAKE_UP event was sent
+ mAutoReleaseWakeLockTime = ::android::uptimeMillis() +
+ static_cast<uint32_t>(WAKE_LOCK_TIMEOUT_SECONDS) * 1000;
+ }
+
+ if (!mHasWakeLock && mOutstandingWakeUpEvents > 0 &&
+ acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLockName) == 0) {
+ mHasWakeLock = true;
+ } else if (mHasWakeLock) {
+ // Check if the wake lock should be released automatically if
+ // SensorTimeout::WAKE_LOCK_SECONDS has elapsed since the last WAKE_UP event was written
+ // to the Wake Lock FMQ.
+ if (::android::uptimeMillis() > mAutoReleaseWakeLockTime) {
+ ALOGD("No events read from wake lock FMQ for %d seconds, auto releasing wake lock",
+ WAKE_LOCK_TIMEOUT_SECONDS);
+ mOutstandingWakeUpEvents = 0;
+ }
+
+ if (mOutstandingWakeUpEvents == 0 && release_wake_lock(kWakeLockName) == 0) {
+ mHasWakeLock = false;
+ }
+ }
+ }
+
+ private:
+ // The Event FMQ where sensor events are written
+ std::unique_ptr<AidlMessageQueue<Event, SynchronizedReadWrite>> mEventQueue;
+ // The Wake Lock FMQ that is read to determine when the framework has handled WAKE_UP events
+ std::unique_ptr<AidlMessageQueue<int32_t, SynchronizedReadWrite>> 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.
+ std::shared_ptr<::aidl::android::hardware::sensors::ISensorsCallback> mCallback;
+ // A map of the available sensors.
+ std::map<int32_t, std::shared_ptr<Sensor>> mSensors;
+ // The next available sensor handle.
+ int32_t mNextHandle;
+ // Lock to protect writes to the FMQs.
+ std::mutex mWriteLock;
+ // Lock to protect acquiring and releasing the wake lock
+ std::mutex mWakeLockLock;
+ // Track the number of WAKE_UP events that have not been handled by the framework
+ uint32_t mOutstandingWakeUpEvents;
+ // A thread to read the Wake Lock FMQ
+ std::thread mWakeLockThread;
+ // Flag to indicate that the Wake Lock Thread should continue to run
+ std::atomic_bool mReadWakeLockQueueRun;
+ // Track the time when the wake lock should automatically be released
+ int64_t mAutoReleaseWakeLockTime;
+ // Flag to indicate if a wake lock has been acquired
+ bool mHasWakeLock;
+};
+
+} // namespace sensors
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/sensors/aidl/default/main.cpp b/sensors/aidl/default/main.cpp
new file mode 100644
index 0000000..8a5a7de
--- /dev/null
+++ b/sensors/aidl/default/main.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "sensors-impl/Sensors.h"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+using aidl::android::hardware::sensors::Sensors;
+
+int main() {
+ ABinderProcess_setThreadPoolMaxThreadCount(0);
+
+ // Make a default sensors service
+ auto sensor = ndk::SharedRefBase::make<Sensors>();
+ const std::string sensorName = std::string() + Sensors::descriptor + "/default";
+ binder_status_t status =
+ AServiceManager_addService(sensor->asBinder().get(), sensorName.c_str());
+ CHECK_EQ(status, STATUS_OK);
+
+ ABinderProcess_joinThreadPool();
+ return EXIT_FAILURE; // should not reach
+}
diff --git a/sensors/aidl/default/sensors-default.rc b/sensors/aidl/default/sensors-default.rc
new file mode 100644
index 0000000..96da85d
--- /dev/null
+++ b/sensors/aidl/default/sensors-default.rc
@@ -0,0 +1,5 @@
+service vendor.sensors-default /vendor/bin/hw/android.hardware.sensors-service.example
+ class hal
+ user system
+ group system
+ rlimit rtprio 10 10
diff --git a/sensors/aidl/default/sensors-default.xml b/sensors/aidl/default/sensors-default.xml
new file mode 100644
index 0000000..7898a6b
--- /dev/null
+++ b/sensors/aidl/default/sensors-default.xml
@@ -0,0 +1,7 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.sensors</name>
+ <version>1</version>
+ <fqname>ISensors/default</fqname>
+ </hal>
+</manifest>
diff --git a/sensors/aidl/vts/Android.bp b/sensors/aidl/vts/Android.bp
new file mode 100644
index 0000000..5a519a5
--- /dev/null
+++ b/sensors/aidl/vts/Android.bp
@@ -0,0 +1,49 @@
+// Copyright 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+ name: "VtsAidlHalSensorsTargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: [
+ "VtsAidlHalSensorsTargetTest.cpp",
+ "SensorsAidlEnvironment.cpp",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libbinder_ndk",
+ "libfmq",
+ "android.hardware.common-V2-ndk",
+ "android.hardware.common.fmq-V1-ndk",
+ ],
+ static_libs: [
+ "android.hardware.sensors-V1-ndk",
+ "VtsHalSensorsTargetTestUtils",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
diff --git a/sensors/aidl/vts/OWNERS b/sensors/aidl/vts/OWNERS
new file mode 100644
index 0000000..90c2330
--- /dev/null
+++ b/sensors/aidl/vts/OWNERS
@@ -0,0 +1,3 @@
+arthuri@google.com
+bduddie@google.com
+stange@google.com
diff --git a/sensors/aidl/vts/SensorsAidlEnvironment.cpp b/sensors/aidl/vts/SensorsAidlEnvironment.cpp
new file mode 100644
index 0000000..e71251f
--- /dev/null
+++ b/sensors/aidl/vts/SensorsAidlEnvironment.cpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SensorsAidlEnvironment.h"
+
+#include <android/binder_manager.h>
+#include <log/log.h>
+
+#include <aidl/android/hardware/sensors/BnSensorsCallback.h>
+
+using aidl::android::hardware::sensors::BnSensorsCallback;
+using aidl::android::hardware::sensors::SensorInfo;
+using android::hardware::EventFlag;
+using ndk::ScopedAStatus;
+using ndk::SpAIBinder;
+
+namespace {
+
+void serviceDied(void* /* cookie */) {
+ ALOGE("Sensors HAL died (likely crashed) during test");
+ FAIL() << "Sensors HAL died during test";
+}
+
+class NoOpSensorsCallback : public BnSensorsCallback {
+ public:
+ ScopedAStatus onDynamicSensorsConnected(
+ const std::vector<SensorInfo>& /* sensorInfos */) override {
+ return ScopedAStatus::ok();
+ }
+
+ ScopedAStatus onDynamicSensorsDisconnected(
+ const std::vector<int32_t>& /* sensorHandles */) override {
+ return ScopedAStatus::ok();
+ }
+};
+
+} // anonymous namespace
+
+SensorsAidlEnvironment::SensorsAidlEnvironment(const std::string& service_name)
+ : SensorsVtsEnvironmentBase(service_name),
+ mCallback(ndk::SharedRefBase::make<NoOpSensorsCallback>()),
+ mDeathRecipient(AIBinder_DeathRecipient_new(serviceDied)) {}
+
+bool SensorsAidlEnvironment::resetHal() {
+ bool succeed = false;
+ do {
+ mSensors = ISensors::fromBinder(
+ SpAIBinder(AServiceManager_waitForService(mServiceName.c_str())));
+ if (mSensors == nullptr) {
+ break;
+ }
+
+ AIBinder_linkToDeath(mSensors->asBinder().get(), mDeathRecipient.get(), this);
+
+ // Initialize FMQs
+ mWakeLockQueue = std::make_unique<WakeLockQueue>(MAX_RECEIVE_BUFFER_EVENT_COUNT,
+ true /* configureEventFlagWord */);
+ mEventQueue = std::make_unique<EventQueue>(MAX_RECEIVE_BUFFER_EVENT_COUNT,
+ true /* configureEventFlagWord */);
+
+ if (mWakeLockQueue == nullptr || mEventQueue == nullptr) {
+ break;
+ }
+
+ EventFlag::deleteEventFlag(&mEventQueueFlag);
+ EventFlag::createEventFlag(mEventQueue->getEventFlagWord(), &mEventQueueFlag);
+ if (mEventQueueFlag == nullptr) {
+ break;
+ }
+
+ mSensors->initialize(mEventQueue->dupeDesc(), mWakeLockQueue->dupeDesc(), mCallback);
+
+ std::vector<SensorInfo> sensorList;
+ if (!mSensors->getSensorsList(&sensorList).isOk()) {
+ break;
+ }
+
+ // stop each sensor individually
+ bool ok = true;
+ for (const auto& i : sensorList) {
+ if (!mSensors->activate(i.sensorHandle, false).isOk()) {
+ ok = false;
+ break;
+ }
+ }
+
+ if (!ok) {
+ break;
+ }
+
+ // mark it done
+ succeed = true;
+ } while (0);
+
+ if (!succeed) {
+ mSensors = nullptr;
+ }
+
+ return succeed;
+}
+
+void SensorsAidlEnvironment::TearDown() {
+ mStopThread = true;
+
+ if (mEventQueueFlag != nullptr) {
+ // Wake up the event queue so the poll thread can exit
+ mEventQueueFlag->wake(ISensors::EVENT_QUEUE_FLAG_BITS_READ_AND_PROCESS);
+ if (mPollThread.joinable()) {
+ mPollThread.join();
+ }
+
+ EventFlag::deleteEventFlag(&mEventQueueFlag);
+ }
+}
+
+void SensorsAidlEnvironment::startPollingThread() {
+ mStopThread = false;
+ mEvents.reserve(MAX_RECEIVE_BUFFER_EVENT_COUNT);
+ mPollThread = std::thread(pollingThread, this);
+}
+
+void SensorsAidlEnvironment::readEvents() {
+ size_t availableEvents = mEventQueue->availableToRead();
+
+ if (availableEvents == 0) {
+ uint32_t eventFlagState = 0;
+
+ mEventQueueFlag->wait(ISensors::EVENT_QUEUE_FLAG_BITS_READ_AND_PROCESS, &eventFlagState);
+ availableEvents = mEventQueue->availableToRead();
+ }
+
+ size_t eventsToRead = std::min(availableEvents, mEventBuffer.size());
+ if (eventsToRead > 0) {
+ if (mEventQueue->read(mEventBuffer.data(), eventsToRead)) {
+ mEventQueueFlag->wake(ISensors::EVENT_QUEUE_FLAG_BITS_EVENTS_READ);
+ for (size_t i = 0; i < eventsToRead; i++) {
+ addEvent(mEventBuffer[i]);
+ }
+ }
+ }
+}
+
+void SensorsAidlEnvironment::pollingThread(SensorsAidlEnvironment* env) {
+ ALOGD("polling thread start");
+
+ while (!env->mStopThread.load()) {
+ env->readEvents();
+ }
+
+ ALOGD("polling thread end");
+}
diff --git a/sensors/aidl/vts/SensorsAidlEnvironment.h b/sensors/aidl/vts/SensorsAidlEnvironment.h
new file mode 100644
index 0000000..2f5f287
--- /dev/null
+++ b/sensors/aidl/vts/SensorsAidlEnvironment.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SENSORS_AIDL_ENVIRONMENT_H
+#define ANDROID_SENSORS_AIDL_ENVIRONMENT_H
+
+#include "sensors-vts-utils/SensorsVtsEnvironmentBase.h"
+
+#include <atomic>
+#include <memory>
+#include <mutex>
+#include <thread>
+#include <vector>
+
+#include <aidl/android/hardware/sensors/ISensors.h>
+#include <fmq/AidlMessageQueue.h>
+
+using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using aidl::android::hardware::sensors::Event;
+using aidl::android::hardware::sensors::ISensors;
+using aidl::android::hardware::sensors::ISensorsCallback;
+
+static constexpr size_t MAX_RECEIVE_BUFFER_EVENT_COUNT = 256;
+
+class SensorsAidlTest;
+
+class SensorsAidlEnvironment : public SensorsVtsEnvironmentBase<Event> {
+ public:
+ virtual void TearDown() override;
+
+ protected:
+ friend SensorsAidlTest;
+ SensorsAidlEnvironment(const std::string& service_name);
+
+ /**
+ * Resets the HAL with new FMQs and a new Event Flag
+ *
+ * @return bool true if successful, false otherwise
+ */
+ bool resetHal() override;
+
+ /**
+ * Starts the polling thread that reads sensor events from the Event FMQ
+ */
+ void startPollingThread() override;
+
+ /**
+ * Thread responsible for calling functions to read Event FMQ
+ *
+ * @param env SensorEnvironment to being polling for events on
+ */
+ static void pollingThread(SensorsAidlEnvironment* env);
+
+ /**
+ * Reads and saves sensor events from the Event FMQ
+ */
+ void readEvents();
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsAidlEnvironment);
+
+ /**
+ * Pointer to the Sensors HAL Interface that allows the test to call HAL functions.
+ */
+ std::shared_ptr<ISensors> mSensors;
+ std::shared_ptr<ISensorsCallback> mCallback;
+
+ ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
+
+ /**
+ * Type used to simplify the creation of the Wake Lock FMQ
+ */
+ typedef android::AidlMessageQueue<int32_t, SynchronizedReadWrite> WakeLockQueue;
+ typedef android::AidlMessageQueue<Event, SynchronizedReadWrite> EventQueue;
+
+ /**
+ * The Wake Lock FMQ is used by the test to notify the Sensors HAL whenever it has processed
+ * WAKE_UP sensor events.
+ */
+ std::unique_ptr<WakeLockQueue> mWakeLockQueue;
+ std::unique_ptr<EventQueue> mEventQueue;
+
+ /**
+ * The Event Queue Flag notifies the test framework when sensor events have been written to the
+ * Event FMQ by the Sensors HAL.
+ */
+ ::android::hardware::EventFlag* mEventQueueFlag;
+
+ std::atomic_bool mStopThread;
+ std::thread mPollThread;
+
+ /**
+ * An array that is used to store sensor events read from the Event FMQ
+ */
+ std::array<Event, MAX_RECEIVE_BUFFER_EVENT_COUNT> mEventBuffer;
+};
+
+#endif // ANDROID_SENSORS_AIDL_ENVIRONMENT_H
diff --git a/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp b/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp
new file mode 100644
index 0000000..33645b2
--- /dev/null
+++ b/sensors/aidl/vts/VtsAidlHalSensorsTargetTest.cpp
@@ -0,0 +1,871 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+
+#include <aidl/android/hardware/sensors/BnSensors.h>
+#include <aidl/android/hardware/sensors/ISensors.h>
+#include <android/binder_manager.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <hardware/sensors.h>
+#include <log/log.h>
+#include <utils/SystemClock.h>
+
+#include "SensorsAidlEnvironment.h"
+#include "sensors-vts-utils/SensorsVtsEnvironmentBase.h"
+
+#include <cinttypes>
+#include <condition_variable>
+#include <map>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+using aidl::android::hardware::sensors::Event;
+using aidl::android::hardware::sensors::ISensors;
+using aidl::android::hardware::sensors::SensorInfo;
+using aidl::android::hardware::sensors::SensorStatus;
+using aidl::android::hardware::sensors::SensorType;
+using android::ProcessState;
+using std::chrono::duration_cast;
+
+namespace {
+
+static void assertTypeMatchStringType(SensorType type, const std::string& stringType) {
+ if (type >= SensorType::DEVICE_PRIVATE_BASE) {
+ return;
+ }
+
+ switch (type) {
+#define CHECK_TYPE_STRING_FOR_SENSOR_TYPE(type) \
+ case SensorType::type: \
+ ASSERT_STREQ(SENSOR_STRING_TYPE_##type, stringType.c_str()); \
+ break;
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ACCELEROMETER);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ACCELEROMETER_UNCALIBRATED);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ADDITIONAL_INFO);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(AMBIENT_TEMPERATURE);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(DEVICE_ORIENTATION);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(DYNAMIC_SENSOR_META);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GAME_ROTATION_VECTOR);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GEOMAGNETIC_ROTATION_VECTOR);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GLANCE_GESTURE);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GRAVITY);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GYROSCOPE);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GYROSCOPE_UNCALIBRATED);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(HEART_BEAT);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(HEART_RATE);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LIGHT);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LINEAR_ACCELERATION);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LOW_LATENCY_OFFBODY_DETECT);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MAGNETIC_FIELD);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MAGNETIC_FIELD_UNCALIBRATED);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MOTION_DETECT);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ORIENTATION);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PICK_UP_GESTURE);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(POSE_6DOF);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PRESSURE);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PROXIMITY);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(RELATIVE_HUMIDITY);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ROTATION_VECTOR);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(SIGNIFICANT_MOTION);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STATIONARY_DETECT);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STEP_COUNTER);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STEP_DETECTOR);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(TILT_DETECTOR);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(WAKE_GESTURE);
+ CHECK_TYPE_STRING_FOR_SENSOR_TYPE(WRIST_TILT_GESTURE);
+ default:
+ FAIL() << "Type " << static_cast<int>(type)
+ << " in android defined range is not checked, "
+ << "stringType = " << stringType;
+#undef CHECK_TYPE_STRING_FOR_SENSOR_TYPE
+ }
+}
+
+int expectedReportModeForType(SensorType type) {
+ switch (type) {
+ case SensorType::ACCELEROMETER:
+ case SensorType::ACCELEROMETER_UNCALIBRATED:
+ case SensorType::GYROSCOPE:
+ case SensorType::MAGNETIC_FIELD:
+ case SensorType::ORIENTATION:
+ case SensorType::PRESSURE:
+ case SensorType::GRAVITY:
+ case SensorType::LINEAR_ACCELERATION:
+ case SensorType::ROTATION_VECTOR:
+ case SensorType::MAGNETIC_FIELD_UNCALIBRATED:
+ case SensorType::GAME_ROTATION_VECTOR:
+ case SensorType::GYROSCOPE_UNCALIBRATED:
+ case SensorType::GEOMAGNETIC_ROTATION_VECTOR:
+ case SensorType::POSE_6DOF:
+ case SensorType::HEART_BEAT:
+ return SensorInfo::SENSOR_FLAG_BITS_CONTINUOUS_MODE;
+
+ case SensorType::LIGHT:
+ case SensorType::PROXIMITY:
+ case SensorType::RELATIVE_HUMIDITY:
+ case SensorType::AMBIENT_TEMPERATURE:
+ case SensorType::HEART_RATE:
+ case SensorType::DEVICE_ORIENTATION:
+ case SensorType::STEP_COUNTER:
+ case SensorType::LOW_LATENCY_OFFBODY_DETECT:
+ return SensorInfo::SENSOR_FLAG_BITS_ON_CHANGE_MODE;
+
+ case SensorType::SIGNIFICANT_MOTION:
+ case SensorType::WAKE_GESTURE:
+ case SensorType::GLANCE_GESTURE:
+ case SensorType::PICK_UP_GESTURE:
+ case SensorType::MOTION_DETECT:
+ case SensorType::STATIONARY_DETECT:
+ return SensorInfo::SENSOR_FLAG_BITS_ONE_SHOT_MODE;
+
+ case SensorType::STEP_DETECTOR:
+ case SensorType::TILT_DETECTOR:
+ case SensorType::WRIST_TILT_GESTURE:
+ case SensorType::DYNAMIC_SENSOR_META:
+ return SensorInfo::SENSOR_FLAG_BITS_SPECIAL_REPORTING_MODE;
+
+ default:
+ ALOGW("Type %d is not implemented in expectedReportModeForType", (int)type);
+ return INT32_MAX;
+ }
+}
+
+void assertTypeMatchReportMode(SensorType type, int reportMode) {
+ if (type >= SensorType::DEVICE_PRIVATE_BASE) {
+ return;
+ }
+
+ int expected = expectedReportModeForType(type);
+
+ ASSERT_TRUE(expected == INT32_MAX || expected == reportMode)
+ << "reportMode=" << static_cast<int>(reportMode)
+ << "expected=" << static_cast<int>(expected);
+}
+
+void assertDelayMatchReportMode(int32_t minDelayUs, int32_t maxDelayUs, int reportMode) {
+ switch (reportMode) {
+ case SensorInfo::SENSOR_FLAG_BITS_CONTINUOUS_MODE:
+ ASSERT_LT(0, minDelayUs);
+ ASSERT_LE(0, maxDelayUs);
+ break;
+ case SensorInfo::SENSOR_FLAG_BITS_ON_CHANGE_MODE:
+ ASSERT_LE(0, minDelayUs);
+ ASSERT_LE(0, maxDelayUs);
+ break;
+ case SensorInfo::SENSOR_FLAG_BITS_ONE_SHOT_MODE:
+ ASSERT_EQ(-1, minDelayUs);
+ ASSERT_EQ(0, maxDelayUs);
+ break;
+ case SensorInfo::SENSOR_FLAG_BITS_SPECIAL_REPORTING_MODE:
+ // do not enforce anything for special reporting mode
+ break;
+ default:
+ FAIL() << "Report mode " << static_cast<int>(reportMode) << " not checked";
+ }
+}
+
+void checkIsOk(ndk::ScopedAStatus status) {
+ ASSERT_TRUE(status.isOk());
+}
+
+} // namespace
+
+class EventCallback : public IEventCallback<Event> {
+ public:
+ void reset() {
+ mFlushMap.clear();
+ mEventMap.clear();
+ }
+
+ void onEvent(const Event& event) override {
+ if (event.sensorType == SensorType::META_DATA &&
+ event.payload.get<Event::EventPayload::Tag::meta>().what ==
+ Event::EventPayload::MetaData::MetaDataEventType::META_DATA_FLUSH_COMPLETE) {
+ std::unique_lock<std::recursive_mutex> lock(mFlushMutex);
+ mFlushMap[event.sensorHandle]++;
+ mFlushCV.notify_all();
+ } else if (event.sensorType != SensorType::ADDITIONAL_INFO) {
+ std::unique_lock<std::recursive_mutex> lock(mEventMutex);
+ mEventMap[event.sensorHandle].push_back(event);
+ mEventCV.notify_all();
+ }
+ }
+
+ int32_t getFlushCount(int32_t sensorHandle) {
+ std::unique_lock<std::recursive_mutex> lock(mFlushMutex);
+ return mFlushMap[sensorHandle];
+ }
+
+ void waitForFlushEvents(const std::vector<SensorInfo>& sensorsToWaitFor,
+ int32_t numCallsToFlush, std::chrono::milliseconds timeout) {
+ std::unique_lock<std::recursive_mutex> lock(mFlushMutex);
+ mFlushCV.wait_for(lock, timeout,
+ [&] { return flushesReceived(sensorsToWaitFor, numCallsToFlush); });
+ }
+
+ const std::vector<Event> getEvents(int32_t sensorHandle) {
+ std::unique_lock<std::recursive_mutex> lock(mEventMutex);
+ return mEventMap[sensorHandle];
+ }
+
+ void waitForEvents(const std::vector<SensorInfo>& sensorsToWaitFor,
+ std::chrono::milliseconds timeout) {
+ std::unique_lock<std::recursive_mutex> lock(mEventMutex);
+ mEventCV.wait_for(lock, timeout, [&] { return eventsReceived(sensorsToWaitFor); });
+ }
+
+ protected:
+ bool flushesReceived(const std::vector<SensorInfo>& sensorsToWaitFor, int32_t numCallsToFlush) {
+ for (const SensorInfo& sensor : sensorsToWaitFor) {
+ if (getFlushCount(sensor.sensorHandle) < numCallsToFlush) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ bool eventsReceived(const std::vector<SensorInfo>& sensorsToWaitFor) {
+ for (const SensorInfo& sensor : sensorsToWaitFor) {
+ if (getEvents(sensor.sensorHandle).size() == 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ std::map<int32_t, int32_t> mFlushMap;
+ std::recursive_mutex mFlushMutex;
+ std::condition_variable_any mFlushCV;
+
+ std::map<int32_t, std::vector<Event>> mEventMap;
+ std::recursive_mutex mEventMutex;
+ std::condition_variable_any mEventCV;
+};
+
+class SensorsAidlTest : public testing::TestWithParam<std::string> {
+ public:
+ virtual void SetUp() override {
+ mEnvironment = new SensorsAidlEnvironment(GetParam());
+ mEnvironment->SetUp();
+
+ // Ensure that we have a valid environment before performing tests
+ ASSERT_NE(getSensors(), nullptr);
+ }
+
+ virtual void TearDown() override {
+ for (int32_t handle : mSensorHandles) {
+ activate(handle, false);
+ }
+ mSensorHandles.clear();
+
+ mEnvironment->TearDown();
+ delete mEnvironment;
+ mEnvironment = nullptr;
+ }
+
+ protected:
+ std::vector<SensorInfo> getNonOneShotSensors();
+ std::vector<SensorInfo> getNonOneShotAndNonSpecialSensors();
+ std::vector<SensorInfo> getNonOneShotAndNonOnChangeAndNonSpecialSensors();
+ std::vector<SensorInfo> getOneShotSensors();
+ std::vector<SensorInfo> getInjectEventSensors();
+
+ inline std::shared_ptr<ISensors>& getSensors() { return mEnvironment->mSensors; }
+
+ inline SensorsAidlEnvironment* getEnvironment() { return mEnvironment; }
+
+ inline bool isValidType(SensorType sensorType) { return (int)sensorType > 0; }
+
+ std::vector<SensorInfo> getSensorsList();
+
+ int32_t getInvalidSensorHandle() {
+ // Find a sensor handle that does not exist in the sensor list
+ int32_t maxHandle = 0;
+ for (const SensorInfo& sensor : getSensorsList()) {
+ maxHandle = std::max(maxHandle, sensor.sensorHandle);
+ }
+ return maxHandle + 1;
+ }
+
+ ndk::ScopedAStatus activate(int32_t sensorHandle, bool enable);
+ void activateAllSensors(bool enable);
+
+ ndk::ScopedAStatus batch(int32_t sensorHandle, int64_t samplingPeriodNs,
+ int64_t maxReportLatencyNs) {
+ return getSensors()->batch(sensorHandle, samplingPeriodNs, maxReportLatencyNs);
+ }
+
+ ndk::ScopedAStatus flush(int32_t sensorHandle) { return getSensors()->flush(sensorHandle); }
+
+ void runSingleFlushTest(const std::vector<SensorInfo>& sensors, bool activateSensor,
+ int32_t expectedFlushCount, bool expectedResult);
+
+ void runFlushTest(const std::vector<SensorInfo>& sensors, bool activateSensor,
+ int32_t flushCalls, int32_t expectedFlushCount, bool expectedResult);
+
+ inline static int32_t extractReportMode(int32_t flag) {
+ return (flag & (SensorInfo::SENSOR_FLAG_BITS_CONTINUOUS_MODE |
+ SensorInfo::SENSOR_FLAG_BITS_ON_CHANGE_MODE |
+ SensorInfo::SENSOR_FLAG_BITS_ONE_SHOT_MODE |
+ SensorInfo::SENSOR_FLAG_BITS_SPECIAL_REPORTING_MODE));
+ }
+
+ // All sensors and direct channnels used
+ std::unordered_set<int32_t> mSensorHandles;
+ std::unordered_set<int32_t> mDirectChannelHandles;
+
+ private:
+ SensorsAidlEnvironment* mEnvironment;
+};
+
+std::vector<SensorInfo> SensorsAidlTest::getSensorsList() {
+ std::vector<SensorInfo> sensorInfoList;
+ checkIsOk(getSensors()->getSensorsList(&sensorInfoList));
+ return sensorInfoList;
+}
+
+ndk::ScopedAStatus SensorsAidlTest::activate(int32_t sensorHandle, bool enable) {
+ // If activating a sensor, add the handle in a set so that when test fails it can be turned off.
+ // The handle is not removed when it is deactivating on purpose so that it is not necessary to
+ // check the return value of deactivation. Deactivating a sensor more than once does not have
+ // negative effect.
+ if (enable) {
+ mSensorHandles.insert(sensorHandle);
+ }
+ return getSensors()->activate(sensorHandle, enable);
+}
+
+void SensorsAidlTest::activateAllSensors(bool enable) {
+ for (const SensorInfo& sensorInfo : getSensorsList()) {
+ if (isValidType(sensorInfo.type)) {
+ checkIsOk(batch(sensorInfo.sensorHandle, sensorInfo.minDelayUs,
+ 0 /* maxReportLatencyNs */));
+ checkIsOk(activate(sensorInfo.sensorHandle, enable));
+ }
+ }
+}
+
+std::vector<SensorInfo> SensorsAidlTest::getNonOneShotSensors() {
+ std::vector<SensorInfo> sensors;
+ for (const SensorInfo& info : getSensorsList()) {
+ if (extractReportMode(info.flags) != SensorInfo::SENSOR_FLAG_BITS_ONE_SHOT_MODE) {
+ sensors.push_back(info);
+ }
+ }
+ return sensors;
+}
+
+std::vector<SensorInfo> SensorsAidlTest::getNonOneShotAndNonSpecialSensors() {
+ std::vector<SensorInfo> sensors;
+ for (const SensorInfo& info : getSensorsList()) {
+ int reportMode = extractReportMode(info.flags);
+ if (reportMode != SensorInfo::SENSOR_FLAG_BITS_ONE_SHOT_MODE &&
+ reportMode != SensorInfo::SENSOR_FLAG_BITS_SPECIAL_REPORTING_MODE) {
+ sensors.push_back(info);
+ }
+ }
+ return sensors;
+}
+
+std::vector<SensorInfo> SensorsAidlTest::getNonOneShotAndNonOnChangeAndNonSpecialSensors() {
+ std::vector<SensorInfo> sensors;
+ for (const SensorInfo& info : getSensorsList()) {
+ int reportMode = extractReportMode(info.flags);
+ if (reportMode != SensorInfo::SENSOR_FLAG_BITS_ONE_SHOT_MODE &&
+ reportMode != SensorInfo::SENSOR_FLAG_BITS_ON_CHANGE_MODE &&
+ reportMode != SensorInfo::SENSOR_FLAG_BITS_SPECIAL_REPORTING_MODE) {
+ sensors.push_back(info);
+ }
+ }
+ return sensors;
+}
+
+std::vector<SensorInfo> SensorsAidlTest::getOneShotSensors() {
+ std::vector<SensorInfo> sensors;
+ for (const SensorInfo& info : getSensorsList()) {
+ if (extractReportMode(info.flags) == SensorInfo::SENSOR_FLAG_BITS_ONE_SHOT_MODE) {
+ sensors.push_back(info);
+ }
+ }
+ return sensors;
+}
+
+std::vector<SensorInfo> SensorsAidlTest::getInjectEventSensors() {
+ std::vector<SensorInfo> out;
+ std::vector<SensorInfo> sensorInfoList = getSensorsList();
+ for (const SensorInfo& info : sensorInfoList) {
+ if (info.flags & SensorInfo::SENSOR_FLAG_BITS_DATA_INJECTION) {
+ out.push_back(info);
+ }
+ }
+ return out;
+}
+
+void SensorsAidlTest::runSingleFlushTest(const std::vector<SensorInfo>& sensors,
+ bool activateSensor, int32_t expectedFlushCount,
+ bool expectedResult) {
+ runFlushTest(sensors, activateSensor, 1 /* flushCalls */, expectedFlushCount, expectedResult);
+}
+
+void SensorsAidlTest::runFlushTest(const std::vector<SensorInfo>& sensors, bool activateSensor,
+ int32_t flushCalls, int32_t expectedFlushCount,
+ bool expectedResult) {
+ EventCallback callback;
+ getEnvironment()->registerCallback(&callback);
+
+ for (const SensorInfo& sensor : sensors) {
+ // Configure and activate the sensor
+ batch(sensor.sensorHandle, sensor.maxDelayUs, 0 /* maxReportLatencyNs */);
+ activate(sensor.sensorHandle, activateSensor);
+
+ // Flush the sensor
+ for (int32_t i = 0; i < flushCalls; i++) {
+ SCOPED_TRACE(::testing::Message()
+ << "Flush " << i << "/" << flushCalls << ": "
+ << " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
+ << sensor.sensorHandle << std::dec
+ << " type=" << static_cast<int>(sensor.type) << " name=" << sensor.name);
+
+ EXPECT_EQ(flush(sensor.sensorHandle).isOk(), expectedResult);
+ }
+ }
+
+ // Wait up to one second for the flush events
+ callback.waitForFlushEvents(sensors, flushCalls, std::chrono::milliseconds(1000) /* timeout */);
+
+ // Deactivate all sensors after waiting for flush events so pending flush events are not
+ // abandoned by the HAL.
+ for (const SensorInfo& sensor : sensors) {
+ activate(sensor.sensorHandle, false);
+ }
+ getEnvironment()->unregisterCallback();
+
+ // Check that the correct number of flushes are present for each sensor
+ for (const SensorInfo& sensor : sensors) {
+ SCOPED_TRACE(::testing::Message()
+ << " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
+ << sensor.sensorHandle << std::dec << " type=" << static_cast<int>(sensor.type)
+ << " name=" << sensor.name);
+ ASSERT_EQ(callback.getFlushCount(sensor.sensorHandle), expectedFlushCount);
+ }
+}
+
+TEST_P(SensorsAidlTest, SensorListValid) {
+ std::vector<SensorInfo> sensorInfoList = getSensorsList();
+ std::unordered_map<int32_t, std::vector<std::string>> sensorTypeNameMap;
+ for (size_t i = 0; i < sensorInfoList.size(); ++i) {
+ const SensorInfo& info = sensorInfoList[i];
+ SCOPED_TRACE(::testing::Message()
+ << i << "/" << sensorInfoList.size() << ": "
+ << " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
+ << info.sensorHandle << std::dec << " type=" << static_cast<int>(info.type)
+ << " name=" << info.name);
+
+ // Test type string non-empty only for private sensor typeinfo.
+ if (info.type >= SensorType::DEVICE_PRIVATE_BASE) {
+ EXPECT_FALSE(info.typeAsString.empty());
+ } else if (!info.typeAsString.empty()) {
+ // Test type string matches framework string if specified for non-private typeinfo.
+ EXPECT_NO_FATAL_FAILURE(assertTypeMatchStringType(info.type, info.typeAsString));
+ }
+
+ // Test if all sensor has name and vendor
+ EXPECT_FALSE(info.name.empty());
+ EXPECT_FALSE(info.vendor.empty());
+
+ // Make sure that sensors of the same type have a unique name.
+ std::vector<std::string>& v = sensorTypeNameMap[static_cast<int32_t>(info.type)];
+ bool isUniqueName = std::find(v.begin(), v.end(), info.name) == v.end();
+ EXPECT_TRUE(isUniqueName) << "Duplicate sensor Name: " << info.name;
+ if (isUniqueName) {
+ v.push_back(info.name);
+ }
+
+ EXPECT_LE(0, info.power);
+ EXPECT_LT(0, info.maxRange);
+
+ // Info type, should have no sensor
+ EXPECT_FALSE(info.type == SensorType::ADDITIONAL_INFO ||
+ info.type == SensorType::META_DATA);
+
+ EXPECT_GE(info.fifoMaxEventCount, info.fifoReservedEventCount);
+
+ // Test Reporting mode valid
+ EXPECT_NO_FATAL_FAILURE(
+ assertTypeMatchReportMode(info.type, extractReportMode(info.flags)));
+
+ // Test min max are in the right order
+ EXPECT_LE(info.minDelayUs, info.maxDelayUs);
+ // Test min/max delay matches reporting mode
+ EXPECT_NO_FATAL_FAILURE(assertDelayMatchReportMode(info.minDelayUs, info.maxDelayUs,
+ extractReportMode(info.flags)));
+ }
+}
+
+TEST_P(SensorsAidlTest, SetOperationMode) {
+ if (getInjectEventSensors().size() > 0) {
+ ASSERT_TRUE(getSensors()->setOperationMode(ISensors::OperationMode::NORMAL).isOk());
+ ASSERT_TRUE(getSensors()->setOperationMode(ISensors::OperationMode::DATA_INJECTION).isOk());
+ ASSERT_TRUE(getSensors()->setOperationMode(ISensors::OperationMode::NORMAL).isOk());
+ } else {
+ ASSERT_EQ(getSensors()
+ ->setOperationMode(ISensors::OperationMode::DATA_INJECTION)
+ .getExceptionCode(),
+ EX_UNSUPPORTED_OPERATION);
+ }
+}
+
+TEST_P(SensorsAidlTest, InjectSensorEventData) {
+ std::vector<SensorInfo> sensors = getInjectEventSensors();
+ if (sensors.size() == 0) {
+ return;
+ }
+
+ ASSERT_TRUE(getSensors()->setOperationMode(ISensors::OperationMode::DATA_INJECTION).isOk());
+
+ EventCallback callback;
+ getEnvironment()->registerCallback(&callback);
+
+ // AdditionalInfo event should not be sent to Event FMQ
+ Event additionalInfoEvent;
+ additionalInfoEvent.sensorType = SensorType::ADDITIONAL_INFO;
+ additionalInfoEvent.timestamp = android::elapsedRealtimeNano();
+
+ Event injectedEvent;
+ injectedEvent.timestamp = android::elapsedRealtimeNano();
+ Event::EventPayload::Vec3 data = {1, 2, 3, SensorStatus::ACCURACY_HIGH};
+ injectedEvent.payload.set<Event::EventPayload::Tag::vec3>(data);
+
+ for (const auto& s : sensors) {
+ additionalInfoEvent.sensorHandle = s.sensorHandle;
+ ASSERT_TRUE(getSensors()->injectSensorData(additionalInfoEvent).isOk());
+
+ injectedEvent.sensorType = s.type;
+ injectedEvent.sensorHandle = s.sensorHandle;
+ ASSERT_TRUE(getSensors()->injectSensorData(injectedEvent).isOk());
+ }
+
+ // Wait for events to be written back to the Event FMQ
+ callback.waitForEvents(sensors, std::chrono::milliseconds(1000) /* timeout */);
+ getEnvironment()->unregisterCallback();
+
+ for (const auto& s : sensors) {
+ auto events = callback.getEvents(s.sensorHandle);
+ if (events.empty()) {
+ FAIL() << "Received no events";
+ } else {
+ auto lastEvent = events.back();
+ SCOPED_TRACE(::testing::Message()
+ << " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
+ << s.sensorHandle << std::dec << " type=" << static_cast<int>(s.type)
+ << " name=" << s.name);
+
+ // Verify that only a single event has been received
+ ASSERT_EQ(events.size(), 1);
+
+ // Verify that the event received matches the event injected and is not the additional
+ // info event
+ ASSERT_EQ(lastEvent.sensorType, s.type);
+ ASSERT_EQ(lastEvent.timestamp, injectedEvent.timestamp);
+ ASSERT_EQ(lastEvent.payload.get<Event::EventPayload::Tag::vec3>().x,
+ injectedEvent.payload.get<Event::EventPayload::Tag::vec3>().x);
+ ASSERT_EQ(lastEvent.payload.get<Event::EventPayload::Tag::vec3>().y,
+ injectedEvent.payload.get<Event::EventPayload::Tag::vec3>().y);
+ ASSERT_EQ(lastEvent.payload.get<Event::EventPayload::Tag::vec3>().z,
+ injectedEvent.payload.get<Event::EventPayload::Tag::vec3>().z);
+ ASSERT_EQ(lastEvent.payload.get<Event::EventPayload::Tag::vec3>().status,
+ injectedEvent.payload.get<Event::EventPayload::Tag::vec3>().status);
+ }
+ }
+
+ ASSERT_TRUE(getSensors()->setOperationMode(ISensors::OperationMode::NORMAL).isOk());
+}
+
+TEST_P(SensorsAidlTest, CallInitializeTwice) {
+ // Create a helper class so that a second environment is able to be instantiated
+ class SensorsAidlEnvironmentTest : public SensorsAidlEnvironment {
+ public:
+ SensorsAidlEnvironmentTest(const std::string& service_name)
+ : SensorsAidlEnvironment(service_name) {}
+ };
+
+ 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<SensorsAidlEnvironmentTest> newEnv =
+ std::make_unique<SensorsAidlEnvironmentTest>(GetParam());
+ newEnv->SetUp();
+ if (HasFatalFailure()) {
+ return; // Exit early if setting up the new environment failed
+ }
+
+ activateAllSensors(true);
+ // Verify that the old environment does not receive any events
+ EXPECT_EQ(getEnvironment()->collectEvents(kCollectionTimeoutUs, kNumEvents).size(), 0);
+ // Verify that the new event queue receives sensor events
+ EXPECT_GE(newEnv.get()->collectEvents(kCollectionTimeoutUs, kNumEvents).size(), kNumEvents);
+ activateAllSensors(false);
+
+ // Cleanup the test environment
+ newEnv->TearDown();
+
+ // Restore the test environment for future tests
+ getEnvironment()->TearDown();
+ getEnvironment()->SetUp();
+ if (HasFatalFailure()) {
+ return; // Exit early if resetting the environment failed
+ }
+
+ // Ensure that the original environment is receiving events
+ activateAllSensors(true);
+ EXPECT_GE(getEnvironment()->collectEvents(kCollectionTimeoutUs, kNumEvents).size(), kNumEvents);
+ activateAllSensors(false);
+}
+
+TEST_P(SensorsAidlTest, CleanupConnectionsOnInitialize) {
+ activateAllSensors(true);
+
+ // Verify that events are received
+ constexpr useconds_t kCollectionTimeoutUs = 1000 * 1000; // 1s
+ constexpr int32_t kNumEvents = 1;
+ ASSERT_GE(getEnvironment()->collectEvents(kCollectionTimeoutUs, kNumEvents).size(), kNumEvents);
+
+ // Clear the active sensor handles so they are not disabled during TearDown
+ auto handles = mSensorHandles;
+ mSensorHandles.clear();
+ getEnvironment()->TearDown();
+ getEnvironment()->SetUp();
+ if (HasFatalFailure()) {
+ return; // Exit early if resetting the environment failed
+ }
+
+ // Verify no events are received until sensors are re-activated
+ ASSERT_EQ(getEnvironment()->collectEvents(kCollectionTimeoutUs, kNumEvents).size(), 0);
+ activateAllSensors(true);
+ ASSERT_GE(getEnvironment()->collectEvents(kCollectionTimeoutUs, kNumEvents).size(), kNumEvents);
+
+ // Disable sensors
+ activateAllSensors(false);
+
+ // Restore active sensors prior to clearing the environment
+ mSensorHandles = handles;
+}
+
+TEST_P(SensorsAidlTest, FlushSensor) {
+ std::vector<SensorInfo> sensors = getNonOneShotSensors();
+ if (sensors.size() == 0) {
+ return;
+ }
+
+ constexpr int32_t kFlushes = 5;
+ runSingleFlushTest(sensors, true /* activateSensor */, 1 /* expectedFlushCount */,
+ true /* expectedResult */);
+ runFlushTest(sensors, true /* activateSensor */, kFlushes, kFlushes, true /* expectedResult */);
+}
+
+TEST_P(SensorsAidlTest, FlushOneShotSensor) {
+ // Find a sensor that is a one-shot sensor
+ std::vector<SensorInfo> sensors = getOneShotSensors();
+ if (sensors.size() == 0) {
+ return;
+ }
+
+ runSingleFlushTest(sensors, true /* activateSensor */, 0 /* expectedFlushCount */,
+ false /* expectedResult */);
+}
+
+TEST_P(SensorsAidlTest, FlushInactiveSensor) {
+ // Attempt to find a non-one shot sensor, then a one-shot sensor if necessary
+ std::vector<SensorInfo> sensors = getNonOneShotSensors();
+ if (sensors.size() == 0) {
+ sensors = getOneShotSensors();
+ if (sensors.size() == 0) {
+ return;
+ }
+ }
+
+ runSingleFlushTest(sensors, false /* activateSensor */, 0 /* expectedFlushCount */,
+ false /* expectedResult */);
+}
+
+TEST_P(SensorsAidlTest, Batch) {
+ if (getSensorsList().size() == 0) {
+ return;
+ }
+
+ activateAllSensors(false /* enable */);
+ for (const SensorInfo& sensor : getSensorsList()) {
+ SCOPED_TRACE(::testing::Message()
+ << " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
+ << sensor.sensorHandle << std::dec << " type=" << static_cast<int>(sensor.type)
+ << " name=" << sensor.name);
+
+ // Call batch on inactive sensor
+ // One shot sensors have minDelay set to -1 which is an invalid
+ // parameter. Use 0 instead to avoid errors.
+ int64_t samplingPeriodNs =
+ extractReportMode(sensor.flags) == SensorInfo::SENSOR_FLAG_BITS_ONE_SHOT_MODE
+ ? 0
+ : sensor.minDelayUs;
+ checkIsOk(batch(sensor.sensorHandle, samplingPeriodNs, 0 /* maxReportLatencyNs */));
+
+ // Activate the sensor
+ activate(sensor.sensorHandle, true /* enabled */);
+
+ // Call batch on an active sensor
+ checkIsOk(batch(sensor.sensorHandle, sensor.maxDelayUs, 0 /* maxReportLatencyNs */));
+ }
+ activateAllSensors(false /* enable */);
+
+ // Call batch on an invalid sensor
+ SensorInfo sensor = getSensorsList().front();
+ sensor.sensorHandle = getInvalidSensorHandle();
+ ASSERT_EQ(batch(sensor.sensorHandle, sensor.minDelayUs, 0 /* maxReportLatencyNs */)
+ .getExceptionCode(),
+ EX_ILLEGAL_ARGUMENT);
+}
+
+TEST_P(SensorsAidlTest, Activate) {
+ if (getSensorsList().size() == 0) {
+ return;
+ }
+
+ // Verify that sensor events are generated when activate is called
+ for (const SensorInfo& sensor : getSensorsList()) {
+ SCOPED_TRACE(::testing::Message()
+ << " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
+ << sensor.sensorHandle << std::dec << " type=" << static_cast<int>(sensor.type)
+ << " name=" << sensor.name);
+
+ checkIsOk(batch(sensor.sensorHandle, sensor.minDelayUs, 0 /* maxReportLatencyNs */));
+ checkIsOk(activate(sensor.sensorHandle, true));
+
+ // Call activate on a sensor that is already activated
+ checkIsOk(activate(sensor.sensorHandle, true));
+
+ // Deactivate the sensor
+ checkIsOk(activate(sensor.sensorHandle, false));
+
+ // Call deactivate on a sensor that is already deactivated
+ checkIsOk(activate(sensor.sensorHandle, false));
+ }
+
+ // Attempt to activate an invalid sensor
+ int32_t invalidHandle = getInvalidSensorHandle();
+ ASSERT_EQ(activate(invalidHandle, true).getExceptionCode(), EX_ILLEGAL_ARGUMENT);
+ ASSERT_EQ(activate(invalidHandle, false).getExceptionCode(), EX_ILLEGAL_ARGUMENT);
+}
+
+TEST_P(SensorsAidlTest, NoStaleEvents) {
+ constexpr std::chrono::milliseconds kFiveHundredMs(500);
+ constexpr std::chrono::milliseconds kOneSecond(1000);
+
+ // Register the callback to receive sensor events
+ EventCallback callback;
+ getEnvironment()->registerCallback(&callback);
+
+ // This test is not valid for one-shot, on-change or special-report-mode sensors
+ const std::vector<SensorInfo> sensors = getNonOneShotAndNonOnChangeAndNonSpecialSensors();
+ std::chrono::milliseconds maxMinDelay(0);
+ for (const SensorInfo& sensor : sensors) {
+ std::chrono::milliseconds minDelay = duration_cast<std::chrono::milliseconds>(
+ std::chrono::microseconds(sensor.minDelayUs));
+ maxMinDelay = std::chrono::milliseconds(std::max(maxMinDelay.count(), minDelay.count()));
+ }
+
+ // Activate the sensors so that they start generating events
+ activateAllSensors(true);
+
+ // According to the CDD, the first sample must be generated within 400ms + 2 * sample_time
+ // and the maximum reporting latency is 100ms + 2 * sample_time. Wait a sufficient amount
+ // of time to guarantee that a sample has arrived.
+ callback.waitForEvents(sensors, kFiveHundredMs + (5 * maxMinDelay));
+ activateAllSensors(false);
+
+ // Save the last received event for each sensor
+ std::map<int32_t, int64_t> lastEventTimestampMap;
+ for (const SensorInfo& sensor : sensors) {
+ SCOPED_TRACE(::testing::Message()
+ << " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
+ << sensor.sensorHandle << std::dec << " type=" << static_cast<int>(sensor.type)
+ << " name=" << sensor.name);
+
+ if (callback.getEvents(sensor.sensorHandle).size() >= 1) {
+ lastEventTimestampMap[sensor.sensorHandle] =
+ callback.getEvents(sensor.sensorHandle).back().timestamp;
+ }
+ }
+
+ // Allow some time to pass, reset the callback, then reactivate the sensors
+ usleep(duration_cast<std::chrono::microseconds>(kOneSecond + (5 * maxMinDelay)).count());
+ callback.reset();
+ activateAllSensors(true);
+ callback.waitForEvents(sensors, kFiveHundredMs + (5 * maxMinDelay));
+ activateAllSensors(false);
+
+ getEnvironment()->unregisterCallback();
+
+ for (const SensorInfo& sensor : sensors) {
+ SCOPED_TRACE(::testing::Message()
+ << " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
+ << sensor.sensorHandle << std::dec << " type=" << static_cast<int>(sensor.type)
+ << " name=" << sensor.name);
+
+ // Skip sensors that did not previously report an event
+ if (lastEventTimestampMap.find(sensor.sensorHandle) == lastEventTimestampMap.end()) {
+ continue;
+ }
+
+ // Ensure that the first event received is not stale by ensuring that its timestamp is
+ // sufficiently different from the previous event
+ const Event newEvent = callback.getEvents(sensor.sensorHandle).front();
+ std::chrono::milliseconds delta =
+ duration_cast<std::chrono::milliseconds>(std::chrono::nanoseconds(
+ newEvent.timestamp - lastEventTimestampMap[sensor.sensorHandle]));
+ std::chrono::milliseconds sensorMinDelay = duration_cast<std::chrono::milliseconds>(
+ std::chrono::microseconds(sensor.minDelayUs));
+ ASSERT_GE(delta, kFiveHundredMs + (3 * sensorMinDelay));
+ }
+}
+
+TEST_P(SensorsAidlTest, DirectChannelAshmem) {
+ // TODO(b/195593357): Implement this
+}
+
+TEST_P(SensorsAidlTest, DirectChannelGralloc) {
+ // TODO(b/195593357): Implement this
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SensorsAidlTest);
+INSTANTIATE_TEST_SUITE_P(Sensors, SensorsAidlTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(ISensors::descriptor)),
+ android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ProcessState::self()->setThreadPoolMaxThreadCount(1);
+ ProcessState::self()->startThreadPool();
+ return RUN_ALL_TESTS();
+}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ITuner.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ITuner.aidl
index decf5b1..0ff2da9 100644
--- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ITuner.aidl
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ITuner.aidl
@@ -45,4 +45,6 @@
android.hardware.tv.tuner.ILnb openLnbById(in int lnbId);
android.hardware.tv.tuner.ILnb openLnbByName(in String lnbName, out int[] lnbId);
void setLna(in boolean bEnable);
+ void setMaxNumberOfFrontends(in android.hardware.tv.tuner.FrontendType frontendType, in int maxNumber);
+ int getMaxNumberOfFrontends(in android.hardware.tv.tuner.FrontendType frontendType);
}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/ITuner.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/ITuner.aidl
index 1fcbb06..03def33 100644
--- a/tv/tuner/aidl/android/hardware/tv/tuner/ITuner.aidl
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/ITuner.aidl
@@ -18,6 +18,7 @@
import android.hardware.tv.tuner.DemuxCapabilities;
import android.hardware.tv.tuner.FrontendInfo;
+import android.hardware.tv.tuner.FrontendType;
import android.hardware.tv.tuner.IDemux;
import android.hardware.tv.tuner.IDescrambler;
import android.hardware.tv.tuner.IFrontend;
@@ -127,4 +128,24 @@
* @param bEnable true if activate LNA module; false if deactivate LNA
*/
void setLna(in boolean bEnable);
+
+ /**
+ * Set the maximum usable frontends number of a given frontend type.
+ *
+ * It is used by the client to enable or disable frontends when cable connection status
+ * is changed by user.
+ *
+ * @param frontendType the frontend type which the maximum usable number will be set.
+ * @param maxNumber the new maximum usable number.
+ */
+ void setMaxNumberOfFrontends(in FrontendType frontendType, in int maxNumber);
+
+ /**
+ * Get the maximum usable frontends number of a given frontend type.
+ *
+ * @param frontendType the frontend type which the maximum usable number will be queried.
+ *
+ * @return the maximum usable number of the queried frontend type.
+ */
+ int getMaxNumberOfFrontends(in FrontendType frontendType);
}
diff --git a/tv/tuner/aidl/default/Tuner.cpp b/tv/tuner/aidl/default/Tuner.cpp
index 45f3dfa..48c1b66 100644
--- a/tv/tuner/aidl/default/Tuner.cpp
+++ b/tv/tuner/aidl/default/Tuner.cpp
@@ -64,6 +64,7 @@
FrontendStatusType::STREAM_ID_LIST,
};
mFrontendStatusCaps[0] = statusCaps;
+ mMaxUsableFrontends[FrontendType::ISDBS] = 1;
FrontendCapabilities capsAtsc3;
capsAtsc3.set<FrontendCapabilities::Tag::atsc3Caps>(FrontendAtsc3Capabilities());
@@ -78,6 +79,7 @@
FrontendStatusType::BANDWIDTH,
};
mFrontendStatusCaps[1] = statusCaps;
+ mMaxUsableFrontends[FrontendType::ATSC3] = 1;
FrontendCapabilities capsDvbc;
capsDvbc.set<FrontendCapabilities::Tag::dvbcCaps>(FrontendDvbcCapabilities());
@@ -89,6 +91,7 @@
FrontendStatusType::INTERLEAVINGS, FrontendStatusType::BANDWIDTH,
};
mFrontendStatusCaps[2] = statusCaps;
+ mMaxUsableFrontends[FrontendType::DVBC] = 1;
FrontendCapabilities capsDvbs;
capsDvbs.set<FrontendCapabilities::Tag::dvbsCaps>(FrontendDvbsCapabilities());
@@ -99,6 +102,7 @@
FrontendStatusType::ROLL_OFF, FrontendStatusType::IS_MISO,
};
mFrontendStatusCaps[3] = statusCaps;
+ mMaxUsableFrontends[FrontendType::DVBS] = 1;
FrontendCapabilities capsDvbt;
capsDvbt.set<FrontendCapabilities::Tag::dvbtCaps>(FrontendDvbtCapabilities());
@@ -115,6 +119,7 @@
FrontendStatusType::DVBT_CELL_IDS,
};
mFrontendStatusCaps[4] = statusCaps;
+ mMaxUsableFrontends[FrontendType::DVBT] = 1;
FrontendCapabilities capsIsdbt;
FrontendIsdbtCapabilities isdbtCaps{
@@ -145,6 +150,7 @@
FrontendStatusType::INTERLEAVINGS,
};
mFrontendStatusCaps[5] = statusCaps;
+ mMaxUsableFrontends[FrontendType::ISDBT] = 1;
FrontendCapabilities capsAnalog;
capsAnalog.set<FrontendCapabilities::Tag::analogCaps>(FrontendAnalogCapabilities());
@@ -156,6 +162,7 @@
FrontendStatusType::TS_DATA_RATES,
};
mFrontendStatusCaps[6] = statusCaps;
+ mMaxUsableFrontends[FrontendType::ANALOG] = 1;
FrontendCapabilities capsAtsc;
capsAtsc.set<FrontendCapabilities::Tag::atscCaps>(FrontendAtscCapabilities());
@@ -167,6 +174,7 @@
FrontendStatusType::IS_LINEAR,
};
mFrontendStatusCaps[7] = statusCaps;
+ mMaxUsableFrontends[FrontendType::ATSC] = 1;
FrontendCapabilities capsIsdbs3;
capsIsdbs3.set<FrontendCapabilities::Tag::isdbs3Caps>(FrontendIsdbs3Capabilities());
@@ -177,6 +185,7 @@
FrontendStatusType::IS_SHORT_FRAMES, FrontendStatusType::STREAM_ID_LIST,
};
mFrontendStatusCaps[8] = statusCaps;
+ mMaxUsableFrontends[FrontendType::ISDBS3] = 1;
FrontendCapabilities capsDtmb;
capsDtmb.set<FrontendCapabilities::Tag::dtmbCaps>(FrontendDtmbCapabilities());
@@ -187,6 +196,7 @@
FrontendStatusType::TRANSMISSION_MODE,
};
mFrontendStatusCaps[9] = statusCaps;
+ mMaxUsableFrontends[FrontendType::DTMB] = 1;
mLnbs.resize(2);
mLnbs[0] = ndk::SharedRefBase::make<Lnb>(0);
@@ -324,6 +334,25 @@
return ::ndk::ScopedAStatus::ok();
}
+::ndk::ScopedAStatus Tuner::setMaxNumberOfFrontends(FrontendType in_frontendType,
+ int32_t in_maxNumber) {
+ ALOGV("%s", __FUNCTION__);
+
+ // In the default implementation, every type only has one frontend.
+ if (in_maxNumber < 0 || in_maxNumber > 1) {
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::INVALID_ARGUMENT));
+ }
+ mMaxUsableFrontends[in_frontendType] = in_maxNumber;
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus Tuner::getMaxNumberOfFrontends(FrontendType in_frontendType,
+ int32_t* _aidl_return) {
+ *_aidl_return = mMaxUsableFrontends[in_frontendType];
+ return ::ndk::ScopedAStatus::ok();
+}
+
binder_status_t Tuner::dump(int fd, const char** args, uint32_t numArgs) {
ALOGV("%s", __FUNCTION__);
{
diff --git a/tv/tuner/aidl/default/Tuner.h b/tv/tuner/aidl/default/Tuner.h
index b33a1be..216a2b6 100644
--- a/tv/tuner/aidl/default/Tuner.h
+++ b/tv/tuner/aidl/default/Tuner.h
@@ -57,6 +57,10 @@
std::vector<int32_t>* out_lnbId,
std::shared_ptr<ILnb>* _aidl_return) override;
::ndk::ScopedAStatus setLna(bool in_bEnable) override;
+ ::ndk::ScopedAStatus setMaxNumberOfFrontends(FrontendType in_frontendType,
+ int32_t in_maxNumber) override;
+ ::ndk::ScopedAStatus getMaxNumberOfFrontends(FrontendType in_frontendType,
+ int32_t* _aidl_return) override;
binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
@@ -81,6 +85,7 @@
// First used id will be 0.
int32_t mLastUsedId = -1;
vector<std::shared_ptr<Lnb>> mLnbs;
+ map<FrontendType, int32_t> mMaxUsableFrontends;
};
} // namespace tuner
diff --git a/tv/tuner/aidl/vts/functional/FrontendTests.cpp b/tv/tuner/aidl/vts/functional/FrontendTests.cpp
index 075ffad..41e98ea 100644
--- a/tv/tuner/aidl/vts/functional/FrontendTests.cpp
+++ b/tv/tuner/aidl/vts/functional/FrontendTests.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include <aidl/android/hardware/tv/tuner/Result.h>
+
#include "FrontendTests.h"
ndk::ScopedAStatus FrontendCallback::onEvent(FrontendEventType frontendEventType) {
@@ -519,6 +521,41 @@
ASSERT_TRUE(closeFrontend());
}
+void FrontendTests::maxNumberOfFrontendsTest() {
+ ASSERT_TRUE(getFrontendIds());
+ for (size_t i = 0; i < mFeIds.size(); i++) {
+ ASSERT_TRUE(getFrontendInfo(mFeIds[i]));
+ int32_t defaultMax = -1;
+ ndk::ScopedAStatus status;
+ // Check default value
+ status = mService->getMaxNumberOfFrontends(mFrontendInfo.type, &defaultMax);
+ ASSERT_TRUE(status.isOk());
+ ASSERT_TRUE(defaultMax > 0);
+ // Set to -1
+ status = mService->setMaxNumberOfFrontends(mFrontendInfo.type, -1);
+ ASSERT_TRUE(status.getServiceSpecificError() ==
+ static_cast<int32_t>(Result::INVALID_ARGUMENT));
+ // Set to defaultMax + 1
+ status = mService->setMaxNumberOfFrontends(mFrontendInfo.type, defaultMax + 1);
+ ASSERT_TRUE(status.getServiceSpecificError() ==
+ static_cast<int32_t>(Result::INVALID_ARGUMENT));
+ // Set to 0
+ status = mService->setMaxNumberOfFrontends(mFrontendInfo.type, 0);
+ ASSERT_TRUE(status.isOk());
+ // Check after set
+ int32_t currentMax = -1;
+ status = mService->getMaxNumberOfFrontends(mFrontendInfo.type, ¤tMax);
+ ASSERT_TRUE(status.isOk());
+ ASSERT_TRUE(currentMax == 0);
+ // Reset to default
+ status = mService->setMaxNumberOfFrontends(mFrontendInfo.type, defaultMax);
+ ASSERT_TRUE(status.isOk());
+ status = mService->getMaxNumberOfFrontends(mFrontendInfo.type, ¤tMax);
+ ASSERT_TRUE(status.isOk());
+ ASSERT_TRUE(defaultMax == currentMax);
+ }
+}
+
void FrontendTests::scanTest(FrontendConfig frontendConf, FrontendScanType scanType) {
int32_t feId;
getFrontendIdByType(frontendConf.type, feId);
diff --git a/tv/tuner/aidl/vts/functional/FrontendTests.h b/tv/tuner/aidl/vts/functional/FrontendTests.h
index 8f769a0..1745f76 100644
--- a/tv/tuner/aidl/vts/functional/FrontendTests.h
+++ b/tv/tuner/aidl/vts/functional/FrontendTests.h
@@ -100,6 +100,7 @@
void tuneTest(FrontendConfig frontendConf);
void scanTest(FrontendConfig frontend, FrontendScanType type);
void debugInfoTest(FrontendConfig frontendConf);
+ void maxNumberOfFrontendsTest();
void setDvrTests(DvrTests* dvrTests) { mExternalDvrTests = dvrTests; }
void setDemux(std::shared_ptr<IDemux> demux) { getDvrTests()->setDemux(demux); }
diff --git a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
index f489bf7..0566089 100644
--- a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
+++ b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
@@ -899,6 +899,14 @@
mFrontendTests.debugInfoTest(frontendMap[live.frontendId]);
}
+TEST_P(TunerFrontendAidlTest, maxNumberOfFrontends) {
+ description("Test Max Frontend number");
+ if (!live.hasFrontendConnection) {
+ return;
+ }
+ mFrontendTests.maxNumberOfFrontendsTest();
+}
+
TEST_P(TunerBroadcastAidlTest, BroadcastDataFlowVideoFilterTest) {
description("Test Video Filter functionality in Broadcast use case.");
if (!live.hasFrontendConnection) {
diff --git a/wifi/1.5/default/Android.bp b/wifi/1.5/default/Android.bp
new file mode 100644
index 0000000..6333b6e
--- /dev/null
+++ b/wifi/1.5/default/Android.bp
@@ -0,0 +1,105 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+filegroup {
+ name: "android.hardware.wifi@1.0-service_srcs",
+ srcs: ["service.cpp"],
+}
+
+cc_defaults {
+ name: "android.hardware.wifi@1.0-service_default",
+ srcs: [":android.hardware.wifi@1.0-service_srcs"],
+ relative_install_path: "hw",
+ soc_specific: true,
+ shared_libs: [
+ "android.hardware.wifi@1.0",
+ "android.hardware.wifi@1.1",
+ "android.hardware.wifi@1.2",
+ "android.hardware.wifi@1.3",
+ "android.hardware.wifi@1.4",
+ "android.hardware.wifi@1.5",
+ "libbase",
+ "libcutils",
+ "libhidlbase",
+ "liblog",
+ "libnl",
+ "libutils",
+ "libwifi-system-iface",
+ "libxml2",
+ ],
+ cppflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
+}
+
+filegroup {
+ name: "android.hardware.wifi@1.0-service-lib_srcs",
+ srcs: [
+ "hidl_struct_util.cpp",
+ "hidl_sync_util.cpp",
+ "ringbuffer.cpp",
+ "wifi.cpp",
+ "wifi_ap_iface.cpp",
+ "wifi_chip.cpp",
+ "wifi_feature_flags.cpp",
+ "wifi_iface_util.cpp",
+ "wifi_legacy_hal.cpp",
+ "wifi_legacy_hal_factory.cpp",
+ "wifi_legacy_hal_stubs.cpp",
+ "wifi_mode_controller.cpp",
+ "wifi_nan_iface.cpp",
+ "wifi_p2p_iface.cpp",
+ "wifi_rtt_controller.cpp",
+ "wifi_sta_iface.cpp",
+ "wifi_status_util.cpp",
+ ],
+}
+
+cc_defaults {
+ name: "android.hardware.wifi@1.0-service-lib_defaults",
+ srcs: [":android.hardware.wifi@1.0-service-lib_srcs"],
+ relative_install_path: "hw",
+ soc_specific: true,
+ shared_libs: [
+ "android.hardware.wifi@1.0",
+ "android.hardware.wifi@1.1",
+ "android.hardware.wifi@1.2",
+ "android.hardware.wifi@1.3",
+ "android.hardware.wifi@1.4",
+ "android.hardware.wifi@1.5",
+ "libbase",
+ "libcutils",
+ "libhidlbase",
+ "liblog",
+ "libnl",
+ "libutils",
+ "libwifi-system-iface",
+ "libxml2",
+ ],
+ // Generated by building android.hardware.wifi@1.0-service-lib and printing LOCAL_CPPFLAGS.
+ cppflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ "-DWIFI_HIDL_FEATURE_DUAL_INTERFACE",
+ ],
+ export_include_dirs: ["."],
+ include_dirs: ["external/libxml2/include"],
+}
diff --git a/wifi/1.5/default/wifi_feature_flags.cpp b/wifi/1.5/default/wifi_feature_flags.cpp
index 124ba32..70ce55a 100644
--- a/wifi/1.5/default/wifi_feature_flags.cpp
+++ b/wifi/1.5/default/wifi_feature_flags.cpp
@@ -157,43 +157,42 @@
// List of pre-defined interface combinations that can be enabled at runtime via
// setting the property: "kDebugPresetInterfaceCombinationIdxProperty" to the
// corresponding index value.
-static const std::vector<
- std::pair<std::string, std::vector<IWifiChip::ChipMode>>>
- kDebugChipModes{
+static const std::vector<std::pair<std::string, std::vector<IWifiChip::ChipMode>>> kDebugChipModes{
// Legacy combination - No STA/AP concurrencies.
// 0 - (1 AP) or (1 STA + 1 of (P2P or NAN))
{"No STA/AP Concurrency",
{{kMainModeId,
- ChipIfaceCombination::make_vec(
- {{{{AP}, 1}}, {{{STA}, 1}, {{P2P, NAN}, 1}}})}}},
+ ChipIfaceCombination::make_vec({{{{AP}, 1}}, {{{STA}, 1}, {{P2P, NAN}, 1}}})}}},
// STA + AP concurrency
// 1 - (1 STA + 1 AP) or (1 STA + 1 of (P2P or NAN))
{"STA + AP Concurrency",
- {{kMainModeId,
- ChipIfaceCombination::make_vec(
- {{{{STA}, 1}, {{AP}, 1}}, {{{STA}, 1}, {{P2P, NAN}, 1}}})}}},
+ {{kMainModeId, ChipIfaceCombination::make_vec(
+ {{{{STA}, 1}, {{AP}, 1}}, {{{STA}, 1}, {{P2P, NAN}, 1}}})}}},
// STA + STA concurrency
// 2 - (1 STA + 1 AP) or (2 STA + 1 of (P2P or NAN))
{"Dual STA Concurrency",
- {{kMainModeId,
- ChipIfaceCombination::make_vec(
- {{{{STA}, 1}, {{AP}, 1}}, {{{STA}, 2}, {{P2P, NAN}, 1}}})}}},
+ {{kMainModeId, ChipIfaceCombination::make_vec(
+ {{{{STA}, 1}, {{AP}, 1}}, {{{STA}, 2}, {{P2P, NAN}, 1}}})}}},
// AP + AP + STA concurrency
// 3 - (1 STA + 2 AP) or (1 STA + 1 of (P2P or NAN))
{"Dual AP Concurrency",
- {{kMainModeId,
- ChipIfaceCombination::make_vec(
- {{{{STA}, 1}, {{AP}, 2}}, {{{STA}, 1}, {{P2P, NAN}, 1}}})}}},
+ {{kMainModeId, ChipIfaceCombination::make_vec(
+ {{{{STA}, 1}, {{AP}, 2}}, {{{STA}, 1}, {{P2P, NAN}, 1}}})}}},
// STA + STA concurrency and AP + AP + STA concurrency
// 4 - (1 STA + 2 AP) or (2 STA + 1 of (P2P or NAN))
{"Dual STA & Dual AP Concurrency",
+ {{kMainModeId, ChipIfaceCombination::make_vec(
+ {{{{STA}, 1}, {{AP}, 2}}, {{{STA}, 2}, {{P2P, NAN}, 1}}})}}},
+
+ // STA + STA concurrency
+ // 5 - (1 STA + 1 AP (bridged or single) | P2P | NAN), or (2 STA))
+ {"Dual STA or STA plus single other interface",
{{kMainModeId,
- ChipIfaceCombination::make_vec(
- {{{{STA}, 1}, {{AP}, 2}}, {{{STA}, 2}, {{P2P, NAN}, 1}}})}}}};
+ ChipIfaceCombination::make_vec({{{{STA}, 1}, {{P2P, NAN, AP}, 1}}, {{{STA}, 2}}})}}}};
#undef STA
#undef AP
diff --git a/wifi/supplicant/aidl/Android.bp b/wifi/supplicant/aidl/Android.bp
index c97a6f9..d00dd21 100644
--- a/wifi/supplicant/aidl/Android.bp
+++ b/wifi/supplicant/aidl/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
aidl_interface {
name: "android.hardware.wifi.supplicant",
vendor_available: true,