Merge "Add dummy interface combination for debugging"
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..76c238b
--- /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.vehicle@2.0-protocan-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/bluetooth/audio/2.2/IBluetoothAudioProvidersFactory.hal b/bluetooth/audio/2.2/IBluetoothAudioProvidersFactory.hal
index 7fb5b6c..ae9c598 100644
--- a/bluetooth/audio/2.2/IBluetoothAudioProvidersFactory.hal
+++ b/bluetooth/audio/2.2/IBluetoothAudioProvidersFactory.hal
@@ -48,4 +48,26 @@
*/
openProvider_2_2(SessionType sessionType)
generates (Status status, IBluetoothAudioProvider provider);
+
+ /**
+ * Gets a list of audio capabilities for a session type.
+ *
+ * For software encoding, the PCM capabilities are returned.
+ * For hardware encoding, the supported codecs and their capabilities are
+ * returned.
+ *
+ * @param sessionType The session type (e.g.
+ * A2DP_SOFTWARE_ENCODING_DATAPATH).
+ * @return audioCapabilities A list containing all the capabilities
+ * supported by the sesson type. The capabilities is a list of
+ * available options when configuring the codec for the session.
+ * For software encoding it is the PCM data rate.
+ * For hardware encoding it is the list of supported codecs and their
+ * capabilities.
+ * If a provider isn't supported, an empty list should be returned.
+ * Note: Only one entry should exist per codec when using hardware
+ * encoding.
+ */
+ getProviderCapabilities_2_2(SessionType sessionType)
+ generates (vec<AudioCapabilities> audioCapabilities);
};
diff --git a/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp b/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp
index 51ee422..2fe31d5 100644
--- a/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp
+++ b/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.cpp
@@ -221,6 +221,47 @@
return Void();
}
+Return<void> BluetoothAudioProvidersFactory::getProviderCapabilities_2_2(
+ const V2_1::SessionType sessionType,
+ getProviderCapabilities_2_2_cb _hidl_cb) {
+ hidl_vec<V2_2::AudioCapabilities> audio_capabilities =
+ hidl_vec<V2_2::AudioCapabilities>(0);
+ if (sessionType == V2_1::SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
+ std::vector<CodecCapabilities> db_codec_capabilities =
+ android::bluetooth::audio::GetOffloadCodecCapabilities(sessionType);
+ if (db_codec_capabilities.size()) {
+ audio_capabilities.resize(db_codec_capabilities.size());
+ for (int i = 0; i < db_codec_capabilities.size(); ++i) {
+ audio_capabilities[i].codecCapabilities(db_codec_capabilities[i]);
+ }
+ }
+ } else if (sessionType == V2_1::SessionType::
+ LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+ sessionType == V2_1::SessionType::
+ LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+ std::vector<LeAudioCodecCapabilitiesPair> db_codec_capabilities =
+ android::bluetooth::audio::GetLeAudioOffloadCodecCapabilities(
+ sessionType);
+ if (db_codec_capabilities.size()) {
+ audio_capabilities.resize(db_codec_capabilities.size());
+ for (int i = 0; i < db_codec_capabilities.size(); ++i) {
+ audio_capabilities[i].leAudioCapabilities(db_codec_capabilities[i]);
+ }
+ }
+ } else if (sessionType != V2_1::SessionType::UNKNOWN) {
+ std::vector<V2_1::PcmParameters> db_pcm_capabilities =
+ android::bluetooth::audio::GetSoftwarePcmCapabilities_2_1();
+ if (db_pcm_capabilities.size() == 1) {
+ audio_capabilities.resize(1);
+ audio_capabilities[0].pcmCapabilities(db_pcm_capabilities[0]);
+ }
+ }
+ LOG(INFO) << __func__ << " - SessionType=" << toString(sessionType)
+ << " supports " << audio_capabilities.size() << " codecs";
+ _hidl_cb(audio_capabilities);
+ return Void();
+}
+
IBluetoothAudioProvidersFactory* HIDL_FETCH_IBluetoothAudioProvidersFactory(
const char* /* name */) {
return new BluetoothAudioProvidersFactory();
diff --git a/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.h b/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.h
index 658249b..4f549d9 100644
--- a/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.h
+++ b/bluetooth/audio/2.2/default/BluetoothAudioProvidersFactory.h
@@ -53,6 +53,10 @@
const V2_1::SessionType sessionType,
getProviderCapabilities_2_1_cb _hidl_cb) override;
+ Return<void> getProviderCapabilities_2_2(
+ const V2_1::SessionType sessionType,
+ getProviderCapabilities_2_2_cb _hidl_cb) override;
+
private:
static A2dpSoftwareAudioProvider a2dp_software_provider_instance_;
static A2dpOffloadAudioProvider a2dp_offload_provider_instance_;
diff --git a/bluetooth/audio/2.2/types.hal b/bluetooth/audio/2.2/types.hal
index d5f8a3f..8ec3660 100644
--- a/bluetooth/audio/2.2/types.hal
+++ b/bluetooth/audio/2.2/types.hal
@@ -19,6 +19,8 @@
import @2.1::Lc3Parameters;
import @2.1::PcmParameters;
import @2.0::CodecConfiguration;
+import @2.0::CodecCapabilities;
+import @2.1::CodecType;
enum LeAudioMode : uint8_t {
UNKNOWN = 0x00,
@@ -26,6 +28,12 @@
BROADCAST = 0x02,
};
+enum AudioLocation : uint8_t {
+ UNKNOWN = 0,
+ FRONT_LEFT = 1,
+ FRONT_RIGHT = 2,
+};
+
struct UnicastStreamMap {
/* The connection handle used for a unicast or a broadcast group. */
uint16_t streamHandle;
@@ -70,3 +78,37 @@
CodecConfiguration codecConfig;
LeAudioConfiguration leAudioConfig;
};
+
+/** Used to specify the capabilities of the different session types */
+safe_union AudioCapabilities {
+ PcmParameters pcmCapabilities;
+ CodecCapabilities codecCapabilities;
+ LeAudioCodecCapabilitiesPair leAudioCapabilities;
+};
+
+/**
+ * Used to specify th le audio capabilities pair of the Hardware offload encode and decode.
+ */
+struct LeAudioCodecCapabilitiesPair{
+ LeAudioMode mode;
+ LeAudioCodecCapability encodeCapability;
+ LeAudioCodecCapability decodeCapability;
+};
+
+/**
+ * Used to specify the le audio capabilities of the codecs supported by Hardware offload
+ * for encode or decode.
+ */
+struct LeAudioCodecCapability {
+ CodecType codecType;
+ AudioLocation supportedChannel;
+
+ // The number of connected device
+ uint8_t deviceCount;
+
+ // Supported channel count for each device
+ uint8_t channelCountPerDevice;
+
+ // Should use safe union when there is more than one codec
+ Lc3Parameters capabilities;
+};
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.cpp b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.cpp
index 5becdaa..34cfd7e 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.cpp
+++ b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.cpp
@@ -24,9 +24,59 @@
namespace bluetooth {
namespace audio {
+using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
+using ::android::hardware::bluetooth::audio::V2_1::CodecType;
+using ::android::hardware::bluetooth::audio::V2_1::Lc3FrameDuration;
+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 SessionType_2_1 =
::android::hardware::bluetooth::audio::V2_1::SessionType;
+// Stores the list of offload supported capability
+std::vector<LeAudioCodecCapabilitiesPair> kDefaultOffloadLeAudioCapabilities;
+
+static const LeAudioCodecCapability kInvalidLc3Capability = {
+ .codecType = CodecType::UNKNOWN};
+
+// Default Supported Codecs
+// LC3 16_1: sample rate: 16 kHz, frame duration: 7.5 ms, octets per frame: 30
+static const Lc3Parameters kLc3Capability_16_1 = {
+ .samplingFrequency = SampleRate::RATE_16000,
+ .frameDuration = Lc3FrameDuration::DURATION_7500US,
+ .octetsPerFrame = 30};
+
+// Default Supported Codecs
+// LC3 16_2: sample rate: 16 kHz, frame duration: 10 ms, octets per frame: 40
+static const Lc3Parameters kLc3Capability_16_2 = {
+ .samplingFrequency = SampleRate::RATE_16000,
+ .frameDuration = Lc3FrameDuration::DURATION_10000US,
+ .octetsPerFrame = 40};
+
+// Default Supported Codecs
+// LC3 48_4: sample rate: 48 kHz, frame duration: 10 ms, octets per frame: 120
+static const Lc3Parameters kLc3Capability_48_4 = {
+ .samplingFrequency = SampleRate::RATE_48000,
+ .frameDuration = Lc3FrameDuration::DURATION_10000US,
+ .octetsPerFrame = 120};
+
+static const std::vector<Lc3Parameters> supportedLc3CapabilityList = {
+ kLc3Capability_48_4, kLc3Capability_16_2, kLc3Capability_16_1};
+
+static AudioLocation stereoAudio = static_cast<AudioLocation>(
+ AudioLocation::FRONT_LEFT | AudioLocation::FRONT_RIGHT);
+static AudioLocation monoAudio = AudioLocation::UNKNOWN;
+
+// Stores the supported setting of audio location, connected device, and the
+// channel count for each device
+std::vector<std::tuple<AudioLocation, uint8_t, uint8_t>>
+ supportedDeviceSetting = {std::make_tuple(stereoAudio, 2, 1),
+ std::make_tuple(monoAudio, 1, 2),
+ std::make_tuple(monoAudio, 1, 1)};
+
bool IsOffloadLeAudioConfigurationValid(
const ::android::hardware::bluetooth::audio::V2_1::SessionType&
session_type,
@@ -44,6 +94,60 @@
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};
+}
+
+std::vector<LeAudioCodecCapabilitiesPair> 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);
+ }
+
+ if (kDefaultOffloadLeAudioCapabilities.empty()) {
+ for (auto [audioLocation, deviceCnt, channelCount] :
+ supportedDeviceSetting) {
+ for (auto capability : supportedLc3CapabilityList) {
+ LeAudioCodecCapability lc3Capability = composeLc3Capability(
+ audioLocation, deviceCnt, channelCount, capability);
+ LeAudioCodecCapability lc3MonoCapability =
+ composeLc3Capability(monoAudio, 1, 1, capability);
+
+ // Adds the capability for encode only
+ kDefaultOffloadLeAudioCapabilities.push_back(
+ {.mode = LeAudioMode::UNICAST,
+ .encodeCapability = lc3Capability,
+ .decodeCapability = kInvalidLc3Capability});
+
+ // Adds the capability for decode only
+ kDefaultOffloadLeAudioCapabilities.push_back(
+ {.mode = LeAudioMode::UNICAST,
+ .encodeCapability = kInvalidLc3Capability,
+ .decodeCapability = lc3Capability});
+
+ // 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});
+ }
+ }
+ }
+
+ return kDefaultOffloadLeAudioCapabilities;
+}
+
} // namespace audio
} // namespace bluetooth
} // namespace android
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.h
index 8321616..89da6a3 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSupportedCodecsDB_2_2.h
@@ -30,6 +30,11 @@
session_type,
const ::android::hardware::bluetooth::audio::V2_2::LeAudioConfiguration&
le_audio_codec_config);
+
+std::vector<hardware::bluetooth::audio::V2_2::LeAudioCodecCapabilitiesPair>
+GetLeAudioOffloadCodecCapabilities(
+ const ::android::hardware::bluetooth::audio::V2_1::SessionType&
+ session_type);
} // namespace audio
} // namespace bluetooth
} // namespace android
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 01ec9cb..d39850d 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -667,7 +667,7 @@
void waitForBuffersReturned();
- private:
+ private:
bool processCaptureResultLocked(const CaptureResult& results,
hidl_vec<PhysicalCameraMetadata> physicalCameraMetadata);
Return<void> notifyHelper(const hidl_vec<NotifyMsg>& msgs,
@@ -907,7 +907,7 @@
static Status getMandatoryConcurrentStreams(const camera_metadata_t* staticMeta,
std::vector<AvailableStream>* outputStreams);
-
+ static bool supportsPreviewStabilization(const std::string& name, sp<ICameraProvider> provider);
static Status getJpegBufferSize(camera_metadata_t *staticMeta,
uint32_t* outBufSize);
static Status isConstrainedModeAvailable(camera_metadata_t *staticMeta);
@@ -955,6 +955,9 @@
void processCaptureRequestInternal(uint64_t bufferusage, RequestTemplate reqTemplate,
bool useSecureOnlyCameras);
+ void processPreviewStabilizationCaptureRequestInternal(
+ bool previewStabilizationOn,
+ /*inout*/ std::unordered_map<std::string, nsecs_t>& cameraDeviceToTimeLag);
// Used by switchToOffline where a new result queue is created for offline reqs
void updateInflightResultQueue(std::shared_ptr<ResultMetadataQueue> resultQueue);
@@ -1008,7 +1011,11 @@
// Buffers are added by process_capture_result when output buffers
// return from HAL but framework.
- ::android::Vector<StreamBuffer> resultOutputBuffers;
+ struct StreamBufferAndTimestamp {
+ StreamBuffer buffer;
+ nsecs_t timeStamp;
+ };
+ ::android::Vector<StreamBufferAndTimestamp> resultOutputBuffers;
std::unordered_set<std::string> expectedPhysicalResults;
@@ -1423,8 +1430,25 @@
return notify;
}
- request->resultOutputBuffers.appendArray(results.outputBuffers.data(),
- results.outputBuffers.size());
+ for (const auto& buffer : results.outputBuffers) {
+ // wait for the fence timestamp and store it along with the buffer
+ // TODO: Check if we really need the dup here
+ sp<android::Fence> releaseFence = nullptr;
+ if (buffer.releaseFence && (buffer.releaseFence->numFds == 1) &&
+ buffer.releaseFence->data[0] >= 0) {
+ releaseFence = new android::Fence(dup(buffer.releaseFence->data[0]));
+ }
+ InFlightRequest::StreamBufferAndTimestamp streamBufferAndTimestamp;
+ streamBufferAndTimestamp.buffer = buffer;
+ streamBufferAndTimestamp.timeStamp = systemTime();
+ if (releaseFence && releaseFence->isValid()) {
+ releaseFence->wait(/*ms*/ 300);
+ nsecs_t releaseTime = releaseFence->getSignalTime();
+ if (streamBufferAndTimestamp.timeStamp < releaseTime)
+ streamBufferAndTimestamp.timeStamp = releaseTime;
+ }
+ request->resultOutputBuffers.push_back(streamBufferAndTimestamp);
+ }
// If shutter event is received notify the pending threads.
if (request->shutterTimestamp != 0) {
notify = true;
@@ -4926,7 +4950,7 @@
ASSERT_FALSE(inflightReq.errorCodeValid);
ASSERT_NE(inflightReq.resultOutputBuffers.size(), 0u);
- ASSERT_EQ(testStream.id, inflightReq.resultOutputBuffers[0].streamId);
+ ASSERT_EQ(testStream.id, inflightReq.resultOutputBuffers[0].buffer.streamId);
// For camera device 3.8 or newer, shutterReadoutTimestamp must be
// available, and it must be >= shutterTimestamp + exposureTime, and
@@ -4986,7 +5010,197 @@
ASSERT_FALSE(inflightReq.errorCodeValid);
ASSERT_NE(inflightReq.resultOutputBuffers.size(), 0u);
- ASSERT_EQ(testStream.id, inflightReq.resultOutputBuffers[0].streamId);
+ ASSERT_EQ(testStream.id, inflightReq.resultOutputBuffers[0].buffer.streamId);
+ }
+
+ if (useHalBufManager) {
+ verifyBuffersReturned(session, deviceVersion, testStream.id, cb);
+ }
+
+ ret = session->close();
+ ASSERT_TRUE(ret.isOk());
+ }
+}
+
+TEST_P(CameraHidlTest, processCaptureRequestPreviewStabilization) {
+ std::unordered_map<std::string, nsecs_t> cameraDeviceToTimeLag;
+ processPreviewStabilizationCaptureRequestInternal(/*previewStabilizationOn*/ false,
+ cameraDeviceToTimeLag);
+ processPreviewStabilizationCaptureRequestInternal(/*previewStabilizationOn*/ true,
+ cameraDeviceToTimeLag);
+}
+
+void CameraHidlTest::processPreviewStabilizationCaptureRequestInternal(
+ bool previewStabilizationOn,
+ // Used as output when preview stabilization is off, as output when its
+ // on.
+ std::unordered_map<std::string, nsecs_t>& cameraDeviceToTimeLag) {
+ hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+ AvailableStream streamThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
+ static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
+ uint64_t bufferId = 1;
+ uint32_t frameNumber = 1;
+ ::android::hardware::hidl_vec<uint8_t> settings;
+
+ for (const auto& name : cameraDeviceNames) {
+ int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+ if (deviceVersion == CAMERA_DEVICE_API_VERSION_1_0) {
+ continue;
+ } else if (deviceVersion <= 0) {
+ ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+ ADD_FAILURE();
+ return;
+ }
+
+ if (!supportsPreviewStabilization(name, mProvider)) {
+ ALOGI(" %s Camera device %s doesn't support preview stabilization, skipping", __func__,
+ name.c_str());
+ continue;
+ }
+
+ if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_8) {
+ ALOGE("%s: device version < 3.8 must not advertise preview stabilization,"
+ " camera metadata validation will fail",
+ __func__);
+ ADD_FAILURE();
+ }
+
+ V3_2::Stream testStream;
+ HalStreamConfiguration halStreamConfig;
+ sp<ICameraDeviceSession> session;
+ sp<DeviceCb> cb;
+ bool supportsPartialResults = false;
+ bool useHalBufManager = false;
+ uint32_t partialResultCount = 0;
+ configureSingleStream(name, deviceVersion, mProvider, &streamThreshold,
+ GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, RequestTemplate::PREVIEW,
+ &session /*out*/, &testStream /*out*/, &halStreamConfig /*out*/,
+ &supportsPartialResults /*out*/, &partialResultCount /*out*/,
+ &useHalBufManager /*out*/, &cb /*out*/);
+
+ std::shared_ptr<ResultMetadataQueue> resultQueue;
+ auto resultQueueRet =
+ session->getCaptureResultMetadataQueue([&resultQueue](const auto& descriptor) {
+ resultQueue = std::make_shared<ResultMetadataQueue>(descriptor);
+ if (!resultQueue->isValid() || resultQueue->availableToWrite() <= 0) {
+ ALOGE("%s: HAL returns empty result metadata fmq,"
+ " not use it",
+ __func__);
+ resultQueue = nullptr;
+ // Don't use the queue onwards.
+ }
+ });
+ ASSERT_TRUE(resultQueueRet.isOk());
+
+ InFlightRequest inflightReq = {1, false, supportsPartialResults, partialResultCount,
+ resultQueue};
+
+ Return<void> ret;
+ android::hardware::camera::common::V1_0::helper::CameraMetadata defaultSettings;
+ ret = session->constructDefaultRequestSettings(
+ RequestTemplate::PREVIEW, [&](auto status, const auto& req) {
+ ASSERT_EQ(Status::OK, status);
+ const camera_metadata_t* metadata =
+ reinterpret_cast<const camera_metadata_t*>(req.data());
+ defaultSettings = metadata;
+ settings = req;
+ });
+ ASSERT_TRUE(ret.isOk());
+ android::status_t metadataRet = ::android::OK;
+ uint8_t videoStabilizationMode = ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF;
+ if (previewStabilizationOn) {
+ videoStabilizationMode = ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION;
+ metadataRet = defaultSettings.update(ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
+ &videoStabilizationMode, 1);
+ } else {
+ metadataRet = defaultSettings.update(ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
+ &videoStabilizationMode, 1);
+ }
+ ASSERT_EQ(metadataRet, ::android::OK);
+ hidl_handle buffer_handle;
+ StreamBuffer outputBuffer;
+ if (useHalBufManager) {
+ outputBuffer = {halStreamConfig.streams[0].id,
+ /*bufferId*/ 0,
+ buffer_handle,
+ BufferStatus::OK,
+ nullptr,
+ nullptr};
+ } else {
+ allocateGraphicBuffer(
+ testStream.width, testStream.height,
+ /* We don't look at halStreamConfig.streams[0].consumerUsage
+ * since that is 0 for output streams
+ */
+ android_convertGralloc1To0Usage(halStreamConfig.streams[0].producerUsage,
+ GRALLOC1_CONSUMER_USAGE_HWCOMPOSER),
+ halStreamConfig.streams[0].overrideFormat, &buffer_handle);
+ outputBuffer = {halStreamConfig.streams[0].id,
+ bufferId,
+ buffer_handle,
+ BufferStatus::OK,
+ nullptr,
+ nullptr};
+ }
+ ::android::hardware::hidl_vec<StreamBuffer> outputBuffers = {outputBuffer};
+ StreamBuffer emptyInputBuffer = {-1, 0, nullptr, BufferStatus::ERROR, nullptr, nullptr};
+ CaptureRequest request = {frameNumber, 0 /* fmqSettingsSize */, settings, emptyInputBuffer,
+ outputBuffers};
+
+ {
+ std::unique_lock<std::mutex> l(mLock);
+ mInflightMap.clear();
+ mInflightMap.add(frameNumber, &inflightReq);
+ }
+
+ Status status = Status::INTERNAL_ERROR;
+ uint32_t numRequestProcessed = 0;
+ hidl_vec<BufferCache> cachesToRemove;
+ Return<void> returnStatus = session->processCaptureRequest(
+ {request}, cachesToRemove, [&status, &numRequestProcessed](auto s, uint32_t n) {
+ status = s;
+ numRequestProcessed = n;
+ });
+ ASSERT_TRUE(returnStatus.isOk());
+ ASSERT_EQ(Status::OK, status);
+ ASSERT_EQ(numRequestProcessed, 1u);
+
+ {
+ std::unique_lock<std::mutex> l(mLock);
+ while (!inflightReq.errorCodeValid &&
+ ((0 < inflightReq.numBuffersLeft) || (!inflightReq.haveResultMetadata))) {
+ auto timeout = std::chrono::system_clock::now() +
+ std::chrono::seconds(kStreamBufferTimeoutSec);
+ ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
+ }
+
+ ASSERT_FALSE(inflightReq.errorCodeValid);
+ ASSERT_NE(inflightReq.resultOutputBuffers.size(), 0u);
+ ASSERT_EQ(testStream.id, inflightReq.resultOutputBuffers[0].buffer.streamId);
+ ASSERT_TRUE(inflightReq.shutterReadoutTimestampValid);
+ nsecs_t readoutTimestamp = inflightReq.shutterReadoutTimestamp;
+
+ if (previewStabilizationOn) {
+ // Here we collect the time difference between the buffer ready
+ // timestamp - notify readout timestamp.
+ // timeLag = buffer ready timestamp - notify readout timestamp.
+ // timeLag(previewStabilization) must be <=
+ // timeLag(stabilization off) + 1 frame duration.
+ auto it = cameraDeviceToTimeLag.find(name.c_str());
+ camera_metadata_entry e;
+ e = inflightReq.collectedResult.find(ANDROID_SENSOR_FRAME_DURATION);
+ ASSERT_TRUE(e.count > 0);
+ nsecs_t frameDuration = e.data.i64[0];
+ ASSERT_TRUE(it != cameraDeviceToTimeLag.end());
+
+ nsecs_t previewStabOnLagTime =
+ inflightReq.resultOutputBuffers[0].timeStamp - readoutTimestamp;
+ ASSERT_TRUE(previewStabOnLagTime <= (it->second + frameDuration));
+ } else {
+ // Fill in the buffer ready timestamp - notify timestamp;
+ cameraDeviceToTimeLag[std::string(name.c_str())] =
+ inflightReq.resultOutputBuffers[0].timeStamp - readoutTimestamp;
+ }
}
if (useHalBufManager) {
@@ -5567,7 +5781,7 @@
ASSERT_FALSE(inflightReqs[i].errorCodeValid);
ASSERT_NE(inflightReqs[i].resultOutputBuffers.size(), 0u);
- ASSERT_EQ(previewStream.id, inflightReqs[i].resultOutputBuffers[0].streamId);
+ ASSERT_EQ(previewStream.id, inflightReqs[i].resultOutputBuffers[0].buffer.streamId);
ASSERT_FALSE(inflightReqs[i].collectedResult.isEmpty());
ASSERT_TRUE(inflightReqs[i].collectedResult.exists(ANDROID_SENSOR_SENSITIVITY));
camera_metadata_entry_t isoResult = inflightReqs[i].collectedResult.find(
@@ -5851,7 +6065,7 @@
ASSERT_FALSE(inflightReqs[i].errorCodeValid);
ASSERT_NE(inflightReqs[i].resultOutputBuffers.size(), 0u);
- ASSERT_EQ(stream.id, inflightReqs[i].resultOutputBuffers[0].streamId);
+ ASSERT_EQ(stream.id, inflightReqs[i].resultOutputBuffers[0].buffer.streamId);
ASSERT_FALSE(inflightReqs[i].collectedResult.isEmpty());
}
@@ -6047,7 +6261,7 @@
if (!inflightReq.errorCodeValid) {
ASSERT_NE(inflightReq.resultOutputBuffers.size(), 0u);
- ASSERT_EQ(previewStream.id, inflightReq.resultOutputBuffers[0].streamId);
+ ASSERT_EQ(previewStream.id, inflightReq.resultOutputBuffers[0].buffer.streamId);
} else {
switch (inflightReq.errorCode) {
case ErrorCode::ERROR_REQUEST:
@@ -7685,6 +7899,47 @@
previewStream, halStreamConfig, supportsPartialResults,
partialResultCount, useHalBufManager, outCb, streamConfigCounter);
}
+
+bool CameraHidlTest::supportsPreviewStabilization(const std::string& name,
+ sp<ICameraProvider> provider) {
+ Return<void> ret;
+ sp<ICameraDevice> device3_x = nullptr;
+ ret = provider->getCameraDeviceInterface_V3_x(name, [&](auto status, const auto& device) {
+ ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status);
+ ASSERT_EQ(Status::OK, status);
+ ASSERT_NE(device, nullptr);
+ device3_x = device;
+ });
+ if (!(ret.isOk())) {
+ ADD_FAILURE() << "Failed to get camera device interface for " << name;
+ }
+
+ camera_metadata_t* staticMeta = nullptr;
+ ret = device3_x->getCameraCharacteristics([&](Status s, CameraMetadata metadata) {
+ ASSERT_EQ(Status::OK, s);
+ staticMeta =
+ clone_camera_metadata(reinterpret_cast<const camera_metadata_t*>(metadata.data()));
+ });
+ if (!(ret.isOk())) {
+ ADD_FAILURE() << "Failed to get camera characteristics for " << name;
+ }
+ // Go through the characteristics and see if video stabilization modes have
+ // preview stabilization
+ camera_metadata_ro_entry entry;
+
+ int retcode = find_camera_metadata_ro_entry(
+ staticMeta, ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES, &entry);
+ if ((0 == retcode) && (entry.count > 0)) {
+ for (auto i = 0; i < entry.count; i++) {
+ if (entry.data.u8[i] ==
+ ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
// Open a device session and configure a preview stream.
void CameraHidlTest::configureSingleStream(
const std::string& name, int32_t deviceVersion, sp<ICameraProvider> provider,
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index c875e8c..c480c13 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -252,6 +252,14 @@
<instance>default</instance>
</interface>
</hal>
+ <hal format="aidl" optional="true">
+ <name>android.hardware.gnss.visibility_control</name>
+ <version>1</version>
+ <interface>
+ <name>IGnssVisibilityControl</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
<hal format="hidl" optional="false">
<name>android.hardware.graphics.allocator</name>
<!-- New, non-Go devices should use 4.0, tested in vts_treble_vintf_vendor_test -->
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/Android.bp b/gnss/aidl/Android.bp
index b197eae..12dd0ac 100644
--- a/gnss/aidl/Android.bp
+++ b/gnss/aidl/Android.bp
@@ -24,9 +24,27 @@
}
aidl_interface {
+ name: "android.hardware.gnss.visibility_control",
+ vendor_available: true,
+ srcs: ["android/hardware/gnss/visibility_control/*.aidl"],
+ stability: "vintf",
+ backend: {
+ java: {
+ platform_apis: true,
+ },
+ ndk: {
+ vndk: {
+ enabled: true,
+ },
+ },
+ },
+}
+
+aidl_interface {
name: "android.hardware.gnss",
vendor_available: true,
srcs: ["android/hardware/gnss/*.aidl"],
+ imports: ["android.hardware.gnss.visibility_control"],
stability: "vintf",
backend: {
java: {
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/HandleIndex.aidl b/gnss/aidl/aidl_api/android.hardware.gnss.visibility_control/current/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl
similarity index 80%
rename from graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/HandleIndex.aidl
rename to gnss/aidl/aidl_api/android.hardware.gnss.visibility_control/current/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl
index b87870d..7ef08d2 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/HandleIndex.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss.visibility_control/current/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl
@@ -1,11 +1,11 @@
-/**
- * Copyright (c) 2021, The Android Open Source Project
+/*
+ * 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
+ * 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,
@@ -31,9 +31,9 @@
// with such a backward incompatible change, it has a high risk of breaking
// later when a module using the interface is updated, e.g., Mainline modules.
-package android.hardware.graphics.composer3;
-@Backing(type="int") @VintfStability
-enum HandleIndex {
- EMPTY = -1,
- CACHED = -2,
+package android.hardware.gnss.visibility_control;
+@VintfStability
+interface IGnssVisibilityControl {
+ void enableNfwLocationAccess(in String[] proxyApps);
+ void setCallback(in android.hardware.gnss.visibility_control.IGnssVisibilityControlCallback callback);
}
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss.visibility_control/current/android/hardware/gnss/visibility_control/IGnssVisibilityControlCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss.visibility_control/current/android/hardware/gnss/visibility_control/IGnssVisibilityControlCallback.aidl
new file mode 100644
index 0000000..37e1886
--- /dev/null
+++ b/gnss/aidl/aidl_api/android.hardware.gnss.visibility_control/current/android/hardware/gnss/visibility_control/IGnssVisibilityControlCallback.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.gnss.visibility_control;
+@VintfStability
+interface IGnssVisibilityControlCallback {
+ void nfwNotifyCb(in android.hardware.gnss.visibility_control.IGnssVisibilityControlCallback.NfwNotification notification);
+ boolean isInEmergencySession();
+ @Backing(type="int") @VintfStability
+ enum NfwProtocolStack {
+ CTRL_PLANE = 0,
+ SUPL = 1,
+ IMS = 10,
+ SIM = 11,
+ OTHER_PROTOCOL_STACK = 100,
+ }
+ @Backing(type="int") @VintfStability
+ enum NfwRequestor {
+ CARRIER = 0,
+ OEM = 10,
+ MODEM_CHIPSET_VENDOR = 11,
+ GNSS_CHIPSET_VENDOR = 12,
+ OTHER_CHIPSET_VENDOR = 13,
+ AUTOMOBILE_CLIENT = 20,
+ OTHER_REQUESTOR = 100,
+ }
+ @Backing(type="int") @VintfStability
+ enum NfwResponseType {
+ REJECTED = 0,
+ ACCEPTED_NO_LOCATION_PROVIDED = 1,
+ ACCEPTED_LOCATION_PROVIDED = 2,
+ }
+ @VintfStability
+ parcelable NfwNotification {
+ String proxyAppPackageName;
+ android.hardware.gnss.visibility_control.IGnssVisibilityControlCallback.NfwProtocolStack protocolStack;
+ String otherProtocolStackName;
+ android.hardware.gnss.visibility_control.IGnssVisibilityControlCallback.NfwRequestor requestor;
+ String requestorId;
+ android.hardware.gnss.visibility_control.IGnssVisibilityControlCallback.NfwResponseType responseType;
+ boolean inEmergencyMode;
+ boolean isCachedLocation;
+ }
+}
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 9df7fe5..3477380 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
@@ -45,6 +45,7 @@
@nullable android.hardware.gnss.IGnssNavigationMessageInterface getExtensionGnssNavigationMessage();
android.hardware.gnss.IAGnss getExtensionAGnss();
android.hardware.gnss.IGnssDebug getExtensionGnssDebug();
+ android.hardware.gnss.visibility_control.IGnssVisibilityControl getExtensionGnssVisibilityControl();
const int ERROR_INVALID_ARGUMENT = 1;
const int ERROR_ALREADY_INIT = 2;
const int ERROR_GENERIC = 3;
diff --git a/gnss/aidl/android/hardware/gnss/IGnss.aidl b/gnss/aidl/android/hardware/gnss/IGnss.aidl
index 2751521..1351f59 100644
--- a/gnss/aidl/android/hardware/gnss/IGnss.aidl
+++ b/gnss/aidl/android/hardware/gnss/IGnss.aidl
@@ -26,6 +26,7 @@
import android.hardware.gnss.IGnssNavigationMessageInterface;
import android.hardware.gnss.IGnssPowerIndication;
import android.hardware.gnss.IGnssPsds;
+import android.hardware.gnss.visibility_control.IGnssVisibilityControl;
/**
* Represents the standard GNSS (Global Navigation Satellite System) interface.
@@ -144,4 +145,11 @@
* @return Handle to the IGnssDebug interface.
*/
IGnssDebug getExtensionGnssDebug();
+
+ /**
+ * This method returns the IGnssVisibilityControl.
+ *
+ * @return Handle to the IGnssVisibilityControl.
+ */
+ IGnssVisibilityControl getExtensionGnssVisibilityControl();
}
diff --git a/gnss/aidl/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl b/gnss/aidl/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl
new file mode 100644
index 0000000..93c3f2c
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl
@@ -0,0 +1,82 @@
+/*
+ * 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.gnss.visibility_control;
+
+import android.hardware.gnss.visibility_control.IGnssVisibilityControlCallback;
+
+/**
+ * Represents the GNSS location reporting permissions and notification interface.
+ *
+ * This interface is used to tell the GNSS HAL implementation whether the framework user has
+ * granted permission to the GNSS HAL implementation to provide GNSS location information for
+ * non-framework (NFW), non-user initiated emergency use cases, and to notify the framework user
+ * of these GNSS location information deliveries.
+ *
+ * For user initiated emergency cases (and for the configured extended emergency session duration),
+ * the GNSS HAL implementation must serve the emergency location supporting network initiated
+ * location requests immediately irrespective of this permission settings.
+ *
+ * There is no separate need for the GNSS HAL implementation to monitor the global device location
+ * on/off setting. Permission to use GNSS for non-framework use cases is expressly controlled
+ * by the method enableNfwLocationAccess(). The framework monitors the location permission settings
+ * of the configured proxy applications(s), and device location settings, and calls the method
+ * enableNfwLocationAccess() whenever the user control proxy applications have, or do not have,
+ * location permission. The proxy applications are used to provide user visibility and control of
+ * location access by the non-framework on/off device entities they are representing.
+ *
+ * For device user visibility, the GNSS HAL implementation must call the method
+ * IGnssVisibilityControlCallback.nfwNotifyCb() whenever location request is rejected or
+ * location information is provided to non-framework entities (on or off device). This includes
+ * the network initiated location requests for user-initiated emergency use cases as well.
+ *
+ * The HAL implementations that support this interface must not report GNSS location, measurement,
+ * status, or other information that can be used to derive user location to any entity when not
+ * expressly authorized by this HAL. This includes all endpoints for location information
+ * off the device, including carriers, vendors, OEM and others directly or indirectly.
+ */
+@VintfStability
+interface IGnssVisibilityControl {
+ /**
+ * Enables/disables non-framework entity location access permission in the GNSS HAL.
+ *
+ * The framework will call this method to update GNSS HAL implementation every time the
+ * framework user, through the given proxy application(s) and/or device location settings,
+ * explicitly grants/revokes the location access permission for non-framework, non-user
+ * initiated emergency use cases.
+ *
+ * Whenever the user location information is delivered to non-framework entities, the HAL
+ * implementation must call the method IGnssVisibilityControlCallback.nfwNotifyCb() to notify
+ * the framework for user visibility.
+ *
+ * @param proxyApps Full list of package names of proxy Android applications representing
+ * the non-framework location access entities (on/off the device) for which the framework
+ * user has granted non-framework location access permission. The GNSS HAL implementation
+ * must provide location information only to non-framework entities represented by these
+ * proxy applications.
+ *
+ * The package name of the proxy Android application follows the standard Java language
+ * package naming format. For example, com.example.myapp.
+ */
+ void enableNfwLocationAccess(in String[] proxyApps);
+
+ /**
+ * Registers the callback for HAL implementation to use.
+ *
+ * @param callback Handle to IGnssVisibilityControlCallback interface.
+ */
+ void setCallback(in IGnssVisibilityControlCallback callback);
+}
diff --git a/gnss/aidl/android/hardware/gnss/visibility_control/IGnssVisibilityControlCallback.aidl b/gnss/aidl/android/hardware/gnss/visibility_control/IGnssVisibilityControlCallback.aidl
new file mode 100644
index 0000000..051fbe6
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/visibility_control/IGnssVisibilityControlCallback.aidl
@@ -0,0 +1,176 @@
+/*
+ * 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.gnss.visibility_control;
+
+/**
+ * GNSS location reporting permissions and notification callback interface.
+ */
+@VintfStability
+interface IGnssVisibilityControlCallback {
+ /**
+ * Protocol stack that is requesting the non-framework location information.
+ */
+ @VintfStability
+ @Backing(type="int")
+ enum NfwProtocolStack {
+ /** Cellular control plane requests */
+ CTRL_PLANE = 0,
+
+ /** All types of SUPL requests */
+ SUPL = 1,
+
+ /** All types of requests from IMS */
+ IMS = 10,
+
+ /** All types of requests from SIM */
+ SIM = 11,
+
+ /** Requests from other protocol stacks */
+ OTHER_PROTOCOL_STACK = 100
+ }
+
+ /**
+ * Entity that is requesting/receiving the location information.
+ */
+ @VintfStability
+ @Backing(type="int")
+ enum NfwRequestor {
+ /** Wireless service provider */
+ CARRIER = 0,
+
+ /** Device manufacturer */
+ OEM = 10,
+
+ /** Modem chipset vendor */
+ MODEM_CHIPSET_VENDOR = 11,
+
+ /** GNSS chipset vendor */
+ GNSS_CHIPSET_VENDOR = 12,
+
+ /** Other chipset vendor */
+ OTHER_CHIPSET_VENDOR = 13,
+
+ /** Automobile client */
+ AUTOMOBILE_CLIENT = 20,
+
+ /** Other sources */
+ OTHER_REQUESTOR = 100
+ }
+
+ /**
+ * GNSS response type for non-framework location requests.
+ */
+ @VintfStability
+ @Backing(type="int")
+ enum NfwResponseType {
+ /** Request rejected because framework has not given permission for this use case */
+ REJECTED = 0,
+
+ /** Request accepted but could not provide location because of a failure */
+ ACCEPTED_NO_LOCATION_PROVIDED = 1,
+
+ /** Request accepted and location provided */
+ ACCEPTED_LOCATION_PROVIDED = 2,
+ }
+
+ /**
+ * Represents a non-framework location information request/response notification.
+ */
+ @VintfStability
+ parcelable NfwNotification {
+ /**
+ * Package name of the Android proxy application representing the non-framework
+ * entity that requested location. Set to empty string if unknown.
+ *
+ * For user-initiated emergency use cases, this field must be set to empty string
+ * and the inEmergencyMode field must be set to true.
+ */
+ String proxyAppPackageName;
+
+ /** Protocol stack that initiated the non-framework location request. */
+ NfwProtocolStack protocolStack;
+
+ /**
+ * Name of the protocol stack if protocolStack field is set to OTHER_PROTOCOL_STACK.
+ * Otherwise, set to empty string.
+ *
+ * This field is opaque to the framework and used for logging purposes.
+ */
+ String otherProtocolStackName;
+
+ /** Source initiating/receiving the location information. */
+ NfwRequestor requestor;
+
+ /**
+ * Identity of the endpoint receiving the location information. For example, carrier
+ * name, OEM name, SUPL SLP/E-SLP FQDN, chipset vendor name, etc.
+ *
+ * This field is opaque to the framework and used for logging purposes.
+ */
+ String requestorId;
+
+ /** Indicates whether location information was provided for this request. */
+ NfwResponseType responseType;
+
+ /** Is the device in user initiated emergency session. */
+ boolean inEmergencyMode;
+
+ /** Is cached location provided */
+ boolean isCachedLocation;
+ }
+
+ /**
+ * Callback to report a non-framework delivered location.
+ *
+ * The GNSS HAL implementation must call this method to notify the framework whenever
+ * a non-framework location request is made to the GNSS HAL.
+ *
+ * Non-framework entities like low power sensor hubs that request location from GNSS and
+ * only pass location information through Android framework controls are exempt from this
+ * power-spending reporting. However, low power sensor hubs or other chipsets which may send
+ * the location information to anywhere other than Android framework (which provides user
+ * visibility and control), must report location information use through this API whenever
+ * location information (or events driven by that location such as "home" location detection)
+ * leaves the domain of that low power chipset.
+ *
+ * To avoid overly spamming the framework, high speed location reporting of the exact same
+ * type may be throttled to report location at a lower rate than the actual report rate, as
+ * long as the location is reported with a latency of no more than the larger of 5 seconds,
+ * or the next the Android processor awake time. For example, if an Automotive client is
+ * getting location information from the GNSS location system at 20Hz, this method may be
+ * called at 1Hz. As another example, if a low power processor is getting location from the
+ * GNSS chipset, and the Android processor is asleep, the notification to the Android HAL may
+ * be delayed until the next wake of the Android processor.
+ *
+ * @param notification Non-framework delivered location request/response description.
+ */
+ void nfwNotifyCb(in NfwNotification notification);
+
+ /**
+ * Tells if the device is currently in an emergency session.
+ *
+ * Emergency session is defined as the device being actively in a user initiated emergency
+ * call or in post emergency call extension time period.
+ *
+ * If the GNSS HAL implementation cannot determine if the device is in emergency session
+ * mode, it must call this method to confirm that the device is in emergency session before
+ * serving network initiated emergency SUPL and Control Plane location requests.
+ *
+ * @return success True if the framework determines that the device is in emergency session.
+ */
+ boolean isInEmergencySession();
+}
diff --git a/gnss/aidl/default/Android.bp b/gnss/aidl/default/Android.bp
index 24569ae..29c26d1 100644
--- a/gnss/aidl/default/Android.bp
+++ b/gnss/aidl/default/Android.bp
@@ -52,6 +52,7 @@
"android.hardware.gnss.measurement_corrections@1.1",
"android.hardware.gnss.measurement_corrections@1.0",
"android.hardware.gnss.visibility_control@1.0",
+ "android.hardware.gnss.visibility_control-V1-ndk",
"android.hardware.gnss-V2-ndk",
],
srcs: [
@@ -66,6 +67,7 @@
"GnssPsds.cpp",
"GnssConfiguration.cpp",
"GnssMeasurementInterface.cpp",
+ "GnssVisibilityControl.cpp",
"service.cpp",
],
static_libs: [
diff --git a/gnss/aidl/default/Gnss.cpp b/gnss/aidl/default/Gnss.cpp
index 45d6b1d..afb7b95 100644
--- a/gnss/aidl/default/Gnss.cpp
+++ b/gnss/aidl/default/Gnss.cpp
@@ -26,6 +26,7 @@
#include "GnssMeasurementInterface.h"
#include "GnssNavigationMessageInterface.h"
#include "GnssPsds.h"
+#include "GnssVisibilityControl.h"
namespace aidl::android::hardware::gnss {
@@ -128,4 +129,12 @@
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus Gnss::getExtensionGnssVisibilityControl(
+ std::shared_ptr<visibility_control::IGnssVisibilityControl>* iGnssVisibilityControl) {
+ ALOGD("Gnss::getExtensionGnssVisibilityControl");
+
+ *iGnssVisibilityControl = SharedRefBase::make<visibility_control::GnssVisibilityControl>();
+ return ndk::ScopedAStatus::ok();
+}
+
} // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/default/Gnss.h b/gnss/aidl/default/Gnss.h
index f59607f..67fef94 100644
--- a/gnss/aidl/default/Gnss.h
+++ b/gnss/aidl/default/Gnss.h
@@ -24,6 +24,7 @@
#include <aidl/android/hardware/gnss/BnGnssMeasurementInterface.h>
#include <aidl/android/hardware/gnss/BnGnssPowerIndication.h>
#include <aidl/android/hardware/gnss/BnGnssPsds.h>
+#include <aidl/android/hardware/gnss/visibility_control/BnGnssVisibilityControl.h>
#include "GnssConfiguration.h"
#include "GnssPowerIndication.h"
@@ -48,6 +49,9 @@
std::shared_ptr<IGnssNavigationMessageInterface>* iGnssNavigationMessage) override;
ndk::ScopedAStatus getExtensionAGnss(std::shared_ptr<IAGnss>* iAGnss) override;
ndk::ScopedAStatus getExtensionGnssDebug(std::shared_ptr<IGnssDebug>* iGnssDebug) override;
+ ndk::ScopedAStatus getExtensionGnssVisibilityControl(
+ std::shared_ptr<android::hardware::gnss::visibility_control::IGnssVisibilityControl>*
+ iGnssVisibilityControl) override;
std::shared_ptr<GnssConfiguration> mGnssConfiguration;
std::shared_ptr<GnssPowerIndication> mGnssPowerIndication;
diff --git a/gnss/aidl/default/GnssVisibilityControl.cpp b/gnss/aidl/default/GnssVisibilityControl.cpp
new file mode 100644
index 0000000..208d73c
--- /dev/null
+++ b/gnss/aidl/default/GnssVisibilityControl.cpp
@@ -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.
+ */
+
+#define LOG_TAG "GnssVisibilityControl"
+
+#include "GnssVisibilityControl.h"
+#include <log/log.h>
+
+namespace aidl::android::hardware::gnss::visibility_control {
+
+std::shared_ptr<IGnssVisibilityControlCallback> GnssVisibilityControl::sCallback = nullptr;
+
+ndk::ScopedAStatus GnssVisibilityControl::enableNfwLocationAccess(
+ const std::vector<std::string>& proxyApps) {
+ std::string os;
+ bool first = true;
+ for (const auto& proxyApp : proxyApps) {
+ if (first) {
+ first = false;
+ } else {
+ os += " ";
+ }
+ os += proxyApp;
+ }
+
+ ALOGD("GnssVisibilityControl::enableNfwLocationAccess proxyApps: %s", os.c_str());
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus GnssVisibilityControl::setCallback(
+ const std::shared_ptr<IGnssVisibilityControlCallback>& callback) {
+ ALOGD("GnssVisibilityControl::setCallback");
+ std::unique_lock<std::mutex> lock(mMutex);
+ sCallback = callback;
+ return ndk::ScopedAStatus::ok();
+}
+
+} // namespace aidl::android::hardware::gnss::visibility_control
diff --git a/gnss/aidl/default/GnssVisibilityControl.h b/gnss/aidl/default/GnssVisibilityControl.h
new file mode 100644
index 0000000..5b36442
--- /dev/null
+++ b/gnss/aidl/default/GnssVisibilityControl.h
@@ -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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/gnss/visibility_control/BnGnssVisibilityControl.h>
+
+namespace aidl::android::hardware::gnss::visibility_control {
+
+struct GnssVisibilityControl : public BnGnssVisibilityControl {
+ public:
+ ndk::ScopedAStatus enableNfwLocationAccess(const std::vector<std::string>& hostname) override;
+ ndk::ScopedAStatus setCallback(
+ const std::shared_ptr<IGnssVisibilityControlCallback>& callback) override;
+
+ private:
+ // Synchronization lock for sCallback
+ mutable std::mutex mMutex;
+ // Guarded by mMutex
+ static std::shared_ptr<IGnssVisibilityControlCallback> sCallback;
+};
+
+} // namespace aidl::android::hardware::gnss::visibility_control
diff --git a/gnss/aidl/vts/Android.bp b/gnss/aidl/vts/Android.bp
index 041d579..d532fad 100644
--- a/gnss/aidl/vts/Android.bp
+++ b/gnss/aidl/vts/Android.bp
@@ -37,6 +37,7 @@
"GnssMeasurementCallbackAidl.cpp",
"GnssNavigationMessageCallback.cpp",
"GnssPowerIndicationCallback.cpp",
+ "GnssVisibilityControlCallback.cpp",
"VtsHalGnssTargetTest.cpp",
],
shared_libs: [
@@ -49,6 +50,7 @@
static_libs: [
"android.hardware.gnss-V2-cpp",
"android.hardware.gnss@common-vts-lib",
+ "android.hardware.gnss.visibility_control-V1-cpp",
],
test_suites: [
"general-tests",
diff --git a/gnss/aidl/vts/GnssVisibilityControlCallback.cpp b/gnss/aidl/vts/GnssVisibilityControlCallback.cpp
new file mode 100644
index 0000000..aa27af1
--- /dev/null
+++ b/gnss/aidl/vts/GnssVisibilityControlCallback.cpp
@@ -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.
+ */
+
+#include "GnssVisibilityControlCallback.h"
+#include <log/log.h>
+
+android::binder::Status GnssVisibilityControlCallback::nfwNotifyCb(const NfwNotification&) {
+ // To implement
+ return android::binder::Status::ok();
+}
+
+android::binder::Status GnssVisibilityControlCallback::isInEmergencySession(bool*) {
+ // To implement
+ return android::binder::Status::ok();
+}
diff --git a/gnss/aidl/vts/GnssVisibilityControlCallback.h b/gnss/aidl/vts/GnssVisibilityControlCallback.h
new file mode 100644
index 0000000..fbacde7
--- /dev/null
+++ b/gnss/aidl/vts/GnssVisibilityControlCallback.h
@@ -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.
+ */
+
+#pragma once
+
+#include <android/hardware/gnss/visibility_control/BnGnssVisibilityControlCallback.h>
+
+class GnssVisibilityControlCallback
+ : public android::hardware::gnss::visibility_control::BnGnssVisibilityControlCallback {
+ public:
+ GnssVisibilityControlCallback(){};
+ ~GnssVisibilityControlCallback(){};
+ android::binder::Status nfwNotifyCb(
+ const android::hardware::gnss::visibility_control::IGnssVisibilityControlCallback::
+ NfwNotification& notification) override;
+ android::binder::Status isInEmergencySession(bool* _aidl_return) override;
+};
diff --git a/gnss/aidl/vts/gnss_hal_test_cases.cpp b/gnss/aidl/vts/gnss_hal_test_cases.cpp
index 36be631..90b643c 100644
--- a/gnss/aidl/vts/gnss_hal_test_cases.cpp
+++ b/gnss/aidl/vts/gnss_hal_test_cases.cpp
@@ -24,6 +24,7 @@
#include <android/hardware/gnss/IGnssMeasurementInterface.h>
#include <android/hardware/gnss/IGnssPowerIndication.h>
#include <android/hardware/gnss/IGnssPsds.h>
+#include <android/hardware/gnss/visibility_control/IGnssVisibilityControl.h>
#include <cutils/properties.h>
#include "AGnssCallbackAidl.h"
#include "GnssBatchingCallback.h"
@@ -31,6 +32,7 @@
#include "GnssMeasurementCallbackAidl.h"
#include "GnssNavigationMessageCallback.h"
#include "GnssPowerIndicationCallback.h"
+#include "GnssVisibilityControlCallback.h"
#include "gnss_hal_test.h"
using android::sp;
@@ -55,6 +57,7 @@
using android::hardware::gnss::IGnssPsds;
using android::hardware::gnss::PsdsType;
using android::hardware::gnss::SatellitePvt;
+using android::hardware::gnss::visibility_control::IGnssVisibilityControl;
using GnssConstellationTypeAidl = android::hardware::gnss::GnssConstellationType;
@@ -876,3 +879,27 @@
data.time.frequencyUncertaintyNsPerSec <= 2.0e5); // 200 ppm
}
}
+
+/*
+ * TestAGnssExtension:
+ * TestGnssVisibilityControlExtension:
+ * 1. Gets the IGnssVisibilityControl extension.
+ * 2. Sets GnssVisibilityControlCallback
+ * 3. Sets proxy apps
+ */
+TEST_P(GnssHalTest, TestGnssVisibilityControlExtension) {
+ if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+ return;
+ }
+ sp<IGnssVisibilityControl> iGnssVisibilityControl;
+ auto status = aidl_gnss_hal_->getExtensionGnssVisibilityControl(&iGnssVisibilityControl);
+ ASSERT_TRUE(status.isOk());
+ ASSERT_TRUE(iGnssVisibilityControl != nullptr);
+ auto gnssVisibilityControlCallback = sp<GnssVisibilityControlCallback>::make();
+ status = iGnssVisibilityControl->setCallback(gnssVisibilityControlCallback);
+ ASSERT_TRUE(status.isOk());
+
+ std::vector<String16> proxyApps{String16("com.example.ims"), String16("com.example.mdt")};
+ status = iGnssVisibilityControl->enableNfwLocationAccess(proxyApps);
+ ASSERT_TRUE(status.isOk());
+}
diff --git a/graphics/composer/aidl/Android.bp b/graphics/composer/aidl/Android.bp
index 5f5b54e..2532a7a 100644
--- a/graphics/composer/aidl/Android.bp
+++ b/graphics/composer/aidl/Android.bp
@@ -55,20 +55,6 @@
},
}
-cc_library {
- name: "android.hardware.graphics.composer3-translate-ndk",
- vendor_available: true,
- srcs: ["android/hardware/graphics/composer3/translate-ndk.cpp"],
- shared_libs: [
- "libbinder_ndk",
- "libhidlbase",
- "android.hardware.graphics.composer3-V1-ndk",
- "android.hardware.graphics.composer@2.1",
- "android.hardware.graphics.composer@2.4",
- ],
- export_include_dirs: ["include"],
-}
-
cc_library_headers {
name: "android.hardware.graphics.composer3-command-buffer",
vendor_available: true,
@@ -88,3 +74,16 @@
],
export_include_dirs: ["include"],
}
+
+cc_test {
+ name: "android.hardware.graphics.composer3-hidl2aidl-asserts",
+ vendor_available: true,
+ srcs: ["android/hardware/graphics/composer3/Hidl2AidlAsserts.cpp"],
+ shared_libs: [
+ "libbinder_ndk",
+ "libhidlbase",
+ "android.hardware.graphics.composer3-V1-ndk",
+ "android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.composer@2.4",
+ ],
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ClockMonotonicTimestamp.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ClockMonotonicTimestamp.aidl
index 856ec64..480a85c 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ClockMonotonicTimestamp.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/ClockMonotonicTimestamp.aidl
@@ -34,5 +34,5 @@
package android.hardware.graphics.composer3;
@VintfStability
parcelable ClockMonotonicTimestamp {
- long timestamp;
+ long timestampNanos;
}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PresentOrValidate.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PresentOrValidate.aidl
index 3514e53..e6ddeba 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PresentOrValidate.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/PresentOrValidate.aidl
@@ -38,7 +38,7 @@
android.hardware.graphics.composer3.PresentOrValidate.Result result;
@VintfStability
enum Result {
- Presented = 0,
- Validated = 1,
+ Validated = 0,
+ Presented = 1,
}
}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/ClockMonotonicTimestamp.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/ClockMonotonicTimestamp.aidl
index f385038..0cfd1c4 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/ClockMonotonicTimestamp.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/ClockMonotonicTimestamp.aidl
@@ -21,5 +21,5 @@
*/
@VintfStability
parcelable ClockMonotonicTimestamp {
- long timestamp;
+ long timestampNanos;
}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/Composition.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/Composition.aidl
index 49cdffc..803de06 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/Composition.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/Composition.aidl
@@ -79,13 +79,10 @@
* bottom of a display.
*
* Pixels in the buffer with an alpha of 0 (transparent) will show the
- * content underneath, and pixels with an alpha of 255 will be rendered in
+ * content underneath, and pixels with a max alpha value will be rendered in
* black. An alpha in between will show the underlying content blended with
* black.
*
- * Some devices may support this flag with a buffer containing an 8 bit
- * alpha mask.
- *
* Upon validateDisplay, the device may request a change from this type
* to either DEVICE or CLIENT.
*/
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/HandleIndex.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/HandleIndex.aidl
deleted file mode 100644
index 0a93c9e..0000000
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/HandleIndex.aidl
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- * 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.graphics.composer3;
-
-/**
- * Special index values (always negative) for command queue commands.
- */
-@VintfStability
-@Backing(type="int")
-enum HandleIndex {
- /**
- * No handle
- */
- EMPTY = -1,
- /**
- * Use cached handle
- */
- CACHED = -2,
-}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/translate-ndk.cpp b/graphics/composer/aidl/android/hardware/graphics/composer3/Hidl2AidlAsserts.cpp
similarity index 79%
rename from graphics/composer/aidl/android/hardware/graphics/composer3/translate-ndk.cpp
rename to graphics/composer/aidl/android/hardware/graphics/composer3/Hidl2AidlAsserts.cpp
index 8a789e3..d34b405 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/translate-ndk.cpp
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/Hidl2AidlAsserts.cpp
@@ -14,7 +14,33 @@
* limitations under the License.
*/
-#include "android/hardware/graphics/composer3/translate-ndk.h"
+#include "aidl/android/hardware/graphics/common/BlendMode.h"
+#include "aidl/android/hardware/graphics/common/FRect.h"
+#include "aidl/android/hardware/graphics/common/Rect.h"
+#include "aidl/android/hardware/graphics/composer3/Capability.h"
+#include "aidl/android/hardware/graphics/composer3/ClientTargetProperty.h"
+#include "aidl/android/hardware/graphics/composer3/Color.h"
+#include "aidl/android/hardware/graphics/composer3/Composition.h"
+#include "aidl/android/hardware/graphics/composer3/ContentType.h"
+#include "aidl/android/hardware/graphics/composer3/DisplayAttribute.h"
+#include "aidl/android/hardware/graphics/composer3/DisplayCapability.h"
+#include "aidl/android/hardware/graphics/composer3/DisplayConnectionType.h"
+#include "aidl/android/hardware/graphics/composer3/FloatColor.h"
+#include "aidl/android/hardware/graphics/composer3/FormatColorComponent.h"
+#include "aidl/android/hardware/graphics/composer3/IComposer.h"
+#include "aidl/android/hardware/graphics/composer3/PerFrameMetadata.h"
+#include "aidl/android/hardware/graphics/composer3/PerFrameMetadataBlob.h"
+#include "aidl/android/hardware/graphics/composer3/PerFrameMetadataKey.h"
+#include "aidl/android/hardware/graphics/composer3/PowerMode.h"
+#include "aidl/android/hardware/graphics/composer3/VsyncPeriodChangeConstraints.h"
+#include "aidl/android/hardware/graphics/composer3/VsyncPeriodChangeTimeline.h"
+#include "android/hardware/graphics/composer/2.1/IComposer.h"
+#include "android/hardware/graphics/composer/2.1/IComposerCallback.h"
+#include "android/hardware/graphics/composer/2.1/IComposerClient.h"
+#include "android/hardware/graphics/composer/2.2/IComposerClient.h"
+#include "android/hardware/graphics/composer/2.3/IComposerClient.h"
+#include "android/hardware/graphics/composer/2.4/IComposerClient.h"
+#include "android/hardware/graphics/composer/2.4/types.h"
namespace android::h2a {
@@ -129,15 +155,6 @@
static_cast<int>(::android::hardware::graphics::composer::V2_1::IComposerClient::
DisplayRequest::WRITE_CLIENT_TARGET_TO_OUTPUT));
-static_assert(aidl::android::hardware::graphics::composer3::HandleIndex::EMPTY ==
- static_cast<aidl::android::hardware::graphics::composer3::HandleIndex>(
- ::android::hardware::graphics::composer::V2_1::IComposerClient::HandleIndex::
- EMPTY));
-static_assert(aidl::android::hardware::graphics::composer3::HandleIndex::CACHED ==
- static_cast<aidl::android::hardware::graphics::composer3::HandleIndex>(
- ::android::hardware::graphics::composer::V2_1::IComposerClient::HandleIndex::
- CACHED));
-
static_assert(
aidl::android::hardware::graphics::composer3::PowerMode::OFF ==
static_cast<aidl::android::hardware::graphics::composer3::PowerMode>(
@@ -327,122 +344,11 @@
static_cast<aidl::android::hardware::graphics::composer3::ContentType>(
::android::hardware::graphics::composer::V2_4::IComposerClient::ContentType::GAME));
-__attribute__((warn_unused_result)) bool translate(
- const ::android::hardware::graphics::composer::V2_4::VsyncPeriodChangeTimeline& in,
- aidl::android::hardware::graphics::composer3::VsyncPeriodChangeTimeline* out) {
- out->newVsyncAppliedTimeNanos = static_cast<int64_t>(in.newVsyncAppliedTimeNanos);
- out->refreshRequired = static_cast<bool>(in.refreshRequired);
- out->refreshTimeNanos = static_cast<int64_t>(in.refreshTimeNanos);
- return true;
-}
-
-__attribute__((warn_unused_result)) bool translate(
- const ::android::hardware::graphics::composer::V2_1::IComposerClient::Rect& in,
- aidl::android::hardware::graphics::common::Rect* out) {
- out->left = static_cast<int32_t>(in.left);
- out->top = static_cast<int32_t>(in.top);
- out->right = static_cast<int32_t>(in.right);
- out->bottom = static_cast<int32_t>(in.bottom);
- return true;
-}
-
-__attribute__((warn_unused_result)) bool translate(
- const ::android::hardware::graphics::composer::V2_1::IComposerClient::FRect& in,
- aidl::android::hardware::graphics::common::FRect* out) {
- out->left = static_cast<float>(in.left);
- out->top = static_cast<float>(in.top);
- out->right = static_cast<float>(in.right);
- out->bottom = static_cast<float>(in.bottom);
- return true;
-}
-
-__attribute__((warn_unused_result)) bool translate(
- const ::android::hardware::graphics::composer::V2_1::IComposerClient::Color& in,
- aidl::android::hardware::graphics::composer3::Color* out) {
- // FIXME This requires conversion between signed and unsigned. Change this if it doesn't suit
- // your needs.
- if (in.r > std::numeric_limits<int8_t>::max() || in.r < 0) {
- return false;
- }
- out->r = static_cast<int8_t>(in.r);
- // FIXME This requires conversion between signed and unsigned. Change this if it doesn't suit
- // your needs.
- if (in.g > std::numeric_limits<int8_t>::max() || in.g < 0) {
- return false;
- }
- out->g = static_cast<int8_t>(in.g);
- // FIXME This requires conversion between signed and unsigned. Change this if it doesn't suit
- // your needs.
- if (in.b > std::numeric_limits<int8_t>::max() || in.b < 0) {
- return false;
- }
- out->b = static_cast<int8_t>(in.b);
- // FIXME This requires conversion between signed and unsigned. Change this if it doesn't suit
- // your needs.
- if (in.a > std::numeric_limits<int8_t>::max() || in.a < 0) {
- return false;
- }
- out->a = static_cast<int8_t>(in.a);
- return true;
-}
-
-__attribute__((warn_unused_result)) bool translate(
- const ::android::hardware::graphics::composer::V2_3::IComposerClient::PerFrameMetadata& in,
- aidl::android::hardware::graphics::composer3::PerFrameMetadata* out) {
- out->key =
- static_cast<aidl::android::hardware::graphics::composer3::PerFrameMetadataKey>(in.key);
- out->value = static_cast<float>(in.value);
- return true;
-}
-
-__attribute__((warn_unused_result)) bool translate(
- const ::android::hardware::graphics::composer::V2_2::IComposerClient::FloatColor& in,
- aidl::android::hardware::graphics::composer3::FloatColor* out) {
- out->r = static_cast<float>(in.r);
- out->g = static_cast<float>(in.g);
- out->b = static_cast<float>(in.b);
- out->a = static_cast<float>(in.a);
- return true;
-}
-
-__attribute__((warn_unused_result)) bool translate(
- const ::android::hardware::graphics::composer::V2_3::IComposerClient::PerFrameMetadataBlob&
- in,
- aidl::android::hardware::graphics::composer3::PerFrameMetadataBlob* out) {
- out->key =
- static_cast<aidl::android::hardware::graphics::composer3::PerFrameMetadataKey>(in.key);
- {
- size_t size = in.blob.size();
- for (size_t i = 0; i < size; i++) {
- // FIXME This requires conversion between signed and unsigned. Change this if it doesn't
- // suit your needs.
- if (in.blob[i] > std::numeric_limits<int8_t>::max() || in.blob[i] < 0) {
- return false;
- }
- out->blob.push_back(static_cast<int8_t>(in.blob[i]));
- }
- }
- return true;
-}
-
-__attribute__((warn_unused_result)) bool translate(
- const ::android::hardware::graphics::composer::V2_4::IComposerClient::
- VsyncPeriodChangeConstraints& in,
- aidl::android::hardware::graphics::composer3::VsyncPeriodChangeConstraints* out) {
- out->desiredTimeNanos = static_cast<int64_t>(in.desiredTimeNanos);
- out->seamlessRequired = static_cast<bool>(in.seamlessRequired);
- return true;
-}
-
-__attribute__((warn_unused_result)) bool translate(
- const ::android::hardware::graphics::composer::V2_4::IComposerClient::ClientTargetProperty&
- in,
- aidl::android::hardware::graphics::composer3::ClientTargetProperty* out) {
- out->pixelFormat =
- static_cast<aidl::android::hardware::graphics::common::PixelFormat>(in.pixelFormat);
- out->dataspace =
- static_cast<aidl::android::hardware::graphics::common::Dataspace>(in.dataspace);
- return true;
-}
+static_assert(
+ aidl::android::hardware::graphics::composer3::PresentOrValidate::Result::Presented ==
+ static_cast<aidl::android::hardware::graphics::composer3::PresentOrValidate::Result>(1));
+static_assert(
+ aidl::android::hardware::graphics::composer3::PresentOrValidate::Result::Validated ==
+ static_cast<aidl::android::hardware::graphics::composer3::PresentOrValidate::Result>(0));
} // namespace android::h2a
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/PresentOrValidate.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/PresentOrValidate.aidl
index f3153bd..5ae8940 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/PresentOrValidate.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/PresentOrValidate.aidl
@@ -27,6 +27,6 @@
/**
* Whether PresentOrValidate presented or validated the display.
*/
- @VintfStability enum Result { Presented, Validated }
+ @VintfStability enum Result { Validated, Presented }
Result result;
}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_ReadbackTest.cpp b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_ReadbackTest.cpp
index eddc2d3..0ece1d5 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_ReadbackTest.cpp
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_ReadbackTest.cpp
@@ -19,6 +19,7 @@
#include <aidl/Gtest.h>
#include <aidl/Vintf.h>
#include <aidl/android/hardware/graphics/common/BufferUsage.h>
+#include <aidl/android/hardware/graphics/composer3/IComposer.h>
#include <android/binder_manager.h>
#include <composer-vts/include/ReadbackVts.h>
#include <composer-vts/include/RenderEngineVts.h>
@@ -103,13 +104,8 @@
ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::OFF));
const auto errors = mReader.takeErrors();
ASSERT_TRUE(mReader.takeErrors().empty());
+ ASSERT_TRUE(mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty());
- std::vector<int64_t> layers;
- std::vector<Composition> types;
- mReader.takeChangedCompositionTypes(mPrimaryDisplay, &layers, &types);
-
- ASSERT_TRUE(layers.empty());
- ASSERT_TRUE(types.empty());
if (mComposerCallback != nullptr) {
EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount());
EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount());
@@ -118,12 +114,14 @@
}
::android::sp<::android::GraphicBuffer> allocate() {
+ const auto width = static_cast<uint32_t>(mDisplayWidth);
+ const auto height = static_cast<uint32_t>(mDisplayHeight);
+ const auto usage = static_cast<uint32_t>(common::BufferUsage::CPU_WRITE_OFTEN) |
+ static_cast<uint32_t>(common::BufferUsage::CPU_READ_OFTEN);
+
return ::android::sp<::android::GraphicBuffer>::make(
- mDisplayWidth, mDisplayHeight, ::android::PIXEL_FORMAT_RGBA_8888,
- /*layerCount*/ 1,
- static_cast<uint64_t>(static_cast<int>(common::BufferUsage::CPU_WRITE_OFTEN) |
- static_cast<int>(common::BufferUsage::CPU_READ_OFTEN)),
- "VtsHalGraphicsComposer3_ReadbackTest");
+ width, height, ::android::PIXEL_FORMAT_RGBA_8888,
+ /*layerCount*/ 1u, usage, "VtsHalGraphicsComposer3_ReadbackTest");
}
void writeLayers(const std::vector<std::shared_ptr<TestLayer>>& layers) {
@@ -141,10 +139,10 @@
}
std::vector<CommandResultPayload> results;
- const auto status = mComposerClient->executeCommands(commands, &results);
+ auto status = mComposerClient->executeCommands(commands, &results);
ASSERT_TRUE(status.isOk()) << "executeCommands failed " << status.getDescription();
- mReader.parse(results);
+ mReader.parse(std::move(results));
mWriter.reset();
}
@@ -262,11 +260,7 @@
execute();
// if hwc cannot handle and asks for composition change,
// just succeed the test
- std::vector<int64_t> changedCompositionLayers;
- std::vector<Composition> changedCompositionTypes;
- mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers,
- &changedCompositionTypes);
- if (!changedCompositionLayers.empty()) {
+ if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
GTEST_SUCCEED();
return;
}
@@ -320,11 +314,7 @@
mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
execute();
- std::vector<int64_t> changedCompositionLayers;
- std::vector<Composition> changedCompositionTypes;
- mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers,
- &changedCompositionTypes);
- if (!changedCompositionLayers.empty()) {
+ if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
GTEST_SUCCEED();
return;
}
@@ -380,11 +370,7 @@
mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
execute();
- std::vector<int64_t> changedCompositionLayers;
- std::vector<Composition> changedCompositionTypes;
- mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers,
- &changedCompositionTypes);
- if (!changedCompositionLayers.empty()) {
+ if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
GTEST_SUCCEED();
return;
}
@@ -433,7 +419,8 @@
return;
}
- aidl::android::hardware::common::NativeHandle bufferHandle = ::android::dupToAidl(nullptr);
+ aidl::android::hardware::common::NativeHandle bufferHandle =
+ ::android::dupToAidl(mGraphicBuffer->handle);
ndk::ScopedFileDescriptor releaseFence = ndk::ScopedFileDescriptor(-1);
const auto error =
mComposerClient->setReadbackBuffer(mPrimaryDisplay, bufferHandle, releaseFence);
@@ -495,14 +482,10 @@
mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
execute();
- std::vector<int64_t> changedCompositionLayers;
- std::vector<Composition> changedCompositionTypes;
- mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers,
- &changedCompositionTypes);
- if (!changedCompositionLayers.empty()) {
- ASSERT_EQ(1, changedCompositionLayers.size());
+ auto changedCompositionTypes = mReader.takeChangedCompositionTypes(mPrimaryDisplay);
+ if (!changedCompositionTypes.empty()) {
ASSERT_EQ(1, changedCompositionTypes.size());
- ASSERT_EQ(Composition::CLIENT, changedCompositionTypes[0]);
+ ASSERT_EQ(Composition::CLIENT, changedCompositionTypes[0].composition);
PixelFormat clientFormat = PixelFormat::RGBA_8888;
auto clientUsage = static_cast<uint32_t>(
@@ -537,9 +520,8 @@
mWriter.setClientTarget(mPrimaryDisplay, 0, mGraphicBuffer->handle, fenceHandle.get(),
clientDataspace, std::vector<common::Rect>(1, damage));
execute();
- mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers,
- &changedCompositionTypes);
- ASSERT_TRUE(changedCompositionLayers.empty());
+ changedCompositionTypes = mReader.takeChangedCompositionTypes(mPrimaryDisplay);
+ ASSERT_TRUE(changedCompositionTypes.empty());
}
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -609,15 +591,12 @@
mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
execute();
- std::vector<int64_t> changedCompositionLayers;
- std::vector<Composition> changedCompositionTypes;
- mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers,
- &changedCompositionTypes);
+ auto changedCompositionTypes = mReader.takeChangedCompositionTypes(mPrimaryDisplay);
if (changedCompositionTypes.size() != 1) {
continue;
}
// create client target buffer
- ASSERT_EQ(Composition::CLIENT, changedCompositionTypes[0]);
+ ASSERT_EQ(Composition::CLIENT, changedCompositionTypes[0].composition);
mGraphicBuffer->reallocate(static_cast<uint32_t>(mDisplayWidth),
static_cast<uint32_t>(mDisplayHeight),
static_cast<int32_t>(common::PixelFormat::RGBA_8888),
@@ -642,9 +621,8 @@
mWriter.setClientTarget(mPrimaryDisplay, 0, mGraphicBuffer->handle, fenceHandle.get(),
clientDataspace, std::vector<common::Rect>(1, clientFrame));
execute();
- mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers,
- &changedCompositionTypes);
- ASSERT_EQ(0, changedCompositionLayers.size());
+ changedCompositionTypes = mReader.takeChangedCompositionTypes(mPrimaryDisplay);
+ ASSERT_TRUE(changedCompositionTypes.empty());
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter.presentDisplay(mPrimaryDisplay);
@@ -687,11 +665,7 @@
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
execute();
- std::vector<int64_t> changedCompositionLayers;
- std::vector<Composition> changedCompositionTypes;
- mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers,
- &changedCompositionTypes);
- if (!changedCompositionLayers.empty()) {
+ if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
GTEST_SUCCEED();
return;
}
@@ -718,10 +692,7 @@
mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
- mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers,
- &changedCompositionTypes);
- ASSERT_TRUE(changedCompositionLayers.empty());
- ASSERT_TRUE(changedCompositionTypes.empty());
+ ASSERT_TRUE(mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty());
mWriter.presentDisplay(mPrimaryDisplay);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -758,11 +729,7 @@
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
execute();
- std::vector<int64_t> changedCompositionLayers;
- std::vector<Composition> changedCompositionTypes;
- mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers,
- &changedCompositionTypes);
- if (!changedCompositionLayers.empty()) {
+ if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
GTEST_SUCCEED();
return;
}
@@ -821,11 +788,7 @@
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
execute();
- std::vector<int64_t> changedCompositionLayers;
- std::vector<Composition> changedCompositionTypes;
- mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers,
- &changedCompositionTypes);
- if (!changedCompositionLayers.empty()) {
+ if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
GTEST_SUCCEED();
return;
}
@@ -879,11 +842,7 @@
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
execute();
- std::vector<int64_t> changedCompositionLayers;
- std::vector<Composition> changedCompositionTypes;
- mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers,
- &changedCompositionTypes);
- if (!changedCompositionLayers.empty()) {
+ if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
GTEST_SUCCEED();
return;
}
@@ -904,10 +863,7 @@
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
execute();
- mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers,
- &changedCompositionTypes);
- ASSERT_TRUE(changedCompositionLayers.empty());
- ASSERT_TRUE(changedCompositionTypes.empty());
+ ASSERT_TRUE(mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty());
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter.presentDisplay(mPrimaryDisplay);
execute();
@@ -1029,11 +985,7 @@
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
execute();
- std::vector<int64_t> changedCompositionLayers;
- std::vector<Composition> changedCompositionTypes;
- mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers,
- &changedCompositionTypes);
- if (!changedCompositionLayers.empty()) {
+ if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
GTEST_SUCCEED();
return;
}
@@ -1074,11 +1026,7 @@
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
execute();
- std::vector<int64_t> changedCompositionLayers;
- std::vector<Composition> changedCompositionTypes;
- mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers,
- &changedCompositionTypes);
- if (!changedCompositionLayers.empty()) {
+ if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
GTEST_SUCCEED();
return;
}
@@ -1114,11 +1062,7 @@
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
execute();
- std::vector<int64_t> changedCompositionLayers;
- std::vector<Composition> changedCompositionTypes;
- mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers,
- &changedCompositionTypes);
- if (!changedCompositionLayers.empty()) {
+ if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
GTEST_SUCCEED();
return;
}
@@ -1197,11 +1141,7 @@
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
execute();
- std::vector<int64_t> changedCompositionLayers;
- std::vector<Composition> changedCompositionTypes;
- mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers,
- &changedCompositionTypes);
- if (!changedCompositionLayers.empty()) {
+ if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
GTEST_SUCCEED();
return;
}
@@ -1243,11 +1183,7 @@
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
execute();
- std::vector<int64_t> changedCompositionLayers;
- std::vector<Composition> changedCompositionTypes;
- mReader.takeChangedCompositionTypes(mPrimaryDisplay, &changedCompositionLayers,
- &changedCompositionTypes);
- if (!changedCompositionLayers.empty()) {
+ if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
GTEST_SUCCEED();
return;
}
@@ -1289,10 +1225,7 @@
ASSERT_TRUE(mReader.takeErrors().empty());
mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
execute();
- std::vector<int64_t> layers;
- std::vector<Composition> types;
- mReader.takeChangedCompositionTypes(mPrimaryDisplay, &layers, &types);
- if (!layers.empty()) {
+ if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
GTEST_SUCCEED();
return;
}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_TargetTest.cpp b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_TargetTest.cpp
index 6638744..4dbe191 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_TargetTest.cpp
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_TargetTest.cpp
@@ -1142,13 +1142,7 @@
void TearDown() override {
const auto errors = mReader.takeErrors();
ASSERT_TRUE(mReader.takeErrors().empty());
-
- std::vector<int64_t> layers;
- std::vector<Composition> types;
- mReader.takeChangedCompositionTypes(mPrimaryDisplay, &layers, &types);
-
- ASSERT_TRUE(layers.empty());
- ASSERT_TRUE(types.empty());
+ ASSERT_TRUE(mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty());
ASSERT_NO_FATAL_FAILURE(GraphicsComposerAidlTest::TearDown());
}
@@ -1164,7 +1158,7 @@
const auto status = mComposerClient->executeCommands(commands, &results);
ASSERT_TRUE(status.isOk()) << "executeCommands failed " << status.getDescription();
- mReader.parse(results);
+ mReader.parse(std::move(results));
mWriter.reset();
}
@@ -1299,10 +1293,12 @@
execute();
EXPECT_TRUE(mReader.takeErrors().empty());
- int presentFence;
- mReader.takePresentFence(mPrimaryDisplay, &presentFence);
- EXPECT_NE(-1, presentFence);
- return sp<::android::Fence>::make(presentFence);
+ auto presentFence = mReader.takePresentFence(mPrimaryDisplay);
+ // take ownership
+ const int fenceOwner = presentFence.get();
+ *presentFence.getR() = -1;
+ EXPECT_NE(-1, fenceOwner);
+ return sp<::android::Fence>::make(fenceOwner);
}
int32_t getVsyncPeriod() {
@@ -1592,10 +1588,7 @@
mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
execute();
- std::vector<int64_t> layers;
- std::vector<Composition> types;
- mReader.takeChangedCompositionTypes(mPrimaryDisplay, &layers, &types);
- if (!layers.empty()) {
+ if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
GTEST_SUCCEED() << "Composition change requested, skipping test";
return;
}
@@ -1640,10 +1633,8 @@
mWriter.validateDisplay(mPrimaryDisplay, ComposerClientWriter::kNoTimestamp);
execute();
- std::vector<int64_t> layers;
- std::vector<Composition> types;
- mReader.takeChangedCompositionTypes(mPrimaryDisplay, &layers, &types);
- if (!layers.empty()) {
+
+ if (!mReader.takeChangedCompositionTypes(mPrimaryDisplay).empty()) {
GTEST_SUCCEED() << "Composition change requested, skipping test";
return;
}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/ReadbackVts.cpp b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/ReadbackVts.cpp
index 4de2d71..5eb912b 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/ReadbackVts.cpp
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/composer-vts/ReadbackVts.cpp
@@ -242,13 +242,13 @@
int outBytesPerPixel;
int outBytesPerStride;
- auto status = mGraphicBuffer->lockAsync(mUsage, mAccessRegion, nullptr, fenceHandle.get(),
+ void* bufData = nullptr;
+ auto status = mGraphicBuffer->lockAsync(mUsage, mAccessRegion, &bufData, fenceHandle.get(),
&outBytesPerPixel, &outBytesPerStride);
EXPECT_EQ(::android::OK, status);
ASSERT_TRUE(mPixelFormat == PixelFormat::RGB_888 || mPixelFormat == PixelFormat::RGBA_8888);
- ReadbackHelper::compareColorBuffers(expectedColors, mGraphicBuffer.get(),
- static_cast<int32_t>(mStride), mWidth, mHeight,
- mPixelFormat);
+ ReadbackHelper::compareColorBuffers(expectedColors, bufData, static_cast<int32_t>(mStride),
+ mWidth, mHeight, mPixelFormat);
status = mGraphicBuffer->unlock();
EXPECT_EQ(::android::OK, status);
}
diff --git a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientReader.h b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientReader.h
index 1dc9145..f9e35e9 100644
--- a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientReader.h
+++ b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientReader.h
@@ -26,40 +26,16 @@
#include <inttypes.h>
#include <string.h>
-#include <aidl/android/hardware/graphics/common/BlendMode.h>
#include <aidl/android/hardware/graphics/composer3/ClientTargetProperty.h>
-#include <aidl/android/hardware/graphics/composer3/Color.h>
#include <aidl/android/hardware/graphics/composer3/Composition.h>
-#include <aidl/android/hardware/graphics/composer3/FloatColor.h>
-#include <aidl/android/hardware/graphics/composer3/HandleIndex.h>
-#include <aidl/android/hardware/graphics/composer3/IComposer.h>
-#include <aidl/android/hardware/graphics/composer3/IComposerClient.h>
-#include <aidl/android/hardware/graphics/composer3/PerFrameMetadata.h>
-#include <aidl/android/hardware/graphics/composer3/PerFrameMetadataBlob.h>
-
#include <aidl/android/hardware/graphics/composer3/CommandResultPayload.h>
-#include <aidl/android/hardware/graphics/composer3/DisplayCommand.h>
-#include <aidl/android/hardware/graphics/common/ColorTransform.h>
-#include <aidl/android/hardware/graphics/common/FRect.h>
-#include <aidl/android/hardware/graphics/common/Rect.h>
-#include <aidl/android/hardware/graphics/common/Transform.h>
#include <log/log.h>
#include <sync/sync.h>
-#include <aidlcommonsupport/NativeHandle.h>
-using aidl::android::hardware::graphics::common::BlendMode;
-using aidl::android::hardware::graphics::common::ColorTransform;
using aidl::android::hardware::graphics::common::Dataspace;
-using aidl::android::hardware::graphics::common::FRect;
-using aidl::android::hardware::graphics::common::Rect;
-using aidl::android::hardware::graphics::common::Transform;
-
-using namespace aidl::android::hardware::graphics::composer3;
-
-using aidl::android::hardware::common::NativeHandle;
namespace aidl::android::hardware::graphics::composer3 {
@@ -69,35 +45,37 @@
// Parse and execute commands from the command queue. The commands are
// actually return values from the server and will be saved in ReturnData.
- void parse(const std::vector<CommandResultPayload>& results) {
+ void parse(std::vector<CommandResultPayload>&& results) {
resetData();
- for (const auto& result : results) {
+ for (auto& result : results) {
switch (result.getTag()) {
case CommandResultPayload::Tag::error:
- parseSetError(result.get<CommandResultPayload::Tag::error>());
+ parseSetError(std::move(result.get<CommandResultPayload::Tag::error>()));
break;
case CommandResultPayload::Tag::changedCompositionTypes:
- parseSetChangedCompositionTypes(
- result.get<CommandResultPayload::Tag::changedCompositionTypes>());
+ parseSetChangedCompositionTypes(std::move(
+ result.get<CommandResultPayload::Tag::changedCompositionTypes>()));
break;
case CommandResultPayload::Tag::displayRequest:
parseSetDisplayRequests(
- result.get<CommandResultPayload::Tag::displayRequest>());
+ std::move(result.get<CommandResultPayload::Tag::displayRequest>()));
break;
case CommandResultPayload::Tag::presentFence:
- parseSetPresentFence(result.get<CommandResultPayload::Tag::presentFence>());
+ parseSetPresentFence(
+ std::move(result.get<CommandResultPayload::Tag::presentFence>()));
break;
case CommandResultPayload::Tag::releaseFences:
- parseSetReleaseFences(result.get<CommandResultPayload::Tag::releaseFences>());
+ parseSetReleaseFences(
+ std::move(result.get<CommandResultPayload::Tag::releaseFences>()));
break;
case CommandResultPayload::Tag::presentOrValidateResult:
- parseSetPresentOrValidateDisplayResult(
- result.get<CommandResultPayload::Tag::presentOrValidateResult>());
+ parseSetPresentOrValidateDisplayResult(std::move(
+ result.get<CommandResultPayload::Tag::presentOrValidateResult>()));
break;
case CommandResultPayload::Tag::clientTargetProperty:
- parseSetClientTargetProperty(
- result.get<CommandResultPayload::Tag::clientTargetProperty>());
+ parseSetClientTargetProperty(std::move(
+ result.get<CommandResultPayload::Tag::clientTargetProperty>()));
break;
}
}
@@ -105,211 +83,140 @@
std::vector<CommandError> takeErrors() { return std::move(mErrors); }
- bool hasChanges(int64_t display, uint32_t* outNumChangedCompositionTypes,
+ void hasChanges(int64_t display, uint32_t* outNumChangedCompositionTypes,
uint32_t* outNumLayerRequestMasks) const {
auto found = mReturnData.find(display);
if (found == mReturnData.end()) {
*outNumChangedCompositionTypes = 0;
*outNumLayerRequestMasks = 0;
- return false;
+ return;
}
const ReturnData& data = found->second;
- *outNumChangedCompositionTypes = static_cast<uint32_t>(data.compositionTypes.size());
- *outNumLayerRequestMasks = static_cast<uint32_t>(data.requestMasks.size());
-
- return !(data.compositionTypes.empty() && data.requestMasks.empty());
+ *outNumChangedCompositionTypes = static_cast<uint32_t>(data.changedLayers.size());
+ *outNumLayerRequestMasks = static_cast<uint32_t>(data.displayRequests.layerRequests.size());
}
// Get and clear saved changed composition types.
- void takeChangedCompositionTypes(int64_t display, std::vector<int64_t>* outLayers,
- std::vector<Composition>* outTypes) {
+ std::vector<ChangedCompositionLayer> takeChangedCompositionTypes(int64_t display) {
auto found = mReturnData.find(display);
if (found == mReturnData.end()) {
- outLayers->clear();
- outTypes->clear();
- return;
+ return {};
}
ReturnData& data = found->second;
-
- *outLayers = std::move(data.changedLayers);
- *outTypes = std::move(data.compositionTypes);
+ return std::move(data.changedLayers);
}
// Get and clear saved display requests.
- void takeDisplayRequests(int64_t display, uint32_t* outDisplayRequestMask,
- std::vector<int64_t>* outLayers,
- std::vector<uint32_t>* outLayerRequestMasks) {
+ DisplayRequest takeDisplayRequests(int64_t display) {
auto found = mReturnData.find(display);
if (found == mReturnData.end()) {
- *outDisplayRequestMask = 0;
- outLayers->clear();
- outLayerRequestMasks->clear();
- return;
+ return {};
}
ReturnData& data = found->second;
-
- *outDisplayRequestMask = data.displayRequests;
- *outLayers = std::move(data.requestedLayers);
- *outLayerRequestMasks = std::move(data.requestMasks);
+ return std::move(data.displayRequests);
}
// Get and clear saved release fences.
- void takeReleaseFences(int64_t display, std::vector<int64_t>* outLayers,
- std::vector<int>* outReleaseFences) {
+ std::vector<ReleaseFences::Layer> takeReleaseFences(int64_t display) {
auto found = mReturnData.find(display);
if (found == mReturnData.end()) {
- outLayers->clear();
- outReleaseFences->clear();
- return;
+ return {};
}
ReturnData& data = found->second;
-
- *outLayers = std::move(data.releasedLayers);
- *outReleaseFences = std::move(data.releaseFences);
+ return std::move(data.releasedLayers);
}
// Get and clear saved present fence.
- void takePresentFence(int64_t display, int* outPresentFence) {
+ ndk::ScopedFileDescriptor takePresentFence(int64_t display) {
auto found = mReturnData.find(display);
if (found == mReturnData.end()) {
- *outPresentFence = -1;
- return;
+ return {};
}
ReturnData& data = found->second;
-
- *outPresentFence = data.presentFence;
- data.presentFence = -1;
+ return std::move(data.presentFence);
}
// Get what stage succeeded during PresentOrValidate: Present or Validate
- void takePresentOrValidateStage(int64_t display, uint32_t* state) {
+ std::optional<PresentOrValidate::Result> takePresentOrValidateStage(int64_t display) {
auto found = mReturnData.find(display);
if (found == mReturnData.end()) {
- *state = static_cast<uint32_t>(-1);
- return;
+ return std::nullopt;
}
ReturnData& data = found->second;
- *state = data.presentOrValidateState;
+ return data.presentOrValidateState;
}
// Get the client target properties requested by hardware composer.
- void takeClientTargetProperty(int64_t display, ClientTargetProperty* outClientTargetProperty,
- float* outWhitePointNits) {
+ ClientTargetPropertyWithNits takeClientTargetProperty(int64_t display) {
auto found = mReturnData.find(display);
// If not found, return the default values.
if (found == mReturnData.end()) {
- outClientTargetProperty->pixelFormat = common::PixelFormat::RGBA_8888;
- outClientTargetProperty->dataspace = Dataspace::UNKNOWN;
- *outWhitePointNits = -1.f;
- return;
+ return ClientTargetPropertyWithNits{
+ .clientTargetProperty = {common::PixelFormat::RGBA_8888, Dataspace::UNKNOWN},
+ .whitePointNits = -1.f,
+ };
}
ReturnData& data = found->second;
- *outClientTargetProperty = data.clientTargetProperty;
- *outWhitePointNits = data.clientTargetWhitePointNits;
+ return std::move(data.clientTargetProperty);
}
private:
void resetData() {
mErrors.clear();
-
- for (auto& data : mReturnData) {
- if (data.second.presentFence >= 0) {
- close(data.second.presentFence);
- }
- for (auto fence : data.second.releaseFences) {
- if (fence >= 0) {
- close(fence);
- }
- }
- }
-
mReturnData.clear();
}
- void parseSetError(const CommandError& error) { mErrors.emplace_back(error); }
+ void parseSetError(CommandError&& error) { mErrors.emplace_back(error); }
- void parseSetChangedCompositionTypes(const ChangedCompositionTypes& changedCompositionTypes) {
+ void parseSetChangedCompositionTypes(ChangedCompositionTypes&& changedCompositionTypes) {
auto& data = mReturnData[changedCompositionTypes.display];
-
- data.changedLayers.reserve(changedCompositionTypes.layers.size());
- data.compositionTypes.reserve(changedCompositionTypes.layers.size());
- for (const auto& layer : changedCompositionTypes.layers) {
- data.changedLayers.push_back(layer.layer);
- data.compositionTypes.push_back(layer.composition);
- }
+ data.changedLayers = std::move(changedCompositionTypes.layers);
}
- void parseSetDisplayRequests(const DisplayRequest& displayRequest) {
+ void parseSetDisplayRequests(DisplayRequest&& displayRequest) {
auto& data = mReturnData[displayRequest.display];
-
- data.displayRequests = displayRequest.mask;
- data.requestedLayers.reserve(displayRequest.layerRequests.size());
- data.requestMasks.reserve(displayRequest.layerRequests.size());
- for (const auto& layerRequest : displayRequest.layerRequests) {
- data.requestedLayers.push_back(layerRequest.layer);
- data.requestMasks.push_back(layerRequest.mask);
- }
+ data.displayRequests = std::move(displayRequest);
}
- void parseSetPresentFence(const PresentFence& presentFence) {
+ void parseSetPresentFence(PresentFence&& presentFence) {
auto& data = mReturnData[presentFence.display];
- if (data.presentFence >= 0) {
- close(data.presentFence);
- }
- data.presentFence = dup(presentFence.fence.get());
+ data.presentFence = std::move(presentFence.fence);
}
- void parseSetReleaseFences(const ReleaseFences& releaseFences) {
+ void parseSetReleaseFences(ReleaseFences&& releaseFences) {
auto& data = mReturnData[releaseFences.display];
- data.releasedLayers.reserve(releaseFences.layers.size());
- data.releaseFences.reserve(releaseFences.layers.size());
- for (const auto& layer : releaseFences.layers) {
- data.releasedLayers.push_back(layer.layer);
- data.releaseFences.push_back(dup(layer.fence.get()));
- }
+ data.releasedLayers = std::move(releaseFences.layers);
}
- void parseSetPresentOrValidateDisplayResult(const PresentOrValidate& presentOrValidate) {
+ void parseSetPresentOrValidateDisplayResult(const PresentOrValidate&& presentOrValidate) {
auto& data = mReturnData[presentOrValidate.display];
- data.presentOrValidateState =
- presentOrValidate.result == PresentOrValidate::Result::Presented ? 1 : 0;
+ data.presentOrValidateState = std::move(presentOrValidate.result);
}
- void parseSetClientTargetProperty(const ClientTargetPropertyWithNits& clientTargetProperty) {
+ void parseSetClientTargetProperty(const ClientTargetPropertyWithNits&& clientTargetProperty) {
auto& data = mReturnData[clientTargetProperty.display];
- data.clientTargetProperty.pixelFormat =
- clientTargetProperty.clientTargetProperty.pixelFormat;
- data.clientTargetProperty.dataspace = clientTargetProperty.clientTargetProperty.dataspace;
- data.clientTargetWhitePointNits = clientTargetProperty.whitePointNits;
+ data.clientTargetProperty = std::move(clientTargetProperty);
}
struct ReturnData {
- int32_t displayRequests = 0;
+ DisplayRequest displayRequests;
+ std::vector<ChangedCompositionLayer> changedLayers;
+ ndk::ScopedFileDescriptor presentFence;
+ std::vector<ReleaseFences::Layer> releasedLayers;
+ PresentOrValidate::Result presentOrValidateState;
- std::vector<int64_t> changedLayers;
- std::vector<Composition> compositionTypes;
-
- std::vector<int64_t> requestedLayers;
- std::vector<uint32_t> requestMasks;
-
- int presentFence = -1;
-
- std::vector<int64_t> releasedLayers;
- std::vector<int> releaseFences;
-
- uint32_t presentOrValidateState;
-
- ClientTargetProperty clientTargetProperty{common::PixelFormat::RGBA_8888,
- Dataspace::UNKNOWN};
- float clientTargetWhitePointNits = -1.f;
+ ClientTargetPropertyWithNits clientTargetProperty = {
+ .clientTargetProperty = {common::PixelFormat::RGBA_8888, Dataspace::UNKNOWN},
+ .whitePointNits = -1.f,
+ };
};
std::vector<CommandError> mErrors;
diff --git a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
index 5bab266..16d63e5 100644
--- a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
+++ b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
@@ -30,9 +30,6 @@
#include <aidl/android/hardware/graphics/composer3/Color.h>
#include <aidl/android/hardware/graphics/composer3/Composition.h>
#include <aidl/android/hardware/graphics/composer3/FloatColor.h>
-#include <aidl/android/hardware/graphics/composer3/HandleIndex.h>
-#include <aidl/android/hardware/graphics/composer3/IComposer.h>
-#include <aidl/android/hardware/graphics/composer3/IComposerClient.h>
#include <aidl/android/hardware/graphics/composer3/PerFrameMetadata.h>
#include <aidl/android/hardware/graphics/composer3/PerFrameMetadataBlob.h>
diff --git a/graphics/composer/aidl/include/android/hardware/graphics/composer3/translate-ndk.h b/graphics/composer/aidl/include/android/hardware/graphics/composer3/translate-ndk.h
deleted file mode 100644
index 263167e..0000000
--- a/graphics/composer/aidl/include/android/hardware/graphics/composer3/translate-ndk.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/**
- * 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 <limits>
-#include "aidl/android/hardware/graphics/common/BlendMode.h"
-#include "aidl/android/hardware/graphics/common/FRect.h"
-#include "aidl/android/hardware/graphics/common/Rect.h"
-#include "aidl/android/hardware/graphics/composer3/Capability.h"
-#include "aidl/android/hardware/graphics/composer3/ClientTargetProperty.h"
-#include "aidl/android/hardware/graphics/composer3/Color.h"
-#include "aidl/android/hardware/graphics/composer3/Composition.h"
-#include "aidl/android/hardware/graphics/composer3/ContentType.h"
-#include "aidl/android/hardware/graphics/composer3/DisplayAttribute.h"
-#include "aidl/android/hardware/graphics/composer3/DisplayCapability.h"
-#include "aidl/android/hardware/graphics/composer3/DisplayConnectionType.h"
-#include "aidl/android/hardware/graphics/composer3/FloatColor.h"
-#include "aidl/android/hardware/graphics/composer3/FormatColorComponent.h"
-#include "aidl/android/hardware/graphics/composer3/HandleIndex.h"
-#include "aidl/android/hardware/graphics/composer3/IComposer.h"
-#include "aidl/android/hardware/graphics/composer3/PerFrameMetadata.h"
-#include "aidl/android/hardware/graphics/composer3/PerFrameMetadataBlob.h"
-#include "aidl/android/hardware/graphics/composer3/PerFrameMetadataKey.h"
-#include "aidl/android/hardware/graphics/composer3/PowerMode.h"
-#include "aidl/android/hardware/graphics/composer3/VsyncPeriodChangeConstraints.h"
-#include "aidl/android/hardware/graphics/composer3/VsyncPeriodChangeTimeline.h"
-#include "android/hardware/graphics/composer/2.1/IComposer.h"
-#include "android/hardware/graphics/composer/2.1/IComposerCallback.h"
-#include "android/hardware/graphics/composer/2.1/IComposerClient.h"
-#include "android/hardware/graphics/composer/2.2/IComposerClient.h"
-#include "android/hardware/graphics/composer/2.3/IComposerClient.h"
-#include "android/hardware/graphics/composer/2.4/IComposerClient.h"
-#include "android/hardware/graphics/composer/2.4/types.h"
-
-namespace android::h2a {
-
-__attribute__((warn_unused_result)) bool translate(
- const ::android::hardware::graphics::composer::V2_4::VsyncPeriodChangeTimeline& in,
- aidl::android::hardware::graphics::composer3::VsyncPeriodChangeTimeline* out);
-__attribute__((warn_unused_result)) bool translate(
- const ::android::hardware::graphics::composer::V2_1::IComposerClient::Rect& in,
- aidl::android::hardware::graphics::common::Rect* out);
-__attribute__((warn_unused_result)) bool translate(
- const ::android::hardware::graphics::composer::V2_1::IComposerClient::FRect& in,
- aidl::android::hardware::graphics::common::FRect* out);
-__attribute__((warn_unused_result)) bool translate(
- const ::android::hardware::graphics::composer::V2_1::IComposerClient::Color& in,
- aidl::android::hardware::graphics::composer3::Color* out);
-__attribute__((warn_unused_result)) bool translate(
- const ::android::hardware::graphics::composer::V2_3::IComposerClient::PerFrameMetadata& in,
- aidl::android::hardware::graphics::composer3::PerFrameMetadata* out);
-__attribute__((warn_unused_result)) bool translate(
- const ::android::hardware::graphics::composer::V2_2::IComposerClient::FloatColor& in,
- aidl::android::hardware::graphics::composer3::FloatColor* out);
-__attribute__((warn_unused_result)) bool translate(
- const ::android::hardware::graphics::composer::V2_3::IComposerClient::PerFrameMetadataBlob&
- in,
- aidl::android::hardware::graphics::composer3::PerFrameMetadataBlob* out);
-__attribute__((warn_unused_result)) bool translate(
- const ::android::hardware::graphics::composer::V2_4::IComposerClient::
- VsyncPeriodChangeConstraints& in,
- aidl::android::hardware::graphics::composer3::VsyncPeriodChangeConstraints* out);
-__attribute__((warn_unused_result)) bool translate(
- const ::android::hardware::graphics::composer::V2_4::IComposerClient::ClientTargetProperty&
- in,
- aidl::android::hardware::graphics::composer3::ClientTargetProperty* out);
-
-} // namespace android::h2a
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/input/classifier/1.0/vts/functional/Android.bp b/input/classifier/1.0/vts/functional/Android.bp
index 58945d3..5ff1457 100644
--- a/input/classifier/1.0/vts/functional/Android.bp
+++ b/input/classifier/1.0/vts/functional/Android.bp
@@ -30,7 +30,10 @@
":inputconstants_aidl",
"VtsHalInputClassifierV1_0TargetTest.cpp",
],
- header_libs: ["jni_headers"],
+ header_libs: [
+ "jni_headers",
+ "libbinder_headers",
+ ],
static_libs: [
"android.hardware.input.classifier@1.0",
"android.hardware.input.common@1.0",
diff --git a/ir/OWNERS b/ir/OWNERS
new file mode 100644
index 0000000..04de9ef
--- /dev/null
+++ b/ir/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 163905
+connoro@google.com
diff --git a/ir/aidl/Android.bp b/ir/aidl/Android.bp
index 8741157..6dacb85 100644
--- a/ir/aidl/Android.bp
+++ b/ir/aidl/Android.bp
@@ -25,7 +25,6 @@
sdk_version: "module_current",
},
ndk: {
- separate_platform_variant: false,
vndk: {
// TODO(b/206116595) enable this
enabled: false,
diff --git a/memtrack/OWNERS b/memtrack/OWNERS
new file mode 100644
index 0000000..a182ed9
--- /dev/null
+++ b/memtrack/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 30545
+connoro@google.com
diff --git a/radio/aidl/compat/service/service.cpp b/radio/aidl/compat/service/service.cpp
index 7433fee..8af05de 100644
--- a/radio/aidl/compat/service/service.cpp
+++ b/radio/aidl/compat/service/service.cpp
@@ -81,6 +81,7 @@
}
static void main() {
+ base::InitLogging(nullptr, base::LogdLogger(base::RADIO));
base::SetDefaultTag("radiocompat");
base::SetMinimumLogSeverity(base::VERBOSE);
LOG(DEBUG) << "Radio HAL compat service starting...";
diff --git a/tv/tuner/1.1/default/Frontend.cpp b/tv/tuner/1.1/default/Frontend.cpp
index f5463a9..919c956 100644
--- a/tv/tuner/1.1/default/Frontend.cpp
+++ b/tv/tuner/1.1/default/Frontend.cpp
@@ -88,46 +88,60 @@
Return<Result> Frontend::scan(const FrontendSettings& settings, FrontendScanType type) {
ALOGV("%s", __FUNCTION__);
+
+ // If it's in middle of scanning, stop it first.
+ if (mScanThread.joinable()) {
+ mScanThread.join();
+ }
+
+ mFrontendSettings = settings;
+ mFrontendScanType = type;
+ mScanThread = std::thread(&Frontend::scanThreadLoop, this);
+
+ return Result::SUCCESS;
+}
+
+void Frontend::scanThreadLoop() {
FrontendScanMessage msg;
if (mIsLocked) {
msg.isEnd(true);
mCallback->onScanMessage(FrontendScanMessageType::END, msg);
- return Result::SUCCESS;
+ return;
}
uint32_t frequency;
- switch (settings.getDiscriminator()) {
+ switch (mFrontendSettings.getDiscriminator()) {
case FrontendSettings::hidl_discriminator::analog:
- frequency = settings.analog().frequency;
+ frequency = mFrontendSettings.analog().frequency;
break;
case FrontendSettings::hidl_discriminator::atsc:
- frequency = settings.atsc().frequency;
+ frequency = mFrontendSettings.atsc().frequency;
break;
case FrontendSettings::hidl_discriminator::atsc3:
- frequency = settings.atsc3().frequency;
+ frequency = mFrontendSettings.atsc3().frequency;
break;
case FrontendSettings::hidl_discriminator::dvbs:
- frequency = settings.dvbs().frequency;
+ frequency = mFrontendSettings.dvbs().frequency;
break;
case FrontendSettings::hidl_discriminator::dvbc:
- frequency = settings.dvbc().frequency;
+ frequency = mFrontendSettings.dvbc().frequency;
break;
case FrontendSettings::hidl_discriminator::dvbt:
- frequency = settings.dvbt().frequency;
+ frequency = mFrontendSettings.dvbt().frequency;
break;
case FrontendSettings::hidl_discriminator::isdbs:
- frequency = settings.isdbs().frequency;
+ frequency = mFrontendSettings.isdbs().frequency;
break;
case FrontendSettings::hidl_discriminator::isdbs3:
- frequency = settings.isdbs3().frequency;
+ frequency = mFrontendSettings.isdbs3().frequency;
break;
case FrontendSettings::hidl_discriminator::isdbt:
- frequency = settings.isdbt().frequency;
+ frequency = mFrontendSettings.isdbt().frequency;
break;
}
- if (type == FrontendScanType::SCAN_BLIND) {
+ if (mFrontendScanType == FrontendScanType::SCAN_BLIND) {
frequency += 100 * 1000;
}
@@ -204,8 +218,6 @@
msg.isLocked(true);
mCallback->onScanMessage(FrontendScanMessageType::LOCKED, msg);
mIsLocked = true;
-
- return Result::SUCCESS;
}
Return<Result> Frontend::scan_1_1(const FrontendSettings& settings, FrontendScanType type,
@@ -218,6 +230,10 @@
Return<Result> Frontend::stopScan() {
ALOGV("%s", __FUNCTION__);
+ if (mScanThread.joinable()) {
+ mScanThread.join();
+ }
+
mIsLocked = false;
return Result::SUCCESS;
}
diff --git a/tv/tuner/1.1/default/Frontend.h b/tv/tuner/1.1/default/Frontend.h
index a28fb64..bf739a8 100644
--- a/tv/tuner/1.1/default/Frontend.h
+++ b/tv/tuner/1.1/default/Frontend.h
@@ -20,6 +20,7 @@
#include <android/hardware/tv/tuner/1.1/IFrontend.h>
#include <fstream>
#include <iostream>
+#include <thread>
#include "Tuner.h"
using namespace std;
@@ -81,13 +82,17 @@
private:
virtual ~Frontend();
bool supportsSatellite();
+ void scanThreadLoop();
+
sp<IFrontendCallback> mCallback;
sp<Tuner> mTunerService;
FrontendType mType = FrontendType::UNDEFINED;
FrontendId mId = 0;
bool mIsLocked = false;
uint32_t mCiCamId;
-
+ std::thread mScanThread;
+ FrontendSettings mFrontendSettings;
+ FrontendScanType mFrontendScanType;
std::ifstream mFrontendData;
};
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/AudioStreamType.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/AudioStreamType.aidl
index bfd2aa8..6c538ea 100644
--- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/AudioStreamType.aidl
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/AudioStreamType.aidl
@@ -51,4 +51,8 @@
OPUS = 13,
VORBIS = 14,
DRA = 15,
+ AAC_ADTS = 16,
+ AAC_LATM = 17,
+ AAC_HE_ADTS = 18,
+ AAC_HE_LATM = 19,
}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl
index 993c639..61a9555 100644
--- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl
@@ -48,4 +48,5 @@
int mpuSequenceNumber;
boolean isPesPrivateData;
android.hardware.tv.tuner.DemuxFilterMediaEventExtraMetaData extraMetaData;
+ android.hardware.tv.tuner.DemuxFilterScIndexMask scIndexMask;
}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IFrontend.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IFrontend.aidl
index ed5b0c0..e7aa070 100644
--- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IFrontend.aidl
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IFrontend.aidl
@@ -43,7 +43,7 @@
void stopScan();
android.hardware.tv.tuner.FrontendStatus[] getStatus(in android.hardware.tv.tuner.FrontendStatusType[] statusTypes);
void setLnb(in int lnbId);
- void setLna(in boolean bEnable);
int linkCiCam(in int ciCamId);
void unlinkCiCam(in int ciCamId);
+ String getHardwareInfo();
}
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 0e903d8..decf5b1 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
@@ -44,4 +44,5 @@
int[] getLnbIds();
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);
}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/AudioStreamType.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/AudioStreamType.aidl
index 1bb5c68f..9e9a8cf 100644
--- a/tv/tuner/aidl/android/hardware/tv/tuner/AudioStreamType.aidl
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/AudioStreamType.aidl
@@ -99,4 +99,24 @@
* SJ/T 11368-2006
*/
DRA,
+
+ /*
+ * AAC with ADTS (Audio Data Transport Format).
+ */
+ AAC_ADTS,
+
+ /*
+ * AAC with ADTS with LATM (Low-overhead MPEG-4 Audio Transport Multiplex).
+ */
+ AAC_LATM,
+
+ /*
+ * High-Efficiency AAC (HE-AAC) with ADTS (Audio Data Transport Format).
+ */
+ AAC_HE_ADTS,
+
+ /*
+ * High-Efficiency AAC (HE-AAC) with LATM (Low-overhead MPEG-4 Audio Transport Multiplex).
+ */
+ AAC_HE_LATM,
}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl
index e92b711..32f0cb2 100644
--- a/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/DemuxFilterMediaEvent.aidl
@@ -19,6 +19,7 @@
import android.hardware.common.NativeHandle;
import android.hardware.tv.tuner.DemuxFilterMediaEventExtraMetaData;
+import android.hardware.tv.tuner.DemuxFilterScIndexMask;
/**
* Filter Event for Audio or Video Filter.
@@ -84,4 +85,10 @@
boolean isPesPrivateData;
DemuxFilterMediaEventExtraMetaData extraMetaData;
+
+ /**
+ * DemuxFilterScIndexMask for the key frame info. It's optional to hardware which can only
+ * access unit framing at decode stage.
+ */
+ DemuxFilterScIndexMask scIndexMask;
}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/IFrontend.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/IFrontend.aidl
index b2717db..5b3ce39 100644
--- a/tv/tuner/aidl/android/hardware/tv/tuner/IFrontend.aidl
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/IFrontend.aidl
@@ -117,13 +117,6 @@
void setLnb(in int lnbId);
/**
- * Enable or Disable Low Noise Amplifier (LNA).
- *
- * @param bEnable true if activate LNA module; false if deactivate LNA
- */
- void setLna(in boolean bEnable);
-
- /**
* Link Conditional Access Modules (CAM) to Frontend support Common
* Interface (CI) bypass mode.
*
@@ -143,4 +136,14 @@
* @param ciCamId specify CI-CAM Id to unlink.
*/
void unlinkCiCam(in int ciCamId);
+
+ /**
+ * Request Hardware information about the frontend.
+ *
+ * The client may use this to collect vendor specific hardware information, e.g. RF
+ * chip version, Demod chip version, detailed status of dvbs blind scan, etc.
+ *
+ * @return the frontend hardware information.
+ */
+ String getHardwareInfo();
}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/ITuner.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/ITuner.aidl
index ab8b0b8..1fcbb06 100644
--- a/tv/tuner/aidl/android/hardware/tv/tuner/ITuner.aidl
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/ITuner.aidl
@@ -120,4 +120,11 @@
* @return the newly opened Lnb iterface.
*/
ILnb openLnbByName(in String lnbName, out int[] lnbId);
+
+ /**
+ * Enable or Disable Low Noise Amplifier (LNA).
+ *
+ * @param bEnable true if activate LNA module; false if deactivate LNA
+ */
+ void setLna(in boolean bEnable);
}
diff --git a/tv/tuner/aidl/default/Frontend.cpp b/tv/tuner/aidl/default/Frontend.cpp
index c1b8b5d..714612d 100644
--- a/tv/tuner/aidl/default/Frontend.cpp
+++ b/tv/tuner/aidl/default/Frontend.cpp
@@ -87,47 +87,60 @@
::ndk::ScopedAStatus Frontend::scan(const FrontendSettings& in_settings, FrontendScanType in_type) {
ALOGV("%s", __FUNCTION__);
+ // If it's in middle of scanning, stop it first.
+ if (mScanThread.joinable()) {
+ mScanThread.join();
+ }
+
+ mFrontendSettings = in_settings;
+ mFrontendScanType = in_type;
+ mScanThread = std::thread(&Frontend::scanThreadLoop, this);
+
+ return ::ndk::ScopedAStatus::ok();
+}
+
+void Frontend::scanThreadLoop() {
if (mIsLocked) {
FrontendScanMessage msg;
msg.set<FrontendScanMessage::Tag::isEnd>(true);
mCallback->onScanMessage(FrontendScanMessageType::END, msg);
- return ::ndk::ScopedAStatus::ok();
+ return;
}
int64_t frequency = 0;
- switch (in_settings.getTag()) {
+ switch (mFrontendSettings.getTag()) {
case FrontendSettings::Tag::analog:
- frequency = in_settings.get<FrontendSettings::Tag::analog>().frequency;
+ frequency = mFrontendSettings.get<FrontendSettings::Tag::analog>().frequency;
break;
case FrontendSettings::Tag::atsc:
- frequency = in_settings.get<FrontendSettings::Tag::atsc>().frequency;
+ frequency = mFrontendSettings.get<FrontendSettings::Tag::atsc>().frequency;
break;
case FrontendSettings::Tag::atsc3:
- frequency = in_settings.get<FrontendSettings::Tag::atsc3>().frequency;
+ frequency = mFrontendSettings.get<FrontendSettings::Tag::atsc3>().frequency;
break;
case FrontendSettings::Tag::dvbs:
- frequency = in_settings.get<FrontendSettings::Tag::dvbs>().frequency;
+ frequency = mFrontendSettings.get<FrontendSettings::Tag::dvbs>().frequency;
break;
case FrontendSettings::Tag::dvbc:
- frequency = in_settings.get<FrontendSettings::Tag::dvbc>().frequency;
+ frequency = mFrontendSettings.get<FrontendSettings::Tag::dvbc>().frequency;
break;
case FrontendSettings::Tag::dvbt:
- frequency = in_settings.get<FrontendSettings::Tag::dvbt>().frequency;
+ frequency = mFrontendSettings.get<FrontendSettings::Tag::dvbt>().frequency;
break;
case FrontendSettings::Tag::isdbs:
- frequency = in_settings.get<FrontendSettings::Tag::isdbs>().frequency;
+ frequency = mFrontendSettings.get<FrontendSettings::Tag::isdbs>().frequency;
break;
case FrontendSettings::Tag::isdbs3:
- frequency = in_settings.get<FrontendSettings::Tag::isdbs3>().frequency;
+ frequency = mFrontendSettings.get<FrontendSettings::Tag::isdbs3>().frequency;
break;
case FrontendSettings::Tag::isdbt:
- frequency = in_settings.get<FrontendSettings::Tag::isdbt>().frequency;
+ frequency = mFrontendSettings.get<FrontendSettings::Tag::isdbt>().frequency;
break;
default:
break;
}
- if (in_type == FrontendScanType::SCAN_BLIND) {
+ if (mFrontendScanType == FrontendScanType::SCAN_BLIND) {
frequency += 100 * 1000;
}
@@ -250,13 +263,15 @@
mCallback->onScanMessage(FrontendScanMessageType::LOCKED, msg);
mIsLocked = true;
}
-
- return ::ndk::ScopedAStatus::ok();
}
::ndk::ScopedAStatus Frontend::stopScan() {
ALOGV("%s", __FUNCTION__);
+ if (mScanThread.joinable()) {
+ mScanThread.join();
+ }
+
mIsLocked = false;
return ::ndk::ScopedAStatus::ok();
}
@@ -703,12 +718,6 @@
return ::ndk::ScopedAStatus::ok();
}
-::ndk::ScopedAStatus Frontend::setLna(bool /* in_bEnable */) {
- ALOGV("%s", __FUNCTION__);
-
- return ::ndk::ScopedAStatus::ok();
-}
-
::ndk::ScopedAStatus Frontend::setLnb(int32_t /* in_lnbId */) {
ALOGV("%s", __FUNCTION__);
if (!supportsSatellite()) {
@@ -743,6 +752,13 @@
return STATUS_OK;
}
+::ndk::ScopedAStatus Frontend::getHardwareInfo(std::string* _aidl_return) {
+ ALOGV("%s", __FUNCTION__);
+
+ *_aidl_return = "Sample Frontend";
+ return ::ndk::ScopedAStatus::ok();
+}
+
FrontendType Frontend::getFrontendType() {
return mType;
}
diff --git a/tv/tuner/aidl/default/Frontend.h b/tv/tuner/aidl/default/Frontend.h
index 5e7b10c..fdedf1e 100644
--- a/tv/tuner/aidl/default/Frontend.h
+++ b/tv/tuner/aidl/default/Frontend.h
@@ -19,6 +19,7 @@
#include <aidl/android/hardware/tv/tuner/BnFrontend.h>
#include <fstream>
#include <iostream>
+#include <thread>
#include "Tuner.h"
using namespace std;
@@ -46,9 +47,9 @@
::ndk::ScopedAStatus getStatus(const std::vector<FrontendStatusType>& in_statusTypes,
std::vector<FrontendStatus>* _aidl_return) override;
::ndk::ScopedAStatus setLnb(int32_t in_lnbId) override;
- ::ndk::ScopedAStatus setLna(bool in_bEnable) override;
::ndk::ScopedAStatus linkCiCam(int32_t in_ciCamId, int32_t* _aidl_return) override;
::ndk::ScopedAStatus unlinkCiCam(int32_t in_ciCamId) override;
+ ::ndk::ScopedAStatus getHardwareInfo(std::string* _aidl_return) override;
binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
@@ -60,13 +61,17 @@
private:
virtual ~Frontend();
bool supportsSatellite();
+ void scanThreadLoop();
+
std::shared_ptr<IFrontendCallback> mCallback;
std::shared_ptr<Tuner> mTuner;
FrontendType mType = FrontendType::UNDEFINED;
int32_t mId = 0;
bool mIsLocked = false;
int32_t mCiCamId;
-
+ std::thread mScanThread;
+ FrontendSettings mFrontendSettings;
+ FrontendScanType mFrontendScanType;
std::ifstream mFrontendData;
};
diff --git a/tv/tuner/aidl/default/Tuner.cpp b/tv/tuner/aidl/default/Tuner.cpp
index 9e81177..45f3dfa 100644
--- a/tv/tuner/aidl/default/Tuner.cpp
+++ b/tv/tuner/aidl/default/Tuner.cpp
@@ -318,6 +318,12 @@
return ::ndk::ScopedAStatus::ok();
}
+::ndk::ScopedAStatus Tuner::setLna(bool /* in_bEnable */) {
+ ALOGV("%s", __FUNCTION__);
+
+ 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 682496c..b33a1be 100644
--- a/tv/tuner/aidl/default/Tuner.h
+++ b/tv/tuner/aidl/default/Tuner.h
@@ -56,6 +56,7 @@
::ndk::ScopedAStatus openLnbByName(const std::string& in_lnbName,
std::vector<int32_t>* out_lnbId,
std::shared_ptr<ILnb>* _aidl_return) override;
+ ::ndk::ScopedAStatus setLna(bool in_bEnable) override;
binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
diff --git a/tv/tuner/aidl/vts/functional/FrontendTests.cpp b/tv/tuner/aidl/vts/functional/FrontendTests.cpp
index f24dea1..075ffad 100644
--- a/tv/tuner/aidl/vts/functional/FrontendTests.cpp
+++ b/tv/tuner/aidl/vts/functional/FrontendTests.cpp
@@ -484,6 +484,13 @@
feId = INVALID_ID;
}
+AssertionResult FrontendTests::verifyHardwareInfo() {
+ EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
+ std::string info;
+ ndk::ScopedAStatus status = mFrontend->getHardwareInfo(&info);
+ return AssertionResult(status.isOk() && !info.empty());
+}
+
void FrontendTests::tuneTest(FrontendConfig frontendConf) {
int32_t feId;
getFrontendIdByType(frontendConf.type, feId);
@@ -500,6 +507,18 @@
ASSERT_TRUE(closeFrontend());
}
+void FrontendTests::debugInfoTest(FrontendConfig frontendConf) {
+ int32_t feId;
+ getFrontendIdByType(frontendConf.type, feId);
+ ASSERT_TRUE(feId != INVALID_ID);
+ ASSERT_TRUE(openFrontendById(feId));
+ ASSERT_TRUE(setFrontendCallback());
+ ASSERT_TRUE(tuneFrontend(frontendConf, false /*testWithDemux*/));
+ ASSERT_TRUE(verifyHardwareInfo());
+ ASSERT_TRUE(stopTuneFrontend(false /*testWithDemux*/));
+ ASSERT_TRUE(closeFrontend());
+}
+
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 e5a9cd3..8f769a0 100644
--- a/tv/tuner/aidl/vts/functional/FrontendTests.h
+++ b/tv/tuner/aidl/vts/functional/FrontendTests.h
@@ -94,10 +94,12 @@
AssertionResult linkCiCam(int32_t ciCamId);
AssertionResult unlinkCiCam(int32_t ciCamId);
+ AssertionResult verifyHardwareInfo();
void getFrontendIdByType(FrontendType feType, int32_t& feId);
void tuneTest(FrontendConfig frontendConf);
void scanTest(FrontendConfig frontend, FrontendScanType type);
+ void debugInfoTest(FrontendConfig frontendConf);
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 89e42df..f489bf7 100644
--- a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
+++ b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
@@ -704,6 +704,9 @@
bool mediaFilter = isMediaFilter(filterConf);
auto filter = mFilterTests.getFilterById(filterId);
+ // startTime needs to be set before calling setDelayHint.
+ auto startTime = std::chrono::steady_clock::now();
+
auto timeDelayInMs = std::chrono::milliseconds(filterConf.timeDelayInMs);
if (timeDelayInMs.count() > 0) {
FilterDelayHint delayHint;
@@ -724,15 +727,22 @@
ASSERT_EQ(filter->setDelayHint(delayHint).isOk(), !mediaFilter);
}
- // start and stop filter in order to circumvent callback scheduler race
- // conditions after adjusting filter delays.
+ // start and stop filter (and wait for first callback) in order to
+ // circumvent callback scheduler race conditions after adjusting filter
+ // delays.
+ auto cb = mFilterTests.getFilterCallbacks().at(filterId);
+ auto future =
+ cb->verifyFilterCallback([](const std::vector<DemuxFilterEvent>&) { return true; });
mFilterTests.startFilter(filterId);
+
+ auto timeout = std::chrono::seconds(30);
+ ASSERT_EQ(future.wait_for(timeout), std::future_status::ready);
+
mFilterTests.stopFilter(filterId);
if (!mediaFilter) {
- auto cb = mFilterTests.getFilterCallbacks().at(filterId);
int callbackSize = 0;
- auto future = cb->verifyFilterCallback(
+ future = cb->verifyFilterCallback(
[&callbackSize](const std::vector<DemuxFilterEvent>& events) {
for (const auto& event : events) {
callbackSize += getDemuxFilterEventDataLength(event);
@@ -744,11 +754,9 @@
// hint beforehand.
ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
- auto startTime = std::chrono::steady_clock::now();
ASSERT_TRUE(mFilterTests.startFilter(filterId));
// block and wait for callback to be received.
- auto timeout = std::chrono::seconds(30);
ASSERT_EQ(future.wait_for(timeout), std::future_status::ready);
auto duration = std::chrono::steady_clock::now() - startTime;
@@ -883,6 +891,14 @@
mFrontendTests.tuneTest(frontendMap[live.frontendId]);
}
+TEST_P(TunerFrontendAidlTest, getHardwareInfo) {
+ description("Test Frontend get hardware info");
+ if (!live.hasFrontendConnection) {
+ return;
+ }
+ mFrontendTests.debugInfoTest(frontendMap[live.frontendId]);
+}
+
TEST_P(TunerBroadcastAidlTest, BroadcastDataFlowVideoFilterTest) {
description("Test Video Filter functionality in Broadcast use case.");
if (!live.hasFrontendConnection) {