Merge "BidirectionalSequenceLSTM op: Fixes VTS test for merge_outputs"
diff --git a/atrace/1.0/default/AtraceDevice.cpp b/atrace/1.0/default/AtraceDevice.cpp
index 43bcd9a..35d11e9 100644
--- a/atrace/1.0/default/AtraceDevice.cpp
+++ b/atrace/1.0/default/AtraceDevice.cpp
@@ -30,24 +30,25 @@
struct TracingConfig {
std::string description;
+ // path and if error on failure
std::vector<std::pair<std::string, bool>> paths;
};
// This is a map stores categories and their sysfs paths with required flags
const std::map<std::string, TracingConfig> kTracingMap = {
- // gfx
- {
- "gfx",
- {"Graphics",
- {{"/sys/kernel/debug/tracing/events/mdss/enable", false},
- {"/sys/kernel/debug/tracing/events/sde/enable", false},
- {"/sys/kernel/debug/tracing/events/mali_systrace/enable", false}}},
- },
- {
- "ion",
- {"ION allocation",
- {{"/sys/kernel/debug/tracing/events/kmem/ion_alloc_buffer_start/enable", true}}},
- },
+ // gfx
+ {
+ "gfx",
+ {"Graphics",
+ {{"/sys/kernel/debug/tracing/events/mdss/enable", false},
+ {"/sys/kernel/debug/tracing/events/sde/enable", false},
+ {"/sys/kernel/debug/tracing/events/mali_systrace/enable", false}}},
+ },
+ {
+ "ion",
+ {"ION allocation",
+ {{"/sys/kernel/debug/tracing/events/kmem/ion_alloc_buffer_start/enable", false}}},
+ },
};
// Methods from ::android::hardware::atrace::V1_0::IAtraceDevice follow.
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h
index 9e32bb5..258dbd9 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VmsUtils.h
@@ -19,6 +19,7 @@
#include <memory>
#include <string>
+#include <unordered_set>
#include <android/hardware/automotive/vehicle/2.0/types.h>
@@ -42,6 +43,20 @@
int type;
int subtype;
int version;
+ bool operator==(const VmsLayer& layer) const {
+ return this->type == layer.type && this->subtype == layer.subtype &&
+ this->version == layer.version;
+ }
+
+ // Class for hash function
+ class VmsLayerHashFunction {
+ public:
+ // Hash of the variables is returned.
+ size_t operator()(const VmsLayer& layer) const {
+ return std::hash<int>()(layer.type) ^ std::hash<int>()(layer.type) ^
+ std::hash<int>()(layer.type);
+ }
+ };
};
struct VmsLayerAndPublisher {
@@ -66,6 +81,15 @@
std::vector<VmsLayer> dependencies;
};
+// A VmsOffers refers to a list of layers that can be published by the publisher
+// with the specified publisher ID.
+struct VmsOffers {
+ VmsOffers(int publisher_id, std::vector<VmsLayerOffering> offerings)
+ : publisher_id(publisher_id), offerings(offerings) {}
+ int publisher_id;
+ std::vector<VmsLayerOffering> offerings;
+};
+
// A VmsSubscriptionsState is delivered in response to a
// VmsMessageType.SUBSCRIPTIONS_REQUEST or on the first SUBSCRIBE or last
// UNSUBSCRIBE for a layer. It indicates which layers or associated_layers are
@@ -81,6 +105,9 @@
std::vector<VmsAssociatedLayer> associated_layers;
};
+// Creates an empty base VMS message with some pre-populated default fields.
+std::unique_ptr<VehiclePropValue> createBaseVmsMessage(size_t message_size);
+
// Creates a VehiclePropValue containing a message of type
// VmsMessageType.SUBSCRIBE, specifying to the VMS service
// which layer to subscribe to.
@@ -106,8 +133,7 @@
// Creates a VehiclePropValue containing a message of type
// VmsMessageType.OFFERING, specifying to the VMS service which layers are being
// offered and their dependencies, if any.
-std::unique_ptr<VehiclePropValue> createOfferingMessage(
- const std::vector<VmsLayerOffering>& offering);
+std::unique_ptr<VehiclePropValue> createOfferingMessage(const VmsOffers& offers);
// Creates a VehiclePropValue containing a message of type
// VmsMessageType.AVAILABILITY_REQUEST.
@@ -143,8 +169,40 @@
// function to ParseFromString.
std::string parseData(const VehiclePropValue& value);
-// TODO(aditin): Need to implement additional parsing functions per message
-// type.
+// Creates a VehiclePropValue containing a message of type
+// VmsMessageType.PUBLISHER_ID_REQUEST with the given publisher information.
+// Returns a nullptr if the input is empty.
+std::unique_ptr<VehiclePropValue> createPublisherIdRequest(
+ const std::string& vms_provider_description);
+
+// Returns the publisher ID by parsing the VehiclePropValue containing the ID.
+// Returns null if the message is invalid.
+int32_t parsePublisherIdResponse(const VehiclePropValue& publisher_id_response);
+
+// Returns true if the new sequence number is greater than the last seen
+// sequence number.
+bool isSequenceNumberNewer(const VehiclePropValue& subscription_change,
+ const int last_seen_sequence_number);
+
+// Returns sequence number of the message.
+int32_t getSequenceNumberForSubscriptionsState(const VehiclePropValue& subscription_change);
+
+// Takes a subscription change message and returns the layers that have active
+// subscriptions of the layers that are offered by your HAL client/publisher.
+//
+// A publisher can use this function when receiving a subscription change message
+// to determine which layers to publish data on.
+// The caller of this function can optionally decide to not consume these layers
+// if the subscription change has the sequence number less than the last seen
+// sequence number.
+std::vector<VmsLayer> getSubscribedLayers(const VehiclePropValue& subscription_change,
+ const VmsOffers& offers);
+
+// Takes an availability change message and returns true if the parsed message implies that
+// the service has newly started or restarted.
+// If the message has a sequence number 0, it means that the service
+// has newly started or restarted.
+bool hasServiceNewlyStarted(const VehiclePropValue& availability_change);
} // namespace vms
} // namespace V2_0
diff --git a/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp b/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp
index f001a32..1863191 100644
--- a/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VmsUtils.cpp
@@ -27,16 +27,23 @@
static constexpr int kMessageIndex = toInt(VmsBaseMessageIntegerValuesIndex::MESSAGE_TYPE);
static constexpr int kMessageTypeSize = 1;
+static constexpr int kPublisherIdSize = 1;
static constexpr int kLayerNumberSize = 1;
static constexpr int kLayerSize = 3;
static constexpr int kLayerAndPublisherSize = 4;
+static constexpr int kPublisherIdIndex =
+ toInt(VmsPublisherInformationIntegerValuesIndex::PUBLISHER_ID);
+static constexpr int kSubscriptionStateSequenceNumberIndex =
+ toInt(VmsSubscriptionsStateIntegerValuesIndex::SEQUENCE_NUMBER);
+static constexpr int kAvailabilitySequenceNumberIndex =
+ toInt(VmsAvailabilityStateIntegerValuesIndex::SEQUENCE_NUMBER);
// TODO(aditin): We should extend the VmsMessageType enum to include a first and
// last, which would prevent breakages in this API. However, for all of the
// functions in this module, we only need to guarantee that the message type is
-// between SUBSCRIBE and DATA.
+// between SUBSCRIBE and PUBLISHER_ID_RESPONSE.
static constexpr int kFirstMessageType = toInt(VmsMessageType::SUBSCRIBE);
-static constexpr int kLastMessageType = toInt(VmsMessageType::DATA);
+static constexpr int kLastMessageType = toInt(VmsMessageType::PUBLISHER_ID_RESPONSE);
std::unique_ptr<VehiclePropValue> createBaseVmsMessage(size_t message_size) {
auto result = createVehiclePropValue(VehiclePropertyType::INT32, message_size);
@@ -77,17 +84,16 @@
return result;
}
-std::unique_ptr<VehiclePropValue> createOfferingMessage(
- const std::vector<VmsLayerOffering>& offering) {
- int message_size = kMessageTypeSize + kLayerNumberSize;
- for (const auto& offer : offering) {
- message_size += kLayerNumberSize + (1 + offer.dependencies.size()) * kLayerSize;
+std::unique_ptr<VehiclePropValue> createOfferingMessage(const VmsOffers& offers) {
+ int message_size = kMessageTypeSize + kPublisherIdSize + kLayerNumberSize;
+ for (const auto& offer : offers.offerings) {
+ message_size += kLayerSize + kLayerNumberSize + (offer.dependencies.size() * kLayerSize);
}
auto result = createBaseVmsMessage(message_size);
- std::vector<int32_t> offers = {toInt(VmsMessageType::OFFERING),
- static_cast<int>(offering.size())};
- for (const auto& offer : offering) {
+ std::vector<int32_t> offerings = {toInt(VmsMessageType::OFFERING), offers.publisher_id,
+ static_cast<int>(offers.offerings.size())};
+ for (const auto& offer : offers.offerings) {
std::vector<int32_t> layer_vector = {offer.layer.type, offer.layer.subtype,
offer.layer.version,
static_cast<int32_t>(offer.dependencies.size())};
@@ -97,9 +103,9 @@
layer_vector.insert(layer_vector.end(), dependency_layer.begin(),
dependency_layer.end());
}
- offers.insert(offers.end(), layer_vector.begin(), layer_vector.end());
+ offerings.insert(offerings.end(), layer_vector.begin(), layer_vector.end());
}
- result->value.int32Values = offers;
+ result->value.int32Values = offerings;
return result;
}
@@ -153,6 +159,103 @@
}
}
+std::unique_ptr<VehiclePropValue> createPublisherIdRequest(
+ const std::string& vms_provider_description) {
+ auto result = createBaseVmsMessage(kMessageTypeSize);
+ result->value.int32Values = hidl_vec<int32_t>{
+ toInt(VmsMessageType::PUBLISHER_ID_REQUEST),
+ };
+ result->value.bytes =
+ std::vector<uint8_t>(vms_provider_description.begin(), vms_provider_description.end());
+ return result;
+}
+
+int32_t parsePublisherIdResponse(const VehiclePropValue& publisher_id_response) {
+ if (isValidVmsMessage(publisher_id_response) &&
+ parseMessageType(publisher_id_response) == VmsMessageType::PUBLISHER_ID_RESPONSE &&
+ publisher_id_response.value.int32Values.size() > kPublisherIdIndex) {
+ return publisher_id_response.value.int32Values[kPublisherIdIndex];
+ }
+ return -1;
+}
+
+bool isSequenceNumberNewer(const VehiclePropValue& subscription_change,
+ const int last_seen_sequence_number) {
+ return (isValidVmsMessage(subscription_change) &&
+ parseMessageType(subscription_change) == VmsMessageType::SUBSCRIPTIONS_CHANGE &&
+ subscription_change.value.int32Values.size() > kSubscriptionStateSequenceNumberIndex &&
+ subscription_change.value.int32Values[kSubscriptionStateSequenceNumberIndex] >
+ last_seen_sequence_number);
+}
+
+int32_t getSequenceNumberForSubscriptionsState(const VehiclePropValue& subscription_change) {
+ if (isValidVmsMessage(subscription_change) &&
+ parseMessageType(subscription_change) == VmsMessageType::SUBSCRIPTIONS_CHANGE &&
+ subscription_change.value.int32Values.size() > kSubscriptionStateSequenceNumberIndex) {
+ return subscription_change.value.int32Values[kSubscriptionStateSequenceNumberIndex];
+ }
+ return -1;
+}
+
+std::vector<VmsLayer> getSubscribedLayers(const VehiclePropValue& subscription_change,
+ const VmsOffers& offers) {
+ if (isValidVmsMessage(subscription_change) &&
+ parseMessageType(subscription_change) == VmsMessageType::SUBSCRIPTIONS_CHANGE &&
+ subscription_change.value.int32Values.size() > kSubscriptionStateSequenceNumberIndex) {
+ const int32_t num_of_layers = subscription_change.value.int32Values[toInt(
+ VmsSubscriptionsStateIntegerValuesIndex::NUMBER_OF_LAYERS)];
+ const int32_t num_of_associated_layers = subscription_change.value.int32Values[toInt(
+ VmsSubscriptionsStateIntegerValuesIndex ::NUMBER_OF_ASSOCIATED_LAYERS)];
+
+ std::unordered_set<VmsLayer, VmsLayer::VmsLayerHashFunction> offered_layers;
+ for (const auto& offer : offers.offerings) {
+ offered_layers.insert(offer.layer);
+ }
+ std::vector<VmsLayer> subscribed_layers;
+
+ int current_index = toInt(VmsSubscriptionsStateIntegerValuesIndex::SUBSCRIPTIONS_START);
+ // Add all subscribed layers which are offered by the current publisher.
+ for (int i = 0; i < num_of_layers; i++) {
+ VmsLayer layer = VmsLayer(subscription_change.value.int32Values[current_index],
+ subscription_change.value.int32Values[current_index + 1],
+ subscription_change.value.int32Values[current_index + 2]);
+ if (offered_layers.find(layer) != offered_layers.end()) {
+ subscribed_layers.push_back(layer);
+ }
+ current_index += kLayerSize;
+ }
+ // Add all subscribed associated layers which are offered by the current publisher.
+ // For this, we need to check if the associated layer has a publisher ID which is
+ // same as that of the current publisher.
+ for (int i = 0; i < num_of_associated_layers; i++) {
+ VmsLayer layer = VmsLayer(subscription_change.value.int32Values[current_index],
+ subscription_change.value.int32Values[current_index + 1],
+ subscription_change.value.int32Values[current_index + 2]);
+ current_index += kLayerSize;
+ if (offered_layers.find(layer) != offered_layers.end()) {
+ int32_t num_of_publisher_ids = subscription_change.value.int32Values[current_index];
+ current_index++;
+ for (int j = 0; j < num_of_publisher_ids; j++) {
+ if (subscription_change.value.int32Values[current_index] ==
+ offers.publisher_id) {
+ subscribed_layers.push_back(layer);
+ }
+ current_index++;
+ }
+ }
+ }
+ return subscribed_layers;
+ }
+ return {};
+}
+
+bool hasServiceNewlyStarted(const VehiclePropValue& availability_change) {
+ return (isValidVmsMessage(availability_change) &&
+ parseMessageType(availability_change) == VmsMessageType::AVAILABILITY_CHANGE &&
+ availability_change.value.int32Values.size() > kAvailabilitySequenceNumberIndex &&
+ availability_change.value.int32Values[kAvailabilitySequenceNumberIndex] == 0);
+}
+
} // namespace vms
} // namespace V2_0
} // namespace vehicle
diff --git a/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp b/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
index f64eab5..0975071 100644
--- a/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
+++ b/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
@@ -278,7 +278,6 @@
cb->reset();
VehiclePropValue actualValue(*subscribedValue.get());
- actualValue.status = VehiclePropertyStatus::AVAILABLE;
hal->sendPropEvent(std::move(subscribedValue));
ASSERT_TRUE(cb->waitForExpectedEvents(1)) << "Events received: "
diff --git a/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp b/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp
index 414c5c2..5ea5bd4 100644
--- a/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp
+++ b/automotive/vehicle/2.0/default/tests/VmsUtils_test.cpp
@@ -60,52 +60,64 @@
}
TEST(VmsUtilsTest, singleOfferingMessage) {
- std::vector<VmsLayerOffering> offering = {VmsLayerOffering(VmsLayer(1, 0, 2))};
- auto message = createOfferingMessage(offering);
+ VmsOffers offers = {123, {VmsLayerOffering(VmsLayer(1, 0, 2))}};
+ auto message = createOfferingMessage(offers);
ASSERT_NE(message, nullptr);
EXPECT_TRUE(isValidVmsMessage(*message));
EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE));
- EXPECT_EQ(message->value.int32Values.size(), 0x6ul);
+ EXPECT_EQ(message->value.int32Values.size(), 0x7ul);
EXPECT_EQ(parseMessageType(*message), VmsMessageType::OFFERING);
+ // Publisher ID
+ EXPECT_EQ(message->value.int32Values[1], 123);
+
// Number of layer offerings
- EXPECT_EQ(message->value.int32Values[1], 1);
+ EXPECT_EQ(message->value.int32Values[2], 1);
// Layer
- EXPECT_EQ(message->value.int32Values[2], 1);
- EXPECT_EQ(message->value.int32Values[3], 0);
- EXPECT_EQ(message->value.int32Values[4], 2);
+ EXPECT_EQ(message->value.int32Values[3], 1);
+ EXPECT_EQ(message->value.int32Values[4], 0);
+ EXPECT_EQ(message->value.int32Values[5], 2);
// Number of dependencies
- EXPECT_EQ(message->value.int32Values[5], 0);
+ EXPECT_EQ(message->value.int32Values[6], 0);
}
TEST(VmsUtilsTest, offeringWithDependencies) {
VmsLayer layer(1, 0, 2);
- std::vector<VmsLayer> dependencies = {VmsLayer(2, 0, 2)};
+ std::vector<VmsLayer> dependencies = {VmsLayer(2, 0, 2), VmsLayer(3, 0, 3)};
std::vector<VmsLayerOffering> offering = {VmsLayerOffering(layer, dependencies)};
- auto message = createOfferingMessage(offering);
+ VmsOffers offers = {123, offering};
+ auto message = createOfferingMessage(offers);
ASSERT_NE(message, nullptr);
EXPECT_TRUE(isValidVmsMessage(*message));
EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE));
- EXPECT_EQ(message->value.int32Values.size(), 0x9ul);
+ EXPECT_EQ(message->value.int32Values.size(), 0xdul);
EXPECT_EQ(parseMessageType(*message), VmsMessageType::OFFERING);
+ // Publisher ID
+ EXPECT_EQ(message->value.int32Values[1], 123);
+
// Number of layer offerings
- EXPECT_EQ(message->value.int32Values[1], 1);
+ EXPECT_EQ(message->value.int32Values[2], 1);
// Layer
- EXPECT_EQ(message->value.int32Values[2], 1);
- EXPECT_EQ(message->value.int32Values[3], 0);
- EXPECT_EQ(message->value.int32Values[4], 2);
+ EXPECT_EQ(message->value.int32Values[3], 1);
+ EXPECT_EQ(message->value.int32Values[4], 0);
+ EXPECT_EQ(message->value.int32Values[5], 2);
// Number of dependencies
- EXPECT_EQ(message->value.int32Values[5], 1);
+ EXPECT_EQ(message->value.int32Values[6], 2);
// Dependency 1
- EXPECT_EQ(message->value.int32Values[6], 2);
- EXPECT_EQ(message->value.int32Values[7], 0);
- EXPECT_EQ(message->value.int32Values[8], 2);
+ EXPECT_EQ(message->value.int32Values[7], 2);
+ EXPECT_EQ(message->value.int32Values[8], 0);
+ EXPECT_EQ(message->value.int32Values[9], 2);
+
+ // Dependency 2
+ EXPECT_EQ(message->value.int32Values[10], 3);
+ EXPECT_EQ(message->value.int32Values[11], 0);
+ EXPECT_EQ(message->value.int32Values[12], 3);
}
TEST(VmsUtilsTest, availabilityMessage) {
@@ -166,6 +178,153 @@
EXPECT_TRUE(data_str.empty());
}
+TEST(VmsUtilsTest, publisherIdRequest) {
+ std::string bytes = "pub_id";
+ auto message = createPublisherIdRequest(bytes);
+ ASSERT_NE(message, nullptr);
+ EXPECT_TRUE(isValidVmsMessage(*message));
+ EXPECT_EQ(message->prop, toInt(VehicleProperty::VEHICLE_MAP_SERVICE));
+ EXPECT_EQ(message->value.int32Values.size(), 0x1ul);
+ EXPECT_EQ(parseMessageType(*message), VmsMessageType::PUBLISHER_ID_REQUEST);
+ EXPECT_EQ(message->value.bytes.size(), bytes.size());
+ EXPECT_EQ(memcmp(message->value.bytes.data(), bytes.data(), bytes.size()), 0);
+}
+
+TEST(VmsUtilsTest, validPublisherIdResponse) {
+ auto message = createBaseVmsMessage(2);
+ message->value.int32Values =
+ hidl_vec<int32_t>{toInt(VmsMessageType::PUBLISHER_ID_RESPONSE), 1234};
+ EXPECT_EQ(parsePublisherIdResponse(*message), 1234);
+}
+
+TEST(VmsUtilsTest, invalidPublisherIdResponse) {
+ auto message = createBaseVmsMessage(1);
+ EXPECT_EQ(parsePublisherIdResponse(*message), -1);
+}
+
+TEST(VmsUtilsTest, validSequenceNumberForSubscriptionsState) {
+ auto message = createBaseVmsMessage(2);
+ message->value.int32Values =
+ hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE), 1234};
+ EXPECT_EQ(getSequenceNumberForSubscriptionsState(*message), 1234);
+}
+
+TEST(VmsUtilsTest, invalidSubscriptionsState) {
+ auto message = createBaseVmsMessage(1);
+ EXPECT_EQ(getSequenceNumberForSubscriptionsState(*message), -1);
+}
+
+TEST(VmsUtilsTest, newSequenceNumberForExistingSmallerNumber) {
+ auto message = createBaseVmsMessage(2);
+ message->value.int32Values =
+ hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE), 1234};
+ EXPECT_TRUE(isSequenceNumberNewer(*message, 1233));
+}
+
+TEST(VmsUtilsTest, newSequenceNumberForExistingGreaterNumber) {
+ auto message = createBaseVmsMessage(2);
+ message->value.int32Values =
+ hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE), 1234};
+ EXPECT_FALSE(isSequenceNumberNewer(*message, 1235));
+}
+
+TEST(VmsUtilsTest, newSequenceNumberForSameNumber) {
+ auto message = createBaseVmsMessage(2);
+ message->value.int32Values =
+ hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE), 1234};
+ EXPECT_FALSE(isSequenceNumberNewer(*message, 1234));
+}
+
+TEST(VmsUtilsTest, subscribedLayers) {
+ VmsOffers offers = {123,
+ {VmsLayerOffering(VmsLayer(1, 0, 1), {VmsLayer(4, 1, 1)}),
+ VmsLayerOffering(VmsLayer(2, 0, 1))}};
+ auto message = createBaseVmsMessage(2);
+ message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE),
+ 1234, // sequence number
+ 2, // number of layers
+ 1, // number of associated layers
+ 1, // layer 1
+ 0,
+ 1,
+ 4, // layer 2
+ 1,
+ 1,
+ 2, // associated layer
+ 0,
+ 1,
+ 2, // number of publisher IDs
+ 111, // publisher IDs
+ 123};
+ EXPECT_TRUE(isValidVmsMessage(*message));
+ auto result = getSubscribedLayers(*message, offers);
+ EXPECT_EQ(static_cast<int>(result.size()), 2);
+ EXPECT_EQ(result.at(0), VmsLayer(1, 0, 1));
+ EXPECT_EQ(result.at(1), VmsLayer(2, 0, 1));
+}
+
+TEST(VmsUtilsTest, subscribedLayersWithDifferentSubtype) {
+ VmsOffers offers = {123, {VmsLayerOffering(VmsLayer(1, 0, 1))}};
+ auto message = createBaseVmsMessage(2);
+ message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE),
+ 1234, // sequence number
+ 1, // number of layers
+ 0, // number of associated layers
+ 1, // layer 1
+ 1, // different subtype
+ 1};
+ EXPECT_TRUE(isValidVmsMessage(*message));
+ EXPECT_TRUE(getSubscribedLayers(*message, offers).empty());
+}
+
+TEST(VmsUtilsTest, subscribedLayersWithDifferentVersion) {
+ VmsOffers offers = {123, {VmsLayerOffering(VmsLayer(1, 0, 1))}};
+ auto message = createBaseVmsMessage(2);
+ message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE),
+ 1234, // sequence number
+ 1, // number of layers
+ 0, // number of associated layers
+ 1, // layer 1
+ 0,
+ 2}; // different version
+ EXPECT_TRUE(isValidVmsMessage(*message));
+ EXPECT_TRUE(getSubscribedLayers(*message, offers).empty());
+}
+
+TEST(VmsUtilsTest, subscribedLayersWithDifferentPublisherId) {
+ VmsOffers offers = {123, {VmsLayerOffering(VmsLayer(1, 0, 1))}};
+ auto message = createBaseVmsMessage(2);
+ message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::SUBSCRIPTIONS_CHANGE),
+ 1234, // sequence number
+ 0, // number of layers
+ 1, // number of associated layers
+ 1, // associated layer 1
+ 0,
+ 1,
+ 1, // number of publisher IDs
+ 234}; // publisher ID 1
+ EXPECT_TRUE(isValidVmsMessage(*message));
+ EXPECT_TRUE(getSubscribedLayers(*message, offers).empty());
+}
+
+TEST(VmsUtilsTest, serviceNewlyStarted) {
+ auto message = createBaseVmsMessage(2);
+ message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::AVAILABILITY_CHANGE), 0};
+ EXPECT_TRUE(hasServiceNewlyStarted(*message));
+}
+
+TEST(VmsUtilsTest, serviceNotNewlyStarted) {
+ auto message = createBaseVmsMessage(2);
+ message->value.int32Values =
+ hidl_vec<int32_t>{toInt(VmsMessageType::AVAILABILITY_CHANGE), 1234};
+ EXPECT_FALSE(hasServiceNewlyStarted(*message));
+}
+
+TEST(VmsUtilsTest, invalidAvailabilityChange) {
+ auto message = createBaseVmsMessage(1);
+ EXPECT_FALSE(hasServiceNewlyStarted(*message));
+}
+
} // namespace
} // namespace vms
diff --git a/camera/device/3.4/default/CameraDeviceSession.cpp b/camera/device/3.4/default/CameraDeviceSession.cpp
index e00b3f8..03b6050 100644
--- a/camera/device/3.4/default/CameraDeviceSession.cpp
+++ b/camera/device/3.4/default/CameraDeviceSession.cpp
@@ -187,7 +187,6 @@
mPhysicalCameraIdMap[id] = requestedConfiguration.streams[i].physicalCameraId;
mStreamMap[id].data_space = mapToLegacyDataspace(
mStreamMap[id].data_space);
- mStreamMap[id].physical_camera_id = mPhysicalCameraIdMap[id].c_str();
mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{});
} else {
// width/height/format must not change, but usage/rotation might need to change
@@ -206,6 +205,11 @@
mStreamMap[id].rotation = (int) requestedConfiguration.streams[i].v3_2.rotation;
mStreamMap[id].usage = (uint32_t) requestedConfiguration.streams[i].v3_2.usage;
}
+ // It is possible for the entry in 'mStreamMap' to get initialized by an older
+ // HIDL API. Make sure that the physical id is always initialized when using
+ // a more recent API call.
+ mStreamMap[id].physical_camera_id = mPhysicalCameraIdMap[id].c_str();
+
(*streams)[i] = &mStreamMap[id];
}
diff --git a/camera/device/3.5/types.hal b/camera/device/3.5/types.hal
index f98c603..6d861e2 100644
--- a/camera/device/3.5/types.hal
+++ b/camera/device/3.5/types.hal
@@ -21,6 +21,14 @@
import @3.2::CameraBlobId;
/**
+ * If the result metadata cannot be produced for a physical camera device part of a logical
+ * multi-camera, then HAL must invoke the notification callback and pass a message with ERROR_RESULT
+ * code and errorStreamId that contains the stream id associated with that physical device.
+ * The behavior during absent result metadata remains unchanged for a logical or a non-logical
+ * camera device and the errorStreamId must be set to -1.
+ */
+
+/**
* StreamConfiguration:
*
* Identical to @3.4::StreamConfiguration, except that it contains streamConfigCounter
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index d77bb0e..814b88b 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -767,7 +767,7 @@
const ::android::hardware::camera::common::V1_0::helper::CameraMetadata& metadata);
void verifyStreamCombination(sp<device::V3_5::ICameraDevice> cameraDevice3_5,
const ::android::hardware::camera::device::V3_4::StreamConfiguration &config3_4,
- bool expectedStatus);
+ bool expectedStatus, bool expectStreamCombQuery);
void verifyLogicalCameraResult(const camera_metadata_t* staticMetadata,
const ::android::hardware::camera::common::V1_0::helper::CameraMetadata& resultMetadata);
@@ -1364,19 +1364,20 @@
}
hidl_vec<StreamBuffer> tmpRetBuffers(bufReq.numBuffersRequested);
- for (size_t i = 0; i < bufReq.numBuffersRequested; i++) {
+ for (size_t j = 0; j < bufReq.numBuffersRequested; j++) {
hidl_handle buffer_handle;
mParent->allocateGraphicBuffer(stream.width, stream.height,
android_convertGralloc1To0Usage(
halStream.producerUsage, halStream.consumerUsage),
halStream.overrideFormat, &buffer_handle);
- tmpRetBuffers[i] = {stream.id, mNextBufferId, buffer_handle, BufferStatus::OK,
+ tmpRetBuffers[j] = {stream.id, mNextBufferId, buffer_handle, BufferStatus::OK,
nullptr, nullptr};
mOutstandingBufferIds[idx].insert(std::make_pair(mNextBufferId++, buffer_handle));
}
atLeastOneStreamOk = true;
- bufRets[0].val.buffers(std::move(tmpRetBuffers));
+ bufRets[i].streamId = stream.id;
+ bufRets[i].val.buffers(std::move(tmpRetBuffers));
}
if (allStreamOk) {
@@ -2877,8 +2878,9 @@
createStreamConfiguration(streams3_2, StreamConfigurationMode::NORMAL_MODE,
&config3_2, &config3_4, &config3_5, jpegBufferSize);
if (session3_5 != nullptr) {
+ bool expectStreamCombQuery = (isLogicalMultiCamera(staticMeta) == Status::OK);
verifyStreamCombination(cameraDevice3_5, config3_4,
- /*expectedStatus*/ true);
+ /*expectedStatus*/ true, expectStreamCombQuery);
config3_5.streamConfigCounter = streamConfigCounter++;
ret = session3_5->configureStreams_3_5(config3_5,
[streamId](Status s, device::V3_4::HalStreamConfiguration halConfig) {
@@ -2971,7 +2973,8 @@
createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE,
&config3_2, &config3_4, &config3_5, jpegBufferSize);
if (session3_5 != nullptr) {
- verifyStreamCombination(cameraDevice3_5, config3_4, /*expectedStatus*/ false);
+ verifyStreamCombination(cameraDevice3_5, config3_4, /*expectedStatus*/ false,
+ /*expectStreamCombQuery*/false);
config3_5.streamConfigCounter = streamConfigCounter++;
ret = session3_5->configureStreams_3_5(config3_5,
[](Status s, device::V3_4::HalStreamConfiguration) {
@@ -3232,7 +3235,7 @@
&config3_2, &config3_4, &config3_5, jpegBufferSize);
if (session3_5 != nullptr) {
verifyStreamCombination(cameraDevice3_5, config3_4,
- /*expectedStatus*/ true);
+ /*expectedStatus*/ true, /*expectStreamCombQuery*/ false);
config3_5.streamConfigCounter = streamConfigCounter++;
ret = session3_5->configureStreams_3_5(config3_5,
[](Status s, device::V3_4::HalStreamConfiguration halConfig) {
@@ -3483,7 +3486,7 @@
&config3_2, &config3_4, &config3_5, jpegBufferSize);
if (session3_5 != nullptr) {
verifyStreamCombination(cameraDevice3_5, config3_4,
- /*expectedStatus*/ true);
+ /*expectedStatus*/ true, /*expectStreamCombQuery*/ false);
config3_5.streamConfigCounter = streamConfigCounter++;
ret = session3_5->configureStreams_3_5(config3_5,
[](Status s, device::V3_4::HalStreamConfiguration halConfig) {
@@ -3578,7 +3581,7 @@
&config3_2, &config3_4, &config3_5);
if (session3_5 != nullptr) {
verifyStreamCombination(cameraDevice3_5, config3_4,
- /*expectedStatus*/ true);
+ /*expectedStatus*/ true, /*expectStreamCombQuery*/ false);
config3_5.streamConfigCounter = streamConfigCounter++;
ret = session3_5->configureStreams_3_5(config3_5,
[streamId](Status s, device::V3_4::HalStreamConfiguration halConfig) {
@@ -3811,7 +3814,7 @@
&config3_2, &config3_4, &config3_5, jpegBufferSize);
if (session3_5 != nullptr) {
verifyStreamCombination(cameraDevice3_5, config3_4,
- /*expectedStatus*/ true);
+ /*expectedStatus*/ true, /*expectStreamCombQuery*/ false);
config3_5.streamConfigCounter = streamConfigCounter++;
ret = session3_5->configureStreams_3_5(config3_5,
[](Status s, device::V3_4::HalStreamConfiguration halConfig) {
@@ -5535,11 +5538,12 @@
void CameraHidlTest::verifyStreamCombination(sp<device::V3_5::ICameraDevice> cameraDevice3_5,
const ::android::hardware::camera::device::V3_4::StreamConfiguration &config3_4,
- bool expectedStatus) {
+ bool expectedStatus, bool expectMethodSupported) {
if (cameraDevice3_5.get() != nullptr) {
auto ret = cameraDevice3_5->isStreamCombinationSupported(config3_4,
- [expectedStatus] (Status s, bool combStatus) {
- ASSERT_TRUE((Status::OK == s) || (Status::METHOD_NOT_SUPPORTED == s));
+ [expectedStatus, expectMethodSupported] (Status s, bool combStatus) {
+ ASSERT_TRUE((Status::OK == s) ||
+ (!expectMethodSupported && Status::METHOD_NOT_SUPPORTED == s));
if (Status::OK == s) {
ASSERT_TRUE(combStatus == expectedStatus);
}
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index 566bd48..e48cc79 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -271,7 +271,16 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="false">
+ <hal format="hidl" optional="true">
+ <name>android.hardware.media.c2</name>
+ <version>1.0</version>
+ <interface>
+ <name>IComponentStore</name>
+ <regex-instance>default[0-9]*</regex-instance>
+ <regex-instance>vendor[0-9]*_software</regex-instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
<name>android.hardware.media.omx</name>
<version>1.0</version>
<interface>
@@ -301,7 +310,7 @@
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.nfc</name>
- <version>1.1</version>
+ <version>1.2</version>
<interface>
<name>INfc</name>
<instance>default</instance>
diff --git a/current.txt b/current.txt
index 96c1bbf..fcb8447 100644
--- a/current.txt
+++ b/current.txt
@@ -396,6 +396,8 @@
d702fb01dc2a0733aa820b7eb65435ee3334f75632ef880bafd2fb8803a20a58 android.hardware.gnss@1.0::IGnssMeasurementCallback
7c7721c0f773fcf422b71a4f558545e9e36acc973e58ca51e5bd53905cf46bc0 android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer
d4fea995378bb4f421b4e24ccf68cad2734ab07fe4f874a126ba558b99df5766 android.hardware.graphics.composer@2.1::IComposerClient
+f7d7cb747dc01a9fdb2d39a80003b4d8df9be733d65f5842198802eb6209db69 android.hardware.graphics.mapper@2.0::IMapper
+65a021fa89085b62fc96b2b6d3bef2f9103cf4d63379c68bc154fd9eef672852 android.hardware.health@1.0::types
b7ecf29927055ec422ec44bf776223f07d79ad9f92ccf9becf167e62c2607e7a android.hardware.keymaster@4.0::IKeymasterDevice
574e8f1499436fb4075894dcae0b36682427956ecb114f17f1fe22d116a83c6b android.hardware.neuralnetworks@1.0::IPreparedModel
417ab60fe1ef786778047e4486f3d868ebce570d91addd8fe4251515213072de android.hardware.neuralnetworks@1.0::types
@@ -446,7 +448,7 @@
09ab9b24994429d9bb32a3fb420b6f6be3e47eb655139a2c08c4e80d3f33ff95 android.hardware.camera.device@3.5::ICameraDevice
06237de53c42890029e3f8fe7d1480d078469c0d07608e51c37b4d485d342992 android.hardware.camera.device@3.5::ICameraDeviceCallback
08c68b196e2fc4e5ba67ba0d0917bde828a87cbe2cffec19d04733972da9eb49 android.hardware.camera.device@3.5::ICameraDeviceSession
-a848f7cb3cb3d080cf175bf08412322bfddb535168253796cdf777afdbf05b38 android.hardware.camera.device@3.5::types
+f9b8b388c0c76669e4b9189e4943efd2982f9bda5c10e276f96cc91bc8e818d6 android.hardware.camera.device@3.5::types
f727d5f350f55a6d3354aad2feb64e43200de77c10d9d642465566bc260bb8ec android.hardware.camera.metadata@3.4::types
0fb39a7809ad1c52b3efbbed5ef4749b06c2a4f1f19cdc3efa2e3d9b28f1205c android.hardware.camera.provider@2.5::ICameraProvider
f5777403d65135a5407723671bc7a864cdca83aea13ee3ce2894b95e6588ca3a android.hardware.camera.provider@2.5::types
@@ -467,7 +469,7 @@
4deafcdcffa2d002119e7f58810b767a84666e76475aae68e757ec2845d9756d android.hardware.gnss@2.0::IGnss
db6bdf6dfc5edf6c85d2944976db899227abb51079c893874353c322342c50b6 android.hardware.gnss@2.0::IGnssBatching
1f89392f1ebb693d8fa6f50324b1635fc79fab246d31900e63998e1b0e17511c android.hardware.gnss@2.0::IGnssBatchingCallback
-b11a5e4a1602d3f408716b6fe2c578a79f060d571aad8e828f9a4426d161fbcf android.hardware.gnss@2.0::IGnssCallback
+64232037109a5e5f53ab0377e755ec494ae93fcb5279e6eea71dec2e7ac6fbfc android.hardware.gnss@2.0::IGnssCallback
ecc966c68bddbd95c8dae782b84204cf01c75734675e8769963f3b5106ec128b android.hardware.gnss@2.0::IGnssConfiguration
b670bae2ab8517336290532e364502b4db9120340d75474ccc8442b1b15d6ab7 android.hardware.gnss@2.0::IGnssDebug
c67759f5d6387d273b66729180d03690e827f0b6b8d4e13ce2ff42d31b224065 android.hardware.gnss@2.0::IGnssMeasurement
@@ -512,7 +514,7 @@
92714960d1a53fc2ec557302b41c7cc93d2636d8364a44bd0f85be0c92927ff8 android.hardware.neuralnetworks@1.2::IExecutionCallback
36e1064c869965dee533c537cefbe87e54db8bd8cd45be7e0e93e00e8a43863a android.hardware.neuralnetworks@1.2::IPreparedModel
e1c734d1545e1a4ae749ff1dd9704a8e594c59aea7c8363159dc258e93e0df3b android.hardware.neuralnetworks@1.2::IPreparedModelCallback
-209a5ee694b94328afb2af2768f1fe6a69148e2cbb85ec3c340a36eed818c697 android.hardware.neuralnetworks@1.2::types
+9b3963253e521cca19fd81aeca83aee6dcfe3bdf2805c07cb2d3f64381709b71 android.hardware.neuralnetworks@1.2::types
cf7a4ba516a638f9b82a249c91fb603042c2d9ca43fd5aad9cf6c0401ed2a5d7 android.hardware.nfc@1.2::INfc
abf98c2ae08bf765db54edc8068e36d52eb558cff6706b6fd7c18c65a1f3fc18 android.hardware.nfc@1.2::types
4cb252dc6372a874aef666b92a6e9529915aa187521a700f0789065c3c702ead android.hardware.power.stats@1.0::IPowerStats
diff --git a/gnss/2.0/IGnssCallback.hal b/gnss/2.0/IGnssCallback.hal
index a96fd6c..d6db9cc 100644
--- a/gnss/2.0/IGnssCallback.hal
+++ b/gnss/2.0/IGnssCallback.hal
@@ -30,32 +30,13 @@
/** Flags for the gnssSetCapabilities callback. */
@export(name="", value_prefix="GPS_CAPABILITY_")
- enum Capabilities : uint32_t {
- /**
- * GNSS HAL schedules fixes for RECURRENCE_PERIODIC mode.
- * If this is not set, then the framework will use 1000ms for
- * minInterval and must call start() and stop() to schedule the GNSS.
- */
- SCHEDULING = 1 << 0,
- /** GNSS supports MS-Based AGNSS mode */
- MSB = 1 << 1,
- /** GNSS supports MS-Assisted AGNSS mode */
- MSA = 1 << 2,
- /** GNSS supports single-shot fixes */
- SINGLE_SHOT = 1 << 3,
- /** GNSS supports on demand time injection */
- ON_DEMAND_TIME = 1 << 4,
- /**
- * Values for the flags removed from IGnssCallback.hal@1.0 Capabilities
- * enum are marked as reserved and not reused here to avoid confusion.
- */
- RESERVED_1 = 1 << 5,
- RESERVED_2 = 1 << 6,
- RESERVED_3 = 1 << 7,
+ enum Capabilities : @1.0::IGnssCallback.Capabilities {
/** GNSS supports low power mode */
- LOW_POWER_MODE = 1 << 8,
+ LOW_POWER_MODE = 1 << 8,
/** GNSS supports blacklisting satellites */
- SATELLITE_BLACKLIST = 1 << 9
+ SATELLITE_BLACKLIST = 1 << 9,
+ /** GNSS supports measurement corrections */
+ MEASUREMENT_CORRECTIONS = 1 << 10
};
/**
diff --git a/gnss/2.0/default/Gnss.cpp b/gnss/2.0/default/Gnss.cpp
index 75c2385..3d64fc3 100644
--- a/gnss/2.0/default/Gnss.cpp
+++ b/gnss/2.0/default/Gnss.cpp
@@ -280,7 +280,8 @@
sGnssCallback_2_0 = callback;
using Capabilities = V2_0::IGnssCallback::Capabilities;
- const auto capabilities = Capabilities::LOW_POWER_MODE | Capabilities::SATELLITE_BLACKLIST;
+ const auto capabilities = Capabilities::MEASUREMENTS | Capabilities::MEASUREMENT_CORRECTIONS |
+ Capabilities::LOW_POWER_MODE | Capabilities::SATELLITE_BLACKLIST;
auto ret = sGnssCallback_2_0->gnssSetCapabilitiesCb_2_0(capabilities);
if (!ret.isOk()) {
ALOGE("%s: Unable to invoke callback", __func__);
diff --git a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
index 0682f84..be182a9 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
@@ -289,19 +289,21 @@
/*
* TestGnssMeasurementCorrectionsCapabilities:
- * If the GnssMeasurementCorrectionsExtension is not null, verifies that the measurement corrections
+ * If measurement corrections capability is supported, verifies that the measurement corrections
* capabilities are reported and the mandatory LOS_SATS or the EXCESS_PATH_LENGTH
* capability flag is set.
*/
TEST_F(GnssHalTest, TestGnssMeasurementCorrectionsCapabilities) {
- // Setup measurement corrections callback.
- auto measurementCorrections = gnss_hal_->getExtensionMeasurementCorrections();
- ASSERT_TRUE(measurementCorrections.isOk());
- sp<IMeasurementCorrections> iMeasurementCorrections = measurementCorrections;
- if (iMeasurementCorrections == nullptr) {
+ if (!(last_capabilities_ & IGnssCallback::Capabilities::MEASUREMENT_CORRECTIONS)) {
return;
}
+ auto measurementCorrections = gnss_hal_->getExtensionMeasurementCorrections();
+ ASSERT_TRUE(measurementCorrections.isOk());
+ sp<IMeasurementCorrections> iMeasurementCorrections = measurementCorrections;
+ ASSERT_NE(iMeasurementCorrections, nullptr);
+
+ // Setup measurement corrections callback.
sp<IMeasurementCorrectionsCallback> iMeasurementCorrectionsCallback =
new GnssMeasurementCorrectionsCallback(*this);
iMeasurementCorrections->setCallback(iMeasurementCorrectionsCallback);
@@ -316,17 +318,19 @@
/*
* TestGnssMeasurementCorrections:
- * If the GnssMeasurementCorrectionsExtension is not null, verifies that it supports the
+ * If measurement corrections capability is supported, verifies that it supports the
* gnss.measurement_corrections@1.0::IMeasurementCorrections interface by invoking a method.
*/
TEST_F(GnssHalTest, TestGnssMeasurementCorrections) {
+ if (!(last_capabilities_ & IGnssCallback::Capabilities::MEASUREMENT_CORRECTIONS)) {
+ return;
+ }
+
// Verify IMeasurementCorrections is supported.
auto measurementCorrections = gnss_hal_->getExtensionMeasurementCorrections();
ASSERT_TRUE(measurementCorrections.isOk());
sp<IMeasurementCorrections> iMeasurementCorrections = measurementCorrections;
- if (iMeasurementCorrections == nullptr) {
- return;
- }
+ ASSERT_NE(iMeasurementCorrections, nullptr);
sp<IMeasurementCorrectionsCallback> iMeasurementCorrectionsCallback =
new GnssMeasurementCorrectionsCallback(*this);
diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h
index 1df496c..18d184e 100644
--- a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h
+++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h
@@ -44,7 +44,7 @@
if (mMapper3) {
return true;
}
- ALOGW_IF(!mMapper3, "failed to get mapper 3.0 service");
+ ALOGD_IF(!mMapper3, "failed to get mapper 3.0 service, falling back to mapper 2.0");
mMapper2 = mapper::V2_0::IMapper::getService();
ALOGE_IF(!mMapper2, "failed to get mapper 2.0 service");
diff --git a/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h b/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h
index 436e461..5826b12 100644
--- a/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h
+++ b/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h
@@ -162,6 +162,7 @@
Error destroyLayer(Display display, Layer layer) override {
int32_t err = mDispatch.destroyLayer(mDevice, display, layer);
+ onLayerDestroyed(display, layer);
return static_cast<Error>(err);
}
@@ -327,6 +328,7 @@
std::vector<IComposerClient::Composition>* outCompositionTypes,
uint32_t* outDisplayRequestMask, std::vector<Layer>* outRequestedLayers,
std::vector<uint32_t>* outRequestMasks) override {
+ onBeforeValidateDisplay(display);
uint32_t typesCount = 0;
uint32_t reqsCount = 0;
int32_t err = mDispatch.validateDisplay(mDevice, display, &typesCount, &reqsCount);
@@ -335,17 +337,15 @@
return static_cast<Error>(err);
}
- err = mDispatch.getChangedCompositionTypes(mDevice, display, &typesCount, nullptr, nullptr);
+ err = getChangedCompositionTypes(display, &typesCount, nullptr, nullptr);
if (err != HWC2_ERROR_NONE) {
return static_cast<Error>(err);
}
std::vector<Layer> changedLayers(typesCount);
std::vector<IComposerClient::Composition> compositionTypes(typesCount);
- err = mDispatch.getChangedCompositionTypes(
- mDevice, display, &typesCount, changedLayers.data(),
- reinterpret_cast<std::underlying_type<IComposerClient::Composition>::type*>(
- compositionTypes.data()));
+ err = getChangedCompositionTypes(display, &typesCount, changedLayers.data(),
+ compositionTypes.data());
if (err != HWC2_ERROR_NONE) {
return static_cast<Error>(err);
}
@@ -578,6 +578,15 @@
return true;
}
+ virtual int32_t getChangedCompositionTypes(Display display, uint32_t* outTypesCount,
+ Layer* outChangedLayers,
+ IComposerClient::Composition* outCompositionTypes) {
+ return getChangedCompositionTypesInternal(display, outTypesCount, outChangedLayers,
+ outCompositionTypes);
+ }
+ virtual void onLayerDestroyed(Display /* display */, Layer /* layer */) {}
+ virtual void onBeforeValidateDisplay(Display /* display */) {}
+
static void hotplugHook(hwc2_callback_data_t callbackData, hwc2_display_t display,
int32_t connected) {
auto hal = static_cast<HwcHalImpl*>(callbackData);
@@ -596,6 +605,15 @@
hal->mEventCallback->onVsync(display, timestamp);
}
+ int32_t getChangedCompositionTypesInternal(Display display, uint32_t* outTypesCount,
+ Layer* outChangedLayers,
+ IComposerClient::Composition* outCompositionTypes) {
+ return mDispatch.getChangedCompositionTypes(
+ mDevice, display, outTypesCount, outChangedLayers,
+ reinterpret_cast<std::underlying_type<IComposerClient::Composition>::type*>(
+ outCompositionTypes));
+ }
+
hwc2_device_t* mDevice = nullptr;
std::unordered_set<hwc2_capability_t> mCapabilities;
diff --git a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
index 070cf80..e2bed95 100644
--- a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
+++ b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
@@ -42,6 +42,20 @@
using V2_1::Display;
using V2_1::Error;
+namespace {
+
+bool isIdentityMatrix(const float* matrix) {
+ if (matrix[0] == 1.0 && matrix[1] == 0.0 && matrix[2] == 0.0 && matrix[3] == 0.0 &&
+ matrix[4] == 0.0 && matrix[5] == 1.0 && matrix[6] == 0.0 && matrix[7] == 0.0 &&
+ matrix[8] == 0.0 && matrix[9] == 0.0 && matrix[10] == 1.0 && matrix[11] == 0.0 &&
+ matrix[12] == 0.0 && matrix[13] == 0.0 && matrix[14] == 0.0 && matrix[15] == 1.0) {
+ return true;
+ }
+ return false;
+}
+
+} // namespace
+
// HwcHalImpl implements V2_*::hal::ComposerHal on top of hwcomposer2
template <typename Hal>
class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl<Hal> {
@@ -130,6 +144,16 @@
Error setLayerColorTransform(Display display, Layer layer, const float* matrix) override {
if (!mDispatch.setLayerColorTransform) {
+ if (isIdentityMatrix(matrix)) {
+ // If an identity matrix is set, then we can remove the layer from client
+ // composition list.
+ mClientCompositionLayers[display].erase(layer);
+ return Error::UNSUPPORTED;
+ }
+ // if setLayerColorTransform is not implemented, per spec we want to make sure the
+ // layer marked as client composition, and thus we maintain a list, and mark all these
+ // layers as client composition later before validate the display.
+ mClientCompositionLayers[display].insert(layer);
return Error::UNSUPPORTED;
}
int32_t err = mDispatch.setLayerColorTransform(mDevice, display, layer, matrix);
@@ -294,7 +318,79 @@
return true;
}
- private:
+ int32_t getChangedCompositionTypes(Display display, uint32_t* outTypesCount,
+ Layer* outChangedLayers,
+ IComposerClient::Composition* outCompositionTypes) override {
+ if (outChangedLayers == nullptr && outCompositionTypes == nullptr) {
+ uint32_t typesCount = 0;
+ int32_t error = BaseType2_1::getChangedCompositionTypesInternal(display, &typesCount,
+ nullptr, nullptr);
+ if (error != HWC2_ERROR_NONE) {
+ return error;
+ }
+ mChangedLayersCache[display].resize(typesCount);
+ mCompositionTypesCache[display].resize(typesCount);
+ error = BaseType2_1::getChangedCompositionTypesInternal(
+ display, &typesCount, mChangedLayersCache[display].data(),
+ mCompositionTypesCache[display].data());
+ if (error != HWC2_ERROR_NONE) {
+ return error;
+ }
+ for (Layer layer : mClientCompositionLayers[display]) {
+ bool exist = false;
+ for (uint32_t i = 0; i < typesCount; ++i) {
+ if (mChangedLayersCache[display][i] == layer) {
+ exist = true;
+ break;
+ }
+ }
+ if (!exist) {
+ mChangedLayersCache[display].push_back(layer);
+ mCompositionTypesCache[display].push_back(IComposerClient::Composition::CLIENT);
+ }
+ }
+ *outTypesCount = mChangedLayersCache[display].size();
+ return error;
+ }
+ for (uint32_t i = 0; i < *outTypesCount; ++i) {
+ if (outChangedLayers != nullptr) {
+ outChangedLayers[i] = mChangedLayersCache[display][i];
+ }
+ if (outCompositionTypes != nullptr) {
+ outCompositionTypes[i] = mCompositionTypesCache[display][i];
+ }
+ }
+ return HWC2_ERROR_NONE;
+ }
+
+ void onLayerDestroyed(Display display, Layer layer) override {
+ if (mClientCompositionLayers.find(display) == mClientCompositionLayers.end()) {
+ return;
+ }
+ mClientCompositionLayers[display].erase(layer);
+ }
+
+ void onBeforeValidateDisplay(Display display) override {
+ if (mClientCompositionLayers.find(display) == mClientCompositionLayers.end()) {
+ return;
+ }
+
+ // clear the cache proactively so that we don't hold too much memory over time.
+ mChangedLayersCache[display].clear();
+ mCompositionTypesCache[display].clear();
+
+ // SET_LAYER_COLOR_TRANSFORM is optional, and thus if it's not implemented, we need to
+ // follow the spec to make sure those layers marked as client composition before validate
+ // the display.
+ if (!mDispatch.setLayerColorTransform) {
+ for (Layer layer : mClientCompositionLayers[display]) {
+ BaseType2_1::setLayerCompositionType(
+ display, layer, static_cast<int32_t>(IComposerClient::Composition::CLIENT));
+ }
+ }
+ }
+
+ private:
struct {
HWC2_PFN_GET_DISPLAY_IDENTIFICATION_DATA getDisplayIdentificationData;
HWC2_PFN_SET_LAYER_COLOR_TRANSFORM setLayerColorTransform;
@@ -318,6 +414,9 @@
using BaseType2_2::getRenderIntents;
using BaseType2_2::setColorMode_2_2;
using BaseType2_2::setLayerPerFrameMetadata;
+ std::map<Display, std::set<Layer>> mClientCompositionLayers;
+ std::map<Display, std::vector<Layer>> mChangedLayersCache;
+ std::map<Display, std::vector<IComposerClient::Composition>> mCompositionTypesCache;
};
} // namespace detail
diff --git a/graphics/mapper/2.0/IMapper.hal b/graphics/mapper/2.0/IMapper.hal
index 4566135..0e18f42 100644
--- a/graphics/mapper/2.0/IMapper.hal
+++ b/graphics/mapper/2.0/IMapper.hal
@@ -147,6 +147,9 @@
* outside of accessRegion is undefined, except that it must not cause
* process termination.
*
+ * An accessRegion of all-zeros means the entire buffer. That is, it is
+ * equivalent to '(0,0)-(buffer width, buffer height)'.
+ *
* data will be filled with a pointer to the locked buffer memory. This
* address will represent the top-left corner of the entire buffer, even
* if accessRegion does not begin at the top-left corner.
diff --git a/health/1.0/types.hal b/health/1.0/types.hal
index 377d1bd..90b8bb1 100644
--- a/health/1.0/types.hal
+++ b/health/1.0/types.hal
@@ -190,7 +190,13 @@
/** Remaining battery capacity in percent */
int32_t batteryLevel;
- /** Instantaneous battery voltage in uV */
+ /**
+ * Instantaneous battery voltage in millivolts (mV).
+ *
+ * Historically, the unit of this field is microvolts (uV), but all
+ * clients and implementations uses millivolts in practice, making it
+ * the de-facto standard.
+ */
int32_t batteryVoltage;
/** Instantaneous battery temperature in tenths of degree celcius */
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
index 106f332..c819b52 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
@@ -125,9 +125,9 @@
ADD_FAILURE() << "asking for burst execution at V1_0";
return nullptr;
}
-static std::unique_ptr<::android::nn::ExecutionBurstController> CreateBurst(
+static std::shared_ptr<::android::nn::ExecutionBurstController> CreateBurst(
const sp<V1_2::IPreparedModel>& preparedModel) {
- return ::android::nn::createExecutionBurstController(preparedModel, /*blocking=*/true);
+ return ::android::nn::ExecutionBurstController::create(preparedModel, /*blocking=*/true);
}
enum class Executor { ASYNC, SYNC, BURST };
enum class OutputType { FULLY_SPECIFIED, UNSPECIFIED, INSUFFICIENT };
@@ -286,7 +286,7 @@
SCOPED_TRACE("burst");
// create burst
- const std::unique_ptr<::android::nn::ExecutionBurstController> controller =
+ const std::shared_ptr<::android::nn::ExecutionBurstController> controller =
CreateBurst(preparedModel);
ASSERT_NE(nullptr, controller.get());
diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal
index 8c57796..67a61c1 100644
--- a/neuralnetworks/1.2/types.hal
+++ b/neuralnetworks/1.2/types.hal
@@ -1188,8 +1188,11 @@
* value if the recurrent projection layer exists, and should otherwise
* have no value.
* * (API level >= 29) The four layer normalization weights either all have
- * values or none of them have values. Layer normalization is used when
- * values are present.
+ * values or none of them have values. Additionally, if CIFG is used,
+ * input layer normalization weights tensor is omitted and the other layer
+ * normalization weights either all have values or none of them have
+ * values. Layer normalization is used when the values of all the layer
+ * normalization weights are present.
*
* References:
*
diff --git a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
index b15f657..870d017 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
@@ -155,8 +155,8 @@
SCOPED_TRACE(message + " [burst]");
// create burst
- std::unique_ptr<::android::nn::ExecutionBurstController> burst =
- ::android::nn::createExecutionBurstController(preparedModel, /*blocking=*/true);
+ std::shared_ptr<::android::nn::ExecutionBurstController> burst =
+ ::android::nn::ExecutionBurstController::create(preparedModel, /*blocking=*/true);
ASSERT_NE(nullptr, burst.get());
// create memory keys
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
index 76d8758..2093c25 100644
--- a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
@@ -758,3 +758,40 @@
{RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE}));
}
}
+
+/*
+ * Test IRadio.getDataRegistrationStateResponse_1_4() for the response returned.
+ */
+TEST_F(RadioHidlTest_v1_4, getDataRegistrationState_1_4) {
+ int rat;
+ serial = GetRandomSerialNumber();
+
+ Return<void> res = radio_v1_4->getDataRegistrationState(serial);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_4->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_v1_4->rspInfo.serial);
+
+ ALOGI("getDataRegistrationStateResponse_1_4, rspInfo.error = %s\n",
+ toString(radioRsp_v1_4->rspInfo.error).c_str());
+
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_4->rspInfo.error,
+ {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::NOT_PROVISIONED}));
+
+ rat = radioRsp_v1_4->dataRegResp.base.rat;
+ /*
+ * - Expect Valid vopsinfo when device is on LTE
+ * - Expect empty vopsInfo when device is not on LTE
+ */
+ if (rat == ((int )::android::hardware::radio::V1_4::RadioTechnology::LTE)
+ || (rat == (int )::android::hardware::radio::V1_4::RadioTechnology::LTE_CA)) {
+
+ EXPECT_EQ(::android::hardware::radio::V1_4::DataRegStateResult::VopsInfo::hidl_discriminator
+ ::lteVopsInfo, radioRsp_v1_4->dataRegResp.vopsInfo.getDiscriminator());
+ } else {
+
+ EXPECT_EQ(::android::hardware::radio::V1_4::DataRegStateResult::VopsInfo::hidl_discriminator
+ ::noinit, radioRsp_v1_4->dataRegResp.vopsInfo.getDiscriminator());
+ }
+}
diff --git a/sensors/2.0/default/Android.bp b/sensors/2.0/default/Android.bp
index d05634b..05a34bb 100644
--- a/sensors/2.0/default/Android.bp
+++ b/sensors/2.0/default/Android.bp
@@ -23,7 +23,7 @@
"Sensor.cpp",
"Sensors.cpp",
],
- init_rc: ["android.hardware.sensors@2.0-service.rc"],
+ init_rc: ["android.hardware.sensors@2.0-service-mock.rc"],
shared_libs: [
"android.hardware.sensors@1.0",
"android.hardware.sensors@2.0",
diff --git a/sensors/2.0/default/android.hardware.sensors@2.0-service.rc b/sensors/2.0/default/android.hardware.sensors@2.0-service-mock.rc
similarity index 100%
rename from sensors/2.0/default/android.hardware.sensors@2.0-service.rc
rename to sensors/2.0/default/android.hardware.sensors@2.0-service-mock.rc
diff --git a/wifi/1.3/default/tests/mock_wifi_legacy_hal.h b/wifi/1.3/default/tests/mock_wifi_legacy_hal.h
index 65fd115..53fa8d6 100644
--- a/wifi/1.3/default/tests/mock_wifi_legacy_hal.h
+++ b/wifi/1.3/default/tests/mock_wifi_legacy_hal.h
@@ -43,6 +43,12 @@
const std::string& iface_name));
MOCK_METHOD1(getDriverVersion, std::pair<wifi_error, std::string>(
const std::string& iface_name));
+
+ MOCK_METHOD2(selectTxPowerScenario,
+ wifi_error(const std::string& iface_name,
+ wifi_power_scenario scenario));
+ MOCK_METHOD1(resetTxPowerScenario,
+ wifi_error(const std::string& iface_name));
MOCK_METHOD2(nanRegisterCallbackHandlers,
wifi_error(const std::string&, const NanCallbackHandlers&));
MOCK_METHOD2(nanDisableRequest,
diff --git a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
index 134563c..7928328 100644
--- a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
+++ b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
@@ -122,7 +122,7 @@
void setup_MultiIfaceCombination() {
// clang-format off
const hidl_vec<V1_0::IWifiChip::ChipIfaceCombination> combinations = {
- {{{{IfaceType::STA}, 3}}}
+ {{{{IfaceType::STA}, 3}, {{IfaceType::AP}, 1}}}
};
const std::vector<V1_0::IWifiChip::ChipMode> modes = {
{feature_flags::chip_mode_ids::kV3, combinations}
@@ -261,6 +261,17 @@
return success;
}
+ sp<WifiChip> chip_;
+ ChipId chip_id_ = kFakeChipId;
+ std::shared_ptr<NiceMock<legacy_hal::MockWifiLegacyHal>> legacy_hal_{
+ new NiceMock<legacy_hal::MockWifiLegacyHal>};
+ std::shared_ptr<NiceMock<mode_controller::MockWifiModeController>>
+ mode_controller_{new NiceMock<mode_controller::MockWifiModeController>};
+ std::shared_ptr<NiceMock<iface_util::MockWifiIfaceUtil>> iface_util_{
+ new NiceMock<iface_util::MockWifiIfaceUtil>};
+ std::shared_ptr<NiceMock<feature_flags::MockWifiFeatureFlags>>
+ feature_flags_{new NiceMock<feature_flags::MockWifiFeatureFlags>};
+
public:
void SetUp() override {
chip_ = new WifiChip(chip_id_, legacy_hal_, mode_controller_,
@@ -272,17 +283,12 @@
.WillRepeatedly(testing::Return(legacy_hal::WIFI_SUCCESS));
}
- private:
- sp<WifiChip> chip_;
- ChipId chip_id_ = kFakeChipId;
- std::shared_ptr<NiceMock<legacy_hal::MockWifiLegacyHal>> legacy_hal_{
- new NiceMock<legacy_hal::MockWifiLegacyHal>};
- std::shared_ptr<NiceMock<mode_controller::MockWifiModeController>>
- mode_controller_{new NiceMock<mode_controller::MockWifiModeController>};
- std::shared_ptr<NiceMock<iface_util::MockWifiIfaceUtil>> iface_util_{
- new NiceMock<iface_util::MockWifiIfaceUtil>};
- std::shared_ptr<NiceMock<feature_flags::MockWifiFeatureFlags>>
- feature_flags_{new NiceMock<feature_flags::MockWifiFeatureFlags>};
+ void TearDown() override {
+ // Restore default system iface names (This should ideally be using a
+ // mock).
+ property_set("wifi.interface", "wlan0");
+ property_set("wifi.concurrent.interface", "wlan1");
+ }
};
////////// V1 Iface Combinations ////////////
@@ -300,7 +306,7 @@
TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateSta_ShouldSucceed) {
findModeAndConfigureForIfaceType(IfaceType::STA);
- ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
}
TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateP2p_ShouldSucceed) {
@@ -326,7 +332,7 @@
TEST_F(WifiChipV1IfaceCombinationTest, ApMode_CreateAp_ShouldSucceed) {
findModeAndConfigureForIfaceType(IfaceType::AP);
- ASSERT_FALSE(createIface(IfaceType::AP).empty());
+ ASSERT_EQ(createIface(IfaceType::AP), "wlan0");
}
TEST_F(WifiChipV1IfaceCombinationTest, ApMode_CreateSta_ShouldFail) {
@@ -359,7 +365,7 @@
TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateSta_ShouldSucceed) {
findModeAndConfigureForIfaceType(IfaceType::STA);
- ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
}
TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateP2p_ShouldSucceed) {
@@ -427,7 +433,7 @@
TEST_F(WifiChipV1_AwareIfaceCombinationTest, ApMode_CreateAp_ShouldSucceed) {
findModeAndConfigureForIfaceType(IfaceType::AP);
- ASSERT_FALSE(createIface(IfaceType::AP).empty());
+ ASSERT_EQ(createIface(IfaceType::AP), "wlan0");
}
TEST_F(WifiChipV1_AwareIfaceCombinationTest, ApMode_CreateSta_ShouldFail) {
@@ -445,18 +451,18 @@
ASSERT_TRUE(createIface(IfaceType::NAN).empty());
}
-TEST_F(WifiChipV1IfaceCombinationTest, RttControllerFlowStaModeNoSta) {
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, RttControllerFlowStaModeNoSta) {
findModeAndConfigureForIfaceType(IfaceType::STA);
ASSERT_TRUE(createRttController());
}
-TEST_F(WifiChipV1IfaceCombinationTest, RttControllerFlowStaModeWithSta) {
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, RttControllerFlowStaModeWithSta) {
findModeAndConfigureForIfaceType(IfaceType::STA);
ASSERT_FALSE(createIface(IfaceType::STA).empty());
ASSERT_TRUE(createRttController());
}
-TEST_F(WifiChipV1IfaceCombinationTest, RttControllerFlowApToSta) {
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, RttControllerFlowApToSta) {
findModeAndConfigureForIfaceType(IfaceType::AP);
const auto ap_iface_name = createIface(IfaceType::AP);
ASSERT_FALSE(ap_iface_name.empty());
@@ -468,6 +474,30 @@
ASSERT_TRUE(createRttController());
}
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, SelectTxScenarioWithOnlySta) {
+ findModeAndConfigureForIfaceType(IfaceType::STA);
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+ EXPECT_CALL(*legacy_hal_, selectTxPowerScenario("wlan0", testing::_))
+ .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
+ chip_->selectTxPowerScenario_1_2(
+ V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF,
+ [](const WifiStatus& status) {
+ ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+ });
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, SelectTxScenarioWithOnlyAp) {
+ findModeAndConfigureForIfaceType(IfaceType::AP);
+ ASSERT_EQ(createIface(IfaceType::AP), "wlan0");
+ EXPECT_CALL(*legacy_hal_, selectTxPowerScenario("wlan0", testing::_))
+ .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
+ chip_->selectTxPowerScenario_1_2(
+ V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF,
+ [](const WifiStatus& status) {
+ ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+ });
+}
+
////////// V2 + Aware Iface Combinations ////////////
// Mode 1 - STA + STA/AP
// - STA + P2P/NAN
@@ -483,7 +513,7 @@
TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateSta_ShouldSucceed) {
findModeAndConfigureForIfaceType(IfaceType::STA);
- ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
}
TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateP2p_ShouldSucceed) {
@@ -498,19 +528,25 @@
TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateAp_ShouldSucceed) {
findModeAndConfigureForIfaceType(IfaceType::STA);
- ASSERT_FALSE(createIface(IfaceType::AP).empty());
+ ASSERT_EQ(createIface(IfaceType::AP), "wlan1");
}
TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaSta_ShouldFail) {
findModeAndConfigureForIfaceType(IfaceType::AP);
- ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
ASSERT_TRUE(createIface(IfaceType::STA).empty());
}
TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaAp_ShouldSucceed) {
findModeAndConfigureForIfaceType(IfaceType::AP);
- ASSERT_FALSE(createIface(IfaceType::AP).empty());
- ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+ ASSERT_EQ(createIface(IfaceType::AP), "wlan1");
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateApSta_ShouldSucceed) {
+ findModeAndConfigureForIfaceType(IfaceType::AP);
+ ASSERT_EQ(createIface(IfaceType::AP), "wlan1");
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
}
TEST_F(WifiChipV2_AwareIfaceCombinationTest,
@@ -640,6 +676,30 @@
ASSERT_TRUE(createRttController());
}
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, SelectTxScenarioWithOnlySta) {
+ findModeAndConfigureForIfaceType(IfaceType::STA);
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+ EXPECT_CALL(*legacy_hal_, selectTxPowerScenario("wlan0", testing::_))
+ .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
+ chip_->selectTxPowerScenario_1_2(
+ V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF,
+ [](const WifiStatus& status) {
+ ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+ });
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, SelectTxScenarioWithOnlyAp) {
+ findModeAndConfigureForIfaceType(IfaceType::AP);
+ ASSERT_EQ(createIface(IfaceType::AP), "wlan1");
+ EXPECT_CALL(*legacy_hal_, selectTxPowerScenario("wlan1", testing::_))
+ .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
+ chip_->selectTxPowerScenario_1_2(
+ V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF,
+ [](const WifiStatus& status) {
+ ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+ });
+}
+
////////// V1 Iface Combinations when AP creation is disabled //////////
class WifiChipV1_AwareDisabledApIfaceCombinationTest : public WifiChipTest {
public:
@@ -707,8 +767,8 @@
property_set("wifi.interface", "bad0");
property_set("wifi.concurrent.interface", "bad1");
findModeAndConfigureForIfaceType(IfaceType::STA);
- ASSERT_EQ(createIface(IfaceType::STA), "test0");
- ASSERT_EQ(createIface(IfaceType::STA), "test1");
+ ASSERT_EQ(createIface(IfaceType::STA), "bad0");
+ ASSERT_EQ(createIface(IfaceType::STA), "bad1");
ASSERT_EQ(createIface(IfaceType::STA), "test2");
}
@@ -724,6 +784,16 @@
ASSERT_EQ(createIface(IfaceType::STA), "wlan2");
}
+TEST_F(WifiChip_MultiIfaceTest, CreateApStartsWithIdx1) {
+ findModeAndConfigureForIfaceType(IfaceType::STA);
+ // First AP will be slotted to wlan1.
+ ASSERT_EQ(createIface(IfaceType::AP), "wlan1");
+ // First STA will be slotted to wlan0.
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+ // All further STA will be slotted to the remaining free indices.
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan2");
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan3");
+}
} // namespace implementation
} // namespace V1_3
} // namespace wifi
diff --git a/wifi/1.3/default/wifi_chip.cpp b/wifi/1.3/default/wifi_chip.cpp
index 3697d50..25eb289 100644
--- a/wifi/1.3/default/wifi_chip.cpp
+++ b/wifi/1.3/default/wifi_chip.cpp
@@ -41,7 +41,9 @@
constexpr uint32_t kMaxRingBufferFileAgeSeconds = 60 * 60 * 10;
constexpr uint32_t kMaxRingBufferFileNum = 20;
constexpr char kTombstoneFolderPath[] = "/data/vendor/tombstones/wifi/";
-constexpr unsigned kMaxWlanIfaces = 100;
+constexpr char kActiveWlanIfaceNameProperty[] = "wifi.active.interface";
+constexpr char kNoActiveWlanIfaceNamePropertyValue[] = "";
+constexpr unsigned kMaxWlanIfaces = 5;
template <typename Iface>
void invalidateAndClear(std::vector<sp<Iface>>& ifaces, sp<Iface> iface) {
@@ -105,6 +107,13 @@
return buffer.data();
}
+void setActiveWlanIfaceNameProperty(const std::string& ifname) {
+ auto res = property_set(kActiveWlanIfaceNameProperty, ifname.data());
+ if (res != 0) {
+ PLOG(ERROR) << "Failed to set active wlan iface name property";
+ }
+}
+
// delete files that meet either conditions:
// 1. older than a predefined time in the wifi tombstone dir.
// 2. Files in excess to a predefined amount, starting from the oldest ones
@@ -316,13 +325,16 @@
is_valid_(true),
current_mode_id_(feature_flags::chip_mode_ids::kInvalid),
modes_(feature_flags.lock()->getChipModes()),
- debug_ring_buffer_cb_registered_(false) {}
+ debug_ring_buffer_cb_registered_(false) {
+ setActiveWlanIfaceNameProperty(kNoActiveWlanIfaceNamePropertyValue);
+}
void WifiChip::invalidate() {
if (!writeRingbufferFilesInternal()) {
LOG(ERROR) << "Error writing files to flash";
}
invalidateAndRemoveAllIfaces();
+ setActiveWlanIfaceNameProperty(kNoActiveWlanIfaceNamePropertyValue);
legacy_hal_.reset();
event_cb_handler_.invalidate();
is_valid_ = false;
@@ -641,7 +653,7 @@
legacy_hal::wifi_error legacy_status;
uint32_t legacy_feature_set;
uint32_t legacy_logger_feature_set;
- const auto ifname = getWlanIfaceName(0);
+ const auto ifname = getFirstActiveWlanIfaceName();
std::tie(legacy_status, legacy_feature_set) =
legacy_hal_.lock()->getSupportedFeatureSet(ifname);
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
@@ -693,6 +705,7 @@
}
current_mode_id_ = mode_id;
LOG(INFO) << "Configured chip in mode " << mode_id;
+ setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
return status;
}
@@ -709,7 +722,7 @@
IWifiChip::ChipDebugInfo result;
legacy_hal::wifi_error legacy_status;
std::string driver_desc;
- const auto ifname = getWlanIfaceName(0);
+ const auto ifname = getFirstActiveWlanIfaceName();
std::tie(legacy_status, driver_desc) =
legacy_hal_.lock()->getDriverVersion(ifname);
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
@@ -741,7 +754,8 @@
legacy_hal::wifi_error legacy_status;
std::vector<uint8_t> driver_dump;
std::tie(legacy_status, driver_dump) =
- legacy_hal_.lock()->requestDriverMemoryDump(getWlanIfaceName(0));
+ legacy_hal_.lock()->requestDriverMemoryDump(
+ getFirstActiveWlanIfaceName());
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
LOG(ERROR) << "Failed to get driver debug dump: "
<< legacyErrorToString(legacy_status);
@@ -756,7 +770,8 @@
legacy_hal::wifi_error legacy_status;
std::vector<uint8_t> firmware_dump;
std::tie(legacy_status, firmware_dump) =
- legacy_hal_.lock()->requestFirmwareMemoryDump(getWlanIfaceName(0));
+ legacy_hal_.lock()->requestFirmwareMemoryDump(
+ getFirstActiveWlanIfaceName());
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
LOG(ERROR) << "Failed to get firmware debug dump: "
<< legacyErrorToString(legacy_status);
@@ -766,10 +781,10 @@
}
std::pair<WifiStatus, sp<IWifiApIface>> WifiChip::createApIfaceInternal() {
- if (!canCurrentModeSupportIfaceOfType(IfaceType::AP)) {
+ if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::AP)) {
return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
}
- std::string ifname = allocateApOrStaIfaceName();
+ std::string ifname = allocateApIfaceName();
sp<WifiApIface> iface =
new WifiApIface(ifname, legacy_hal_, iface_util_, feature_flags_);
ap_ifaces_.push_back(iface);
@@ -778,6 +793,7 @@
LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
}
}
+ setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
}
@@ -809,15 +825,16 @@
LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
}
}
+ setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
return createWifiStatus(WifiStatusCode::SUCCESS);
}
std::pair<WifiStatus, sp<IWifiNanIface>> WifiChip::createNanIfaceInternal() {
- if (!canCurrentModeSupportIfaceOfType(IfaceType::NAN)) {
+ if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::NAN)) {
return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
}
// These are still assumed to be based on wlan0.
- std::string ifname = getWlanIfaceName(0);
+ std::string ifname = getFirstActiveWlanIfaceName();
sp<WifiNanIface> iface = new WifiNanIface(ifname, legacy_hal_);
nan_ifaces_.push_back(iface);
for (const auto& callback : event_cb_handler_.getCallbacks()) {
@@ -860,7 +877,7 @@
}
std::pair<WifiStatus, sp<IWifiP2pIface>> WifiChip::createP2pIfaceInternal() {
- if (!canCurrentModeSupportIfaceOfType(IfaceType::P2P)) {
+ if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::P2P)) {
return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
}
std::string ifname = getP2pIfaceName();
@@ -906,10 +923,10 @@
}
std::pair<WifiStatus, sp<IWifiStaIface>> WifiChip::createStaIfaceInternal() {
- if (!canCurrentModeSupportIfaceOfType(IfaceType::STA)) {
+ if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::STA)) {
return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
}
- std::string ifname = allocateApOrStaIfaceName();
+ std::string ifname = allocateStaIfaceName();
sp<WifiStaIface> iface = new WifiStaIface(ifname, legacy_hal_, iface_util_);
sta_ifaces_.push_back(iface);
for (const auto& callback : event_cb_handler_.getCallbacks()) {
@@ -917,6 +934,7 @@
LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
}
}
+ setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
}
@@ -948,6 +966,7 @@
LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
}
}
+ setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
return createWifiStatus(WifiStatusCode::SUCCESS);
}
@@ -959,8 +978,8 @@
"(and RTT by extension)";
return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
}
- sp<WifiRttController> rtt =
- new WifiRttController(getWlanIfaceName(0), bound_iface, legacy_hal_);
+ sp<WifiRttController> rtt = new WifiRttController(
+ getFirstActiveWlanIfaceName(), bound_iface, legacy_hal_);
rtt_controllers_.emplace_back(rtt);
return {createWifiStatus(WifiStatusCode::SUCCESS), rtt};
}
@@ -971,7 +990,7 @@
std::vector<legacy_hal::wifi_ring_buffer_status>
legacy_ring_buffer_status_vec;
std::tie(legacy_status, legacy_ring_buffer_status_vec) =
- legacy_hal_.lock()->getRingBuffersStatus(getWlanIfaceName(0));
+ legacy_hal_.lock()->getRingBuffersStatus(getFirstActiveWlanIfaceName());
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
return {createWifiStatusFromLegacyError(legacy_status), {}};
}
@@ -993,7 +1012,7 @@
}
legacy_hal::wifi_error legacy_status =
legacy_hal_.lock()->startRingBufferLogging(
- getWlanIfaceName(0), ring_name,
+ getFirstActiveWlanIfaceName(), ring_name,
static_cast<
std::underlying_type<WifiDebugRingBufferVerboseLevel>::type>(
verbose_level),
@@ -1010,7 +1029,8 @@
return status;
}
legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->getRingBufferData(getWlanIfaceName(0), ring_name);
+ legacy_hal_.lock()->getRingBufferData(getFirstActiveWlanIfaceName(),
+ ring_name);
return createWifiStatusFromLegacyError(legacy_status);
}
@@ -1026,7 +1046,7 @@
WifiStatus WifiChip::stopLoggingToDebugRingBufferInternal() {
legacy_hal::wifi_error legacy_status =
legacy_hal_.lock()->deregisterRingBufferCallbackHandler(
- getWlanIfaceName(0));
+ getFirstActiveWlanIfaceName());
return createWifiStatusFromLegacyError(legacy_status);
}
@@ -1035,7 +1055,7 @@
legacy_hal::wifi_error legacy_status;
legacy_hal::WakeReasonStats legacy_stats;
std::tie(legacy_status, legacy_stats) =
- legacy_hal_.lock()->getWakeReasonStats(getWlanIfaceName(0));
+ legacy_hal_.lock()->getWakeReasonStats(getFirstActiveWlanIfaceName());
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
return {createWifiStatusFromLegacyError(legacy_status), {}};
}
@@ -1067,10 +1087,10 @@
}
};
legacy_status = legacy_hal_.lock()->registerErrorAlertCallbackHandler(
- getWlanIfaceName(0), on_alert_callback);
+ getFirstActiveWlanIfaceName(), on_alert_callback);
} else {
legacy_status = legacy_hal_.lock()->deregisterErrorAlertCallbackHandler(
- getWlanIfaceName(0));
+ getFirstActiveWlanIfaceName());
}
return createWifiStatusFromLegacyError(legacy_status);
}
@@ -1078,20 +1098,20 @@
WifiStatus WifiChip::selectTxPowerScenarioInternal(
V1_1::IWifiChip::TxPowerScenario scenario) {
auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario(
- getWlanIfaceName(0),
+ getFirstActiveWlanIfaceName(),
hidl_struct_util::convertHidlTxPowerScenarioToLegacy(scenario));
return createWifiStatusFromLegacyError(legacy_status);
}
WifiStatus WifiChip::resetTxPowerScenarioInternal() {
auto legacy_status =
- legacy_hal_.lock()->resetTxPowerScenario(getWlanIfaceName(0));
+ legacy_hal_.lock()->resetTxPowerScenario(getFirstActiveWlanIfaceName());
return createWifiStatusFromLegacyError(legacy_status);
}
WifiStatus WifiChip::setLatencyModeInternal(LatencyMode mode) {
auto legacy_status = legacy_hal_.lock()->setLatencyMode(
- getWlanIfaceName(0),
+ getFirstActiveWlanIfaceName(),
hidl_struct_util::convertHidlLatencyModeToLegacy(mode));
return createWifiStatusFromLegacyError(legacy_status);
}
@@ -1107,7 +1127,7 @@
WifiStatus WifiChip::selectTxPowerScenarioInternal_1_2(
TxPowerScenario scenario) {
auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario(
- getWlanIfaceName(0),
+ getFirstActiveWlanIfaceName(),
hidl_struct_util::convertHidlTxPowerScenarioToLegacy_1_2(scenario));
return createWifiStatusFromLegacyError(legacy_status);
}
@@ -1197,7 +1217,7 @@
};
legacy_hal::wifi_error legacy_status =
legacy_hal_.lock()->registerRingBufferCallbackHandler(
- getWlanIfaceName(0), on_ring_buffer_data_callback);
+ getFirstActiveWlanIfaceName(), on_ring_buffer_data_callback);
if (legacy_status == legacy_hal::WIFI_SUCCESS) {
debug_ring_buffer_cb_registered_ = true;
@@ -1231,7 +1251,7 @@
};
legacy_hal::wifi_error legacy_status =
legacy_hal_.lock()->registerRadioModeChangeCallbackHandler(
- getWlanIfaceName(0), on_radio_mode_change_callback);
+ getFirstActiveWlanIfaceName(), on_radio_mode_change_callback);
return createWifiStatusFromLegacyError(legacy_status);
}
@@ -1298,8 +1318,9 @@
return expanded_combos;
}
-bool WifiChip::canExpandedIfaceCombinationSupportIfaceOfType(
- const std::map<IfaceType, size_t>& combo, IfaceType requested_type) {
+bool WifiChip::canExpandedIfaceComboSupportIfaceOfTypeWithCurrentIfaces(
+ const std::map<IfaceType, size_t>& expanded_combo,
+ IfaceType requested_type) {
const auto current_combo = getCurrentIfaceCombination();
// Check if we have space for 1 more iface of |type| in this combo
@@ -1309,7 +1330,7 @@
if (type == requested_type) {
num_ifaces_needed++;
}
- size_t num_ifaces_allowed = combo.at(type);
+ size_t num_ifaces_allowed = expanded_combo.at(type);
if (num_ifaces_needed > num_ifaces_allowed) {
return false;
}
@@ -1320,8 +1341,10 @@
// This method does the following:
// a) Enumerate all possible iface combos by expanding the current
// ChipIfaceCombination.
-// b) Check if the requested iface type can be added to the current mode.
-bool WifiChip::canCurrentModeSupportIfaceOfType(IfaceType type) {
+// b) Check if the requested iface type can be added to the current mode
+// with the iface combination that is already active.
+bool WifiChip::canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(
+ IfaceType requested_type) {
if (!isValidModeId(current_mode_id_)) {
LOG(ERROR) << "Chip not configured in a mode yet";
return false;
@@ -1330,8 +1353,8 @@
for (const auto& combination : combinations) {
const auto expanded_combos = expandIfaceCombinations(combination);
for (const auto& expanded_combo : expanded_combos) {
- if (canExpandedIfaceCombinationSupportIfaceOfType(expanded_combo,
- type)) {
+ if (canExpandedIfaceComboSupportIfaceOfTypeWithCurrentIfaces(
+ expanded_combo, requested_type)) {
return true;
}
}
@@ -1339,6 +1362,62 @@
return false;
}
+// Note: This does not consider ifaces already active. It only checks if the
+// provided expanded iface combination can support the requested combo.
+bool WifiChip::canExpandedIfaceComboSupportIfaceCombo(
+ const std::map<IfaceType, size_t>& expanded_combo,
+ const std::map<IfaceType, size_t>& req_combo) {
+ // Check if we have space for 1 more iface of |type| in this combo
+ for (const auto type :
+ {IfaceType::AP, IfaceType::NAN, IfaceType::P2P, IfaceType::STA}) {
+ if (req_combo.count(type) == 0) {
+ // Iface of "type" not in the req_combo.
+ continue;
+ }
+ size_t num_ifaces_needed = req_combo.at(type);
+ size_t num_ifaces_allowed = expanded_combo.at(type);
+ if (num_ifaces_needed > num_ifaces_allowed) {
+ return false;
+ }
+ }
+ return true;
+}
+// This method does the following:
+// a) Enumerate all possible iface combos by expanding the current
+// ChipIfaceCombination.
+// b) Check if the requested iface combo can be added to the current mode.
+// Note: This does not consider ifaces already active. It only checks if the
+// current mode can support the requested combo.
+bool WifiChip::canCurrentModeSupportIfaceCombo(
+ const std::map<IfaceType, size_t>& req_combo) {
+ if (!isValidModeId(current_mode_id_)) {
+ LOG(ERROR) << "Chip not configured in a mode yet";
+ return false;
+ }
+ const auto combinations = getCurrentModeIfaceCombinations();
+ for (const auto& combination : combinations) {
+ const auto expanded_combos = expandIfaceCombinations(combination);
+ for (const auto& expanded_combo : expanded_combos) {
+ if (canExpandedIfaceComboSupportIfaceCombo(expanded_combo,
+ req_combo)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+// This method does the following:
+// a) Enumerate all possible iface combos by expanding the current
+// ChipIfaceCombination.
+// b) Check if the requested iface type can be added to the current mode.
+bool WifiChip::canCurrentModeSupportIfaceOfType(IfaceType requested_type) {
+ // Check if we can support atleast 1 iface of type.
+ std::map<IfaceType, size_t> req_iface_combo;
+ req_iface_combo[requested_type] = 1;
+ return canCurrentModeSupportIfaceCombo(req_iface_combo);
+}
+
bool WifiChip::isValidModeId(ChipModeId mode_id) {
for (const auto& mode : modes_) {
if (mode.id == mode_id) {
@@ -1348,11 +1427,32 @@
return false;
}
-// Return the first wlan (wlan0, wlan1 etc.) not already in use.
-// This doesn't check the actual presence of these interfaces.
-std::string WifiChip::allocateApOrStaIfaceName() {
- for (unsigned i = 0; i < kMaxWlanIfaces; i++) {
- const auto ifname = getWlanIfaceName(i);
+bool WifiChip::isStaApConcurrencyAllowedInCurrentMode() {
+ // Check if we can support atleast 1 STA & 1 AP concurrently.
+ std::map<IfaceType, size_t> req_iface_combo;
+ req_iface_combo[IfaceType::AP] = 1;
+ req_iface_combo[IfaceType::STA] = 1;
+ return canCurrentModeSupportIfaceCombo(req_iface_combo);
+}
+
+std::string WifiChip::getFirstActiveWlanIfaceName() {
+ for (unsigned idx = 0; idx < kMaxWlanIfaces; idx++) {
+ const auto ifname = getWlanIfaceName(idx);
+ if (findUsingName(sta_ifaces_, ifname)) return ifname;
+ if (findUsingName(ap_ifaces_, ifname)) return ifname;
+ }
+ // This could happen if the chip call is made before any STA/AP
+ // iface is created. Default to wlan0 for such cases.
+ LOG(WARNING) << "No active wlan interfaces in use!";
+ return getWlanIfaceName(0);
+}
+
+// Return the first wlan (wlan0, wlan1 etc.) starting from |start_idx|
+// not already in use.
+// Note: This doesn't check the actual presence of these interfaces.
+std::string WifiChip::allocateApOrStaIfaceName(uint32_t start_idx) {
+ for (unsigned idx = start_idx; idx < kMaxWlanIfaces; idx++) {
+ const auto ifname = getWlanIfaceName(idx);
if (findUsingName(ap_ifaces_, ifname)) continue;
if (findUsingName(sta_ifaces_, ifname)) continue;
return ifname;
@@ -1362,6 +1462,19 @@
return {};
}
+// AP iface names start with idx 1 for modes supporting
+// concurrent STA, else start with idx 0.
+std::string WifiChip::allocateApIfaceName() {
+ return allocateApOrStaIfaceName(
+ isStaApConcurrencyAllowedInCurrentMode() ? 1 : 0);
+}
+
+// STA iface names start with idx 0.
+// Primary STA iface will always be 0.
+std::string WifiChip::allocateStaIfaceName() {
+ return allocateApOrStaIfaceName(0);
+}
+
bool WifiChip::writeRingbufferFilesInternal() {
if (!removeOldFilesInternal()) {
LOG(ERROR) << "Error occurred while deleting old tombstone files";
diff --git a/wifi/1.3/default/wifi_chip.h b/wifi/1.3/default/wifi_chip.h
index 3eb0aee..3d12f4c 100644
--- a/wifi/1.3/default/wifi_chip.h
+++ b/wifi/1.3/default/wifi_chip.h
@@ -224,11 +224,23 @@
std::map<IfaceType, size_t> getCurrentIfaceCombination();
std::vector<std::map<IfaceType, size_t>> expandIfaceCombinations(
const IWifiChip::ChipIfaceCombination& combination);
- bool canExpandedIfaceCombinationSupportIfaceOfType(
- const std::map<IfaceType, size_t>& combo, IfaceType type);
- bool canCurrentModeSupportIfaceOfType(IfaceType type);
+ bool canExpandedIfaceComboSupportIfaceOfTypeWithCurrentIfaces(
+ const std::map<IfaceType, size_t>& expanded_combo,
+ IfaceType requested_type);
+ bool canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(
+ IfaceType requested_type);
+ bool canExpandedIfaceComboSupportIfaceCombo(
+ const std::map<IfaceType, size_t>& expanded_combo,
+ const std::map<IfaceType, size_t>& req_combo);
+ bool canCurrentModeSupportIfaceCombo(
+ const std::map<IfaceType, size_t>& req_combo);
+ bool canCurrentModeSupportIfaceOfType(IfaceType requested_type);
bool isValidModeId(ChipModeId mode_id);
- std::string allocateApOrStaIfaceName();
+ bool isStaApConcurrencyAllowedInCurrentMode();
+ std::string getFirstActiveWlanIfaceName();
+ std::string allocateApOrStaIfaceName(uint32_t start_idx);
+ std::string allocateApIfaceName();
+ std::string allocateStaIfaceName();
bool writeRingbufferFilesInternal();
ChipId chip_id_;
diff --git a/wifi/1.3/default/wifi_legacy_hal.cpp b/wifi/1.3/default/wifi_legacy_hal.cpp
index 5aa98c4..7f9b635 100644
--- a/wifi/1.3/default/wifi_legacy_hal.cpp
+++ b/wifi/1.3/default/wifi_legacy_hal.cpp
@@ -777,7 +777,7 @@
}
wifi_error WifiLegacyHal::startSendingOffloadedPacket(
- const std::string& iface_name, uint32_t cmd_id,
+ const std::string& iface_name, uint32_t cmd_id, uint16_t ether_type,
const std::vector<uint8_t>& ip_packet_data,
const std::array<uint8_t, 6>& src_address,
const std::array<uint8_t, 6>& dst_address, uint32_t period_in_ms) {
@@ -787,9 +787,9 @@
std::vector<uint8_t> dst_address_internal(
dst_address.data(), dst_address.data() + dst_address.size());
return global_func_table_.wifi_start_sending_offloaded_packet(
- cmd_id, getIfaceHandle(iface_name), ip_packet_data_internal.data(),
- ip_packet_data_internal.size(), src_address_internal.data(),
- dst_address_internal.data(), period_in_ms);
+ cmd_id, getIfaceHandle(iface_name), ether_type,
+ ip_packet_data_internal.data(), ip_packet_data_internal.size(),
+ src_address_internal.data(), dst_address_internal.data(), period_in_ms);
}
wifi_error WifiLegacyHal::stopSendingOffloadedPacket(
diff --git a/wifi/1.3/default/wifi_legacy_hal.h b/wifi/1.3/default/wifi_legacy_hal.h
index 4d6beb3..a3ed460 100644
--- a/wifi/1.3/default/wifi_legacy_hal.h
+++ b/wifi/1.3/default/wifi_legacy_hal.h
@@ -246,7 +246,7 @@
fw_roaming_state_t state);
wifi_error configureNdOffload(const std::string& iface_name, bool enable);
wifi_error startSendingOffloadedPacket(
- const std::string& iface_name, uint32_t cmd_id,
+ const std::string& iface_name, uint32_t cmd_id, uint16_t ether_type,
const std::vector<uint8_t>& ip_packet_data,
const std::array<uint8_t, 6>& src_address,
const std::array<uint8_t, 6>& dst_address, uint32_t period_in_ms);
@@ -254,9 +254,9 @@
uint32_t cmd_id);
wifi_error setScanningMacOui(const std::string& iface_name,
const std::array<uint8_t, 3>& oui);
- wifi_error selectTxPowerScenario(const std::string& iface_name,
- wifi_power_scenario scenario);
- wifi_error resetTxPowerScenario(const std::string& iface_name);
+ virtual wifi_error selectTxPowerScenario(const std::string& iface_name,
+ wifi_power_scenario scenario);
+ virtual wifi_error resetTxPowerScenario(const std::string& iface_name);
wifi_error setLatencyMode(const std::string& iface_name,
wifi_latency_mode mode);
// Logger/debug functions.
diff --git a/wifi/1.3/default/wifi_sta_iface.cpp b/wifi/1.3/default/wifi_sta_iface.cpp
index 17f3e3d..a6539e5 100644
--- a/wifi/1.3/default/wifi_sta_iface.cpp
+++ b/wifi/1.3/default/wifi_sta_iface.cpp
@@ -562,12 +562,12 @@
WifiStatus WifiStaIface::startSendingKeepAlivePacketsInternal(
uint32_t cmd_id, const std::vector<uint8_t>& ip_packet_data,
- uint16_t /* ether_type */, const std::array<uint8_t, 6>& src_address,
+ uint16_t ether_type, const std::array<uint8_t, 6>& src_address,
const std::array<uint8_t, 6>& dst_address, uint32_t period_in_ms) {
legacy_hal::wifi_error legacy_status =
legacy_hal_.lock()->startSendingOffloadedPacket(
- ifname_, cmd_id, ip_packet_data, src_address, dst_address,
- period_in_ms);
+ ifname_, cmd_id, ether_type, ip_packet_data, src_address,
+ dst_address, period_in_ms);
return createWifiStatusFromLegacyError(legacy_status);
}