Merge "Fix a bug in VUR VTS test." into main
diff --git a/audio/aidl/default/spatializer/SpatializerSw.cpp b/audio/aidl/default/spatializer/SpatializerSw.cpp
index ef86ddb..ab4a53e 100644
--- a/audio/aidl/default/spatializer/SpatializerSw.cpp
+++ b/audio/aidl/default/spatializer/SpatializerSw.cpp
@@ -65,8 +65,6 @@
const std::string SpatializerSw::kEffectName = "SpatializerSw";
const std::vector<Range::SpatializerRange> SpatializerSw::kRanges = {
- MAKE_RANGE(Spatializer, supportedChannelLayout, std::vector<AudioChannelLayout>{},
- std::vector<AudioChannelLayout>{}),
MAKE_RANGE(Spatializer, spatializationLevel, Spatialization::Level::NONE,
Spatialization::Level::BED_PLUS_OBJECTS),
MAKE_RANGE(Spatializer, spatializationMode, Spatialization::Mode::BINAURAL,
@@ -175,11 +173,19 @@
if (mParamsMap.find(tag) != mParamsMap.end()) {
return mParamsMap.at(tag);
}
+ if (tag == Spatializer::supportedChannelLayout) {
+ return Spatializer::make<Spatializer::supportedChannelLayout>(
+ {AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
+ AudioChannelLayout::LAYOUT_5POINT1)});
+ }
return std::nullopt;
}
template <typename TAG>
ndk::ScopedAStatus SpatializerSwContext::setParam(TAG tag, Spatializer spatializer) {
+ RETURN_IF(tag == Spatializer::supportedChannelLayout, EX_ILLEGAL_ARGUMENT,
+ "supportedChannelLayoutGetOnly");
+
mParamsMap[tag] = spatializer;
return ndk::ScopedAStatus::ok();
}
diff --git a/graphics/composer/aidl/vts/ReadbackVts.cpp b/graphics/composer/aidl/vts/ReadbackVts.cpp
index c72ec69..283b8ce 100644
--- a/graphics/composer/aidl/vts/ReadbackVts.cpp
+++ b/graphics/composer/aidl/vts/ReadbackVts.cpp
@@ -67,8 +67,9 @@
case ColorMode::DISPLAY_P3:
return Dataspace::DISPLAY_P3;
case ColorMode::SRGB:
+ return Dataspace::SRGB;
default:
- return common::Dataspace::UNKNOWN;
+ return Dataspace::UNKNOWN;
}
}
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
index 3f82925..d4ce3ba 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
@@ -522,6 +522,83 @@
}
}
+TEST_P(GraphicsCompositionTest, MixedColorSpaces) {
+ ASSERT_TRUE(
+ mComposerClient->setClientTargetSlotCount(getPrimaryDisplayId(), kClientTargetSlotCount)
+ .isOk());
+ const auto& [status, properties] = mComposerClient->getOverlaySupport();
+ if (!status.isOk() && status.getExceptionCode() == EX_SERVICE_SPECIFIC &&
+ status.getServiceSpecificError() == IComposerClient::EX_UNSUPPORTED) {
+ GTEST_SUCCEED() << "getOverlaySupport is not supported";
+ return;
+ }
+
+ if (properties.supportMixedColorSpaces == false) {
+ GTEST_SUCCEED() << "supportMixedColorSpaces is not supported";
+ return;
+ }
+
+ for (ColorMode mode : mTestColorModes) {
+ EXPECT_TRUE(mComposerClient
+ ->setColorMode(getPrimaryDisplayId(), mode, RenderIntent::COLORIMETRIC)
+ .isOk());
+
+ bool isSupported;
+ ASSERT_NO_FATAL_FAILURE(isSupported = getHasReadbackBuffer());
+ if (!isSupported) {
+ GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+ return;
+ }
+
+ // sRGB layer
+ auto srgbLayer = std::make_shared<TestBufferLayer>(
+ mComposerClient, *mTestRenderEngine, getPrimaryDisplayId(), getDisplayWidth(),
+ getDisplayHeight() / 2, PixelFormat::RGBA_8888, *mWriter);
+ std::vector<Color> sRgbDeviceColors(srgbLayer->getWidth() * srgbLayer->getHeight());
+ ReadbackHelper::fillColorsArea(sRgbDeviceColors, getDisplayWidth(),
+ {0, 0, static_cast<int32_t>(srgbLayer->getWidth()),
+ static_cast<int32_t>(srgbLayer->getHeight())},
+ GREEN);
+ srgbLayer->setDisplayFrame({0, 0, static_cast<int32_t>(srgbLayer->getWidth()),
+ static_cast<int32_t>(srgbLayer->getHeight())});
+ srgbLayer->setZOrder(10);
+ srgbLayer->setDataspace(Dataspace::SRGB);
+ ASSERT_NO_FATAL_FAILURE(srgbLayer->setBuffer(sRgbDeviceColors));
+
+ // display P3 layer
+ auto displayP3Layer = std::make_shared<TestBufferLayer>(
+ mComposerClient, *mTestRenderEngine, getPrimaryDisplayId(), getDisplayWidth(),
+ getDisplayHeight() / 2, PixelFormat::RGBA_8888, *mWriter);
+ std::vector<Color> displayP3DeviceColors(
+ static_cast<size_t>(displayP3Layer->getWidth() * displayP3Layer->getHeight()));
+ ReadbackHelper::fillColorsArea(displayP3DeviceColors, getDisplayWidth(),
+ {0, 0, static_cast<int32_t>(displayP3Layer->getWidth()),
+ static_cast<int32_t>(displayP3Layer->getHeight())},
+ RED);
+ displayP3Layer->setDisplayFrame(
+ {0, getDisplayHeight() / 2, getDisplayWidth(), getDisplayHeight()});
+ displayP3Layer->setZOrder(10);
+ displayP3Layer->setDataspace(Dataspace::DISPLAY_P3);
+ ASSERT_NO_FATAL_FAILURE(displayP3Layer->setBuffer(displayP3DeviceColors));
+
+ writeLayers({srgbLayer, displayP3Layer});
+
+ mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp,
+ VtsComposerClient::kNoFrameIntervalNs);
+ execute();
+
+ auto changedCompositionTypes = mReader.takeChangedCompositionTypes(getPrimaryDisplayId());
+ ASSERT_TRUE(changedCompositionTypes.empty());
+
+ mWriter->presentDisplay(getPrimaryDisplayId());
+ execute();
+
+ changedCompositionTypes = mReader.takeChangedCompositionTypes(getPrimaryDisplayId());
+ ASSERT_TRUE(changedCompositionTypes.empty());
+ ASSERT_TRUE(mReader.takeErrors().empty());
+ }
+}
+
TEST_P(GraphicsCompositionTest, DeviceAndClientComposition) {
ASSERT_TRUE(
mComposerClient->setClientTargetSlotCount(getPrimaryDisplayId(), kClientTargetSlotCount)
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index a8f41c3..9575183 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -1086,6 +1086,7 @@
};
for (auto notBefore : test_vector_not_before_millis) {
uint64_t notAfter = notBefore + 378691200000 /* 12 years milliseconds*/;
+ SCOPED_TRACE(testing::Message() << "notBefore: " << notBefore << " notAfter: " << notAfter);
ASSERT_EQ(ErrorCode::OK,
GenerateKey(AuthorizationSetBuilder()
.RsaSigningKey(2048, 65537)
@@ -1101,14 +1102,14 @@
const ASN1_TIME* not_before = X509_get0_notBefore(cert.get());
ASSERT_NE(not_before, nullptr);
- time_t not_before_time;
- ASSERT_EQ(ASN1_TIME_to_time_t(not_before, ¬_before_time), 1);
+ int64_t not_before_time;
+ ASSERT_EQ(ASN1_TIME_to_posix(not_before, ¬_before_time), 1);
EXPECT_EQ(not_before_time, (notBefore / 1000));
const ASN1_TIME* not_after = X509_get0_notAfter(cert.get());
ASSERT_NE(not_after, nullptr);
- time_t not_after_time;
- ASSERT_EQ(ASN1_TIME_to_time_t(not_after, ¬_after_time), 1);
+ int64_t not_after_time;
+ ASSERT_EQ(ASN1_TIME_to_posix(not_after, ¬_after_time), 1);
EXPECT_EQ(not_after_time, (notAfter / 1000));
}
}
diff --git a/security/secretkeeper/aidl/vts/Android.bp b/security/secretkeeper/aidl/vts/Android.bp
index e6521ae..b9ce5ce 100644
--- a/security/secretkeeper/aidl/vts/Android.bp
+++ b/security/secretkeeper/aidl/vts/Android.bp
@@ -47,6 +47,7 @@
"android.hardware.security.secretkeeper-V1-rust",
"libauthgraph_boringssl",
"libauthgraph_core",
+ "libauthgraph_wire",
"libauthgraph_vts_test",
"libbinder_rs",
"libciborium",
diff --git a/security/secretkeeper/aidl/vts/secretkeeper_cli.rs b/security/secretkeeper/aidl/vts/secretkeeper_cli.rs
index d02bfe6..377ed37 100644
--- a/security/secretkeeper/aidl/vts/secretkeeper_cli.rs
+++ b/security/secretkeeper/aidl/vts/secretkeeper_cli.rs
@@ -120,7 +120,7 @@
fn new(instance: &str, dice_artifacts: OwnedDiceArtifactsWithExplicitKey) -> Self {
let sk: binder::Strong<dyn ISecretkeeper> =
binder::get_interface(&format!("{SECRETKEEPER_SERVICE}/{instance}")).unwrap();
- let session = SkSession::new(sk.clone(), &dice_artifacts).unwrap();
+ let session = SkSession::new(sk.clone(), &dice_artifacts, None).unwrap();
Self { sk, session, dice_artifacts }
}
diff --git a/security/secretkeeper/aidl/vts/secretkeeper_test_client.rs b/security/secretkeeper/aidl/vts/secretkeeper_test_client.rs
index 72d3e57..7c00aa9 100644
--- a/security/secretkeeper/aidl/vts/secretkeeper_test_client.rs
+++ b/security/secretkeeper/aidl/vts/secretkeeper_test_client.rs
@@ -19,11 +19,11 @@
use authgraph_vts_test as ag_vts;
use authgraph_boringssl as boring;
use authgraph_core::key;
-use coset::{CborSerializable, CoseEncrypt0};
+use coset::{CborOrdering, CborSerializable, CoseEncrypt0, CoseKey};
use dice_policy_builder::{CertIndex, ConstraintSpec, ConstraintType, MissingAction, WILDCARD_FULL_ARRAY, policy_for_dice_chain};
use rdroidtest::{ignore_if, rdroidtest};
use secretkeeper_client::dice::OwnedDiceArtifactsWithExplicitKey;
-use secretkeeper_client::SkSession;
+use secretkeeper_client::{SkSession, Error as SkClientError};
use secretkeeper_core::cipher;
use secretkeeper_comm::data_types::error::SecretkeeperError;
use secretkeeper_comm::data_types::request::Request;
@@ -38,9 +38,14 @@
SUBCOMPONENT_DESCRIPTORS, SUBCOMPONENT_SECURITY_VERSION,
dice_sample::make_explicit_owned_dice
};
+use std::fs;
+use std::path::Path;
const SECRETKEEPER_SERVICE: &str = "android.hardware.security.secretkeeper.ISecretkeeper";
const CURRENT_VERSION: u64 = 1;
+const SECRETKEEPER_KEY_HOST_DT: &str =
+ "/proc/device-tree/avf/reference/avf/secretkeeper_public_key";
+
// Random bytes (of ID_SIZE/SECRET_SIZE) generated for tests.
const ID_EXAMPLE: Id = Id([
0xF1, 0xB2, 0xED, 0x3B, 0xD1, 0xBD, 0xF0, 0x7D, 0xE1, 0xF0, 0x01, 0xFC, 0x61, 0x71, 0xD3, 0x42,
@@ -65,6 +70,22 @@
0x06, 0xAC, 0x36, 0x8B, 0x3C, 0x95, 0x50, 0x16, 0x67, 0x71, 0x65, 0x26, 0xEB, 0xD0, 0xC3, 0x98,
]);
+// Android expects the public key of Secretkeeper instance to be present in the Linux device tree.
+// This allows clients to (cryptographically) verify that they are indeed talking to the real
+// secretkeeper.
+// Note that this is the identity of the `default` instance (and not `nonsecure`)!
+fn get_secretkeeper_identity() -> Option<CoseKey> {
+ let path = Path::new(SECRETKEEPER_KEY_HOST_DT);
+ if path.exists() {
+ let key = fs::read(path).unwrap();
+ let mut key = CoseKey::from_slice(&key).unwrap();
+ key.canonicalize(CborOrdering::Lexicographic);
+ Some(key)
+ } else {
+ None
+ }
+}
+
fn get_instances() -> Vec<(String, String)> {
// Determine which instances are available.
binder::get_declared_instances(SECRETKEEPER_SERVICE)
@@ -80,6 +101,7 @@
}
/// Secretkeeper client information.
+#[derive(Debug)]
struct SkClient {
sk: binder::Strong<dyn ISecretkeeper>,
session: SkSession,
@@ -95,19 +117,40 @@
impl SkClient {
/// Create an `SkClient` using the default `OwnedDiceArtifactsWithExplicitKey` for identity.
- fn new(instance: &str) -> Self {
+ fn new(instance: &str) -> Result<Self, SkClientError> {
let default_dice = make_explicit_owned_dice(/*Security version in a node */ 5);
- Self::with_identity(instance, default_dice)
+ Self::create(instance, default_dice, None)
}
- /// Create an `SkClient` using the given `OwnedDiceArtifactsWithExplicitKey` for identity.
- fn with_identity(instance: &str, dice_artifacts: OwnedDiceArtifactsWithExplicitKey) -> Self {
+ /// Create an `SkClient` using given `OwnedDiceArtifactsWithExplicitKey` as client identity.
+ fn with_identity(
+ instance: &str,
+ dice_artifacts: OwnedDiceArtifactsWithExplicitKey,
+ ) -> Result<Self, SkClientError> {
+ Self::create(instance, dice_artifacts, None)
+ }
+
+ /// Create an `SkClient` with default client identity, requiring Secretkeeper's identity to be
+ /// matched against given `expected_sk_key`.
+ fn with_expected_sk_identity(
+ instance: &str,
+ expected_sk_key: coset::CoseKey,
+ ) -> Result<Self, SkClientError> {
+ let default_dice = make_explicit_owned_dice(/*Security version in a node */ 5);
+ Self::create(instance, default_dice, Some(expected_sk_key))
+ }
+
+ fn create(
+ instance: &str,
+ dice_artifacts: OwnedDiceArtifactsWithExplicitKey,
+ expected_sk_key: Option<coset::CoseKey>,
+ ) -> Result<Self, SkClientError> {
let sk = get_connection(instance);
- Self {
+ Ok(Self {
sk: sk.clone(),
- session: SkSession::new(sk, &dice_artifacts).unwrap(),
+ session: SkSession::new(sk, &dice_artifacts, expected_sk_key)?,
dice_artifacts,
- }
+ })
}
/// This method is wrapper that use `SkSession::secret_management_request` which handles
@@ -347,7 +390,7 @@
#[rdroidtest(get_instances())]
fn secret_management_get_version(instance: String) {
- let mut sk_client = SkClient::new(&instance);
+ let mut sk_client = SkClient::new(&instance).unwrap();
let request = GetVersionRequest {};
let request_packet = request.serialize_to_packet();
@@ -364,7 +407,7 @@
#[rdroidtest(get_instances())]
fn secret_management_malformed_request(instance: String) {
- let mut sk_client = SkClient::new(&instance);
+ let mut sk_client = SkClient::new(&instance).unwrap();
let request = GetVersionRequest {};
let request_packet = request.serialize_to_packet();
@@ -383,7 +426,7 @@
#[rdroidtest(get_instances())]
fn secret_management_store_get_secret_found(instance: String) {
- let mut sk_client = SkClient::new(&instance);
+ let mut sk_client = SkClient::new(&instance).unwrap();
sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE).unwrap();
@@ -393,7 +436,7 @@
#[rdroidtest(get_instances())]
fn secret_management_store_get_secret_not_found(instance: String) {
- let mut sk_client = SkClient::new(&instance);
+ let mut sk_client = SkClient::new(&instance).unwrap();
// Store a secret (corresponding to an id).
sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE).unwrap();
@@ -404,7 +447,7 @@
#[rdroidtest(get_instances())]
fn secretkeeper_store_delete_ids(instance: String) {
- let mut sk_client = SkClient::new(&instance);
+ let mut sk_client = SkClient::new(&instance).unwrap();
sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE).unwrap();
sk_client.store(&ID_EXAMPLE_2, &SECRET_EXAMPLE).unwrap();
@@ -420,7 +463,7 @@
#[rdroidtest(get_instances())]
fn secretkeeper_store_delete_multiple_ids(instance: String) {
- let mut sk_client = SkClient::new(&instance);
+ let mut sk_client = SkClient::new(&instance).unwrap();
sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE).unwrap();
sk_client.store(&ID_EXAMPLE_2, &SECRET_EXAMPLE).unwrap();
@@ -431,7 +474,7 @@
}
#[rdroidtest(get_instances())]
fn secretkeeper_store_delete_duplicate_ids(instance: String) {
- let mut sk_client = SkClient::new(&instance);
+ let mut sk_client = SkClient::new(&instance).unwrap();
sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE).unwrap();
sk_client.store(&ID_EXAMPLE_2, &SECRET_EXAMPLE).unwrap();
@@ -444,7 +487,7 @@
#[rdroidtest(get_instances())]
fn secretkeeper_store_delete_nonexistent(instance: String) {
- let mut sk_client = SkClient::new(&instance);
+ let mut sk_client = SkClient::new(&instance).unwrap();
sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE).unwrap();
sk_client.store(&ID_EXAMPLE_2, &SECRET_EXAMPLE).unwrap();
@@ -459,7 +502,7 @@
#[rdroidtest(get_instances())]
#[ignore_if(|p| p != "nonsecure")]
fn secretkeeper_store_delete_all(instance: String) {
- let mut sk_client = SkClient::new(&instance);
+ let mut sk_client = SkClient::new(&instance).unwrap();
sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE).unwrap();
sk_client.store(&ID_EXAMPLE_2, &SECRET_EXAMPLE).unwrap();
@@ -486,7 +529,7 @@
fn secret_management_replay_protection_seq_num(instance: String) {
let dice_chain = make_explicit_owned_dice(/*Security version in a node */ 5);
let sealing_policy = sealing_policy(dice_chain.explicit_key_dice_chain().unwrap());
- let sk_client = SkClient::with_identity(&instance, dice_chain);
+ let sk_client = SkClient::with_identity(&instance, dice_chain).unwrap();
// Construct encoded request packets for the test
let (req_1, req_2, req_3) = construct_secret_management_requests(sealing_policy);
@@ -522,7 +565,7 @@
fn secret_management_replay_protection_seq_num_per_session(instance: String) {
let dice_chain = make_explicit_owned_dice(/*Security version in a node */ 5);
let sealing_policy = sealing_policy(dice_chain.explicit_key_dice_chain().unwrap());
- let sk_client = SkClient::with_identity(&instance, dice_chain);
+ let sk_client = SkClient::with_identity(&instance, dice_chain).unwrap();
// Construct encoded request packets for the test
let (req_1, _, _) = construct_secret_management_requests(sealing_policy);
@@ -538,7 +581,7 @@
assert_eq!(res.response_type().unwrap(), ResponseType::Success);
// Start another session
- let sk_client_diff = SkClient::new(&instance);
+ let sk_client_diff = SkClient::new(&instance).unwrap();
// Check first request/response is with seq_0 is successful
let res = ResponsePacket::from_slice(
&sk_client_diff.secret_management_request_custom_aad(&req_1, &seq_0, &seq_0).unwrap(),
@@ -553,7 +596,7 @@
fn secret_management_replay_protection_out_of_seq_req_not_accepted(instance: String) {
let dice_chain = make_explicit_owned_dice(/*Security version in a node */ 5);
let sealing_policy = sealing_policy(dice_chain.explicit_key_dice_chain().unwrap());
- let sk_client = SkClient::with_identity(&instance, dice_chain);
+ let sk_client = SkClient::with_identity(&instance, dice_chain).unwrap();
// Construct encoded request packets for the test
let (req_1, req_2, _) = construct_secret_management_requests(sealing_policy);
@@ -578,18 +621,19 @@
#[rdroidtest(get_instances())]
fn secret_management_policy_gate(instance: String) {
let dice_chain = make_explicit_owned_dice(/*Security version in a node */ 100);
- let mut sk_client_original = SkClient::with_identity(&instance, dice_chain);
+ let mut sk_client_original = SkClient::with_identity(&instance, dice_chain).unwrap();
sk_client_original.store(&ID_EXAMPLE, &SECRET_EXAMPLE).unwrap();
assert_eq!(sk_client_original.get(&ID_EXAMPLE).unwrap(), SECRET_EXAMPLE);
// Start a session with higher security_version & get the stored secret.
let dice_chain_upgraded = make_explicit_owned_dice(/*Security version in a node */ 101);
- let mut sk_client_upgraded = SkClient::with_identity(&instance, dice_chain_upgraded);
+ let mut sk_client_upgraded = SkClient::with_identity(&instance, dice_chain_upgraded).unwrap();
assert_eq!(sk_client_upgraded.get(&ID_EXAMPLE).unwrap(), SECRET_EXAMPLE);
// Start a session with lower security_version (This should be denied access to the secret).
let dice_chain_downgraded = make_explicit_owned_dice(/*Security version in a node */ 99);
- let mut sk_client_downgraded = SkClient::with_identity(&instance, dice_chain_downgraded);
+ let mut sk_client_downgraded =
+ SkClient::with_identity(&instance, dice_chain_downgraded).unwrap();
assert!(matches!(
sk_client_downgraded.get(&ID_EXAMPLE).unwrap_err(),
Error::SecretkeeperError(SecretkeeperError::DicePolicyError)
@@ -610,6 +654,30 @@
));
}
+// This test checks that the identity of Secretkeeper (in context of AuthGraph key exchange) is
+// same as the one advertized in Linux device tree. This is only expected from `default` instance.
+#[rdroidtest(get_instances())]
+#[ignore_if(|p| p != "default")]
+fn secretkeeper_check_identity(instance: String) {
+ let sk_key = get_secretkeeper_identity()
+ .expect("Failed to extract identity of default instance from device tree");
+ // Create a session with this expected identity. This succeeds only if the identity used by
+ // Secretkeeper is sk_key.
+ let _ = SkClient::with_expected_sk_identity(&instance, sk_key).unwrap();
+ // Create a session using any other expected sk identity, this should fail. Note that the
+ // failure arises from validation which happens at the local participant.
+ let mut any_other_key = CoseKey::default();
+ any_other_key.canonicalize(CborOrdering::Lexicographic);
+ let err = SkClient::with_expected_sk_identity(&instance, any_other_key).unwrap_err();
+ assert!(matches!(
+ err,
+ SkClientError::AuthgraphError(authgraph_core::error::Error(
+ authgraph_wire::ErrorCode::InvalidPeerKeKey,
+ _
+ ))
+ ));
+}
+
// Helper method that constructs 3 SecretManagement requests. Callers would usually not care about
// what each of the request concretely is.
fn construct_secret_management_requests(sealing_policy: Vec<u8>) -> (Vec<u8>, Vec<u8>, Vec<u8>) {
diff --git a/wifi/aidl/vts/functional/wifi_rtt_controller_aidl_test.cpp b/wifi/aidl/vts/functional/wifi_rtt_controller_aidl_test.cpp
index 9c6a29e..1596602 100644
--- a/wifi/aidl/vts/functional/wifi_rtt_controller_aidl_test.cpp
+++ b/wifi/aidl/vts/functional/wifi_rtt_controller_aidl_test.cpp
@@ -161,6 +161,48 @@
}
/*
+ * Request80211azNtbRangeMeasurement
+ * Tests the two sided 11az non-trigger based ranging - 802.11az NTB FTM protocol.
+ */
+TEST_P(WifiRttControllerAidlTest, Request80211azNtbRangeMeasurement) {
+ if (interface_version_ < 2) {
+ GTEST_SKIP() << "Request80211azNtbRangeMeasurement is available as of RttController V2";
+ }
+
+ RttCapabilities caps = getCapabilities();
+ if (!caps.ntbInitiatorSupported) {
+ GTEST_SKIP() << "Skipping 11az NTB RTT since driver/fw does not support";
+ }
+
+ RttConfig config;
+ config.addr = {{0x00, 0x01, 0x02, 0x03, 0x04, 0x05}};
+ config.type = RttType::TWO_SIDED_11AZ_NTB;
+ config.peer = RttPeerType::AP;
+ config.channel.width = WifiChannelWidthInMhz::WIDTH_80;
+ config.channel.centerFreq = 5180;
+ config.channel.centerFreq0 = 5210;
+ config.channel.centerFreq1 = 0;
+ config.bw = RttBw::BW_20MHZ;
+ config.preamble = RttPreamble::HT;
+ config.mustRequestLci = false;
+ config.mustRequestLcr = false;
+ config.numFramesPerBurst = 8;
+ config.numRetriesPerRttFrame = 0;
+ config.numRetriesPerFtmr = 0;
+ // 11az non-trigger based minimum measurement time in units of 100 microseconds.
+ config.ntbMinMeasurementTime = 2500;
+ // 11az non-trigger based maximum measurement time in units of 10 milliseconds.
+ config.ntbMaxMeasurementTime = 1500;
+
+ int cmdId = 55;
+ std::vector<RttConfig> configs = {config};
+ EXPECT_TRUE(wifi_rtt_controller_->rangeRequest(cmdId, configs).isOk());
+
+ // Sleep for 2 seconds to wait for driver/firmware to complete RTT.
+ sleep(2);
+}
+
+/*
* Request2SidedRangeMeasurement
* Tests the two sided ranging - 802.11mc FTM protocol.
*/
diff --git a/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp b/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp
index e8e19ae..51b7301 100644
--- a/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp
+++ b/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp
@@ -40,6 +40,8 @@
using aidl::android::hardware::wifi::StaRoamingCapabilities;
using aidl::android::hardware::wifi::StaRoamingConfig;
using aidl::android::hardware::wifi::StaRoamingState;
+using aidl::android::hardware::wifi::TwtCapabilities;
+using aidl::android::hardware::wifi::TwtRequest;
using aidl::android::hardware::wifi::WifiBand;
using aidl::android::hardware::wifi::WifiDebugRxPacketFateReport;
using aidl::android::hardware::wifi::WifiDebugTxPacketFateReport;
@@ -51,6 +53,7 @@
stopWifiService(getInstanceName());
wifi_sta_iface_ = getWifiStaIface(getInstanceName());
ASSERT_NE(nullptr, wifi_sta_iface_.get());
+ ASSERT_TRUE(wifi_sta_iface_->getInterfaceVersion(&interface_version_).isOk());
}
void TearDown() override { stopWifiService(getInstanceName()); }
@@ -69,6 +72,7 @@
}
std::shared_ptr<IWifiStaIface> wifi_sta_iface_;
+ int interface_version_;
// Checks if the mDNS Offload is supported by any NIC.
bool isMdnsOffloadPresentInNIC() {
@@ -356,6 +360,91 @@
}
}
+TEST_P(WifiStaIfaceAidlTest, TwtGetCapabilities) {
+ if (interface_version_ < 2) {
+ GTEST_SKIP() << "TwtGetCapabilities is available as of sta_iface V2";
+ }
+
+ TwtCapabilities twt_capabilities = {};
+ auto status = wifi_sta_iface_->twtGetCapabilities(&twt_capabilities);
+ if (checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED)) {
+ GTEST_SKIP() << "twtGetCapabilities() is not supported by the vendor";
+ }
+ EXPECT_TRUE(status.isOk());
+ if (!twt_capabilities.isTwtRequesterSupported) {
+ GTEST_SKIP() << "TWT is not supported";
+ }
+
+ EXPECT_GT(twt_capabilities.minWakeDurationUs, 0);
+ EXPECT_GT(twt_capabilities.maxWakeDurationUs, 0);
+ EXPECT_GT(twt_capabilities.minWakeIntervalUs, 0);
+ EXPECT_GT(twt_capabilities.maxWakeIntervalUs, 0);
+}
+
+TEST_P(WifiStaIfaceAidlTest, TwtSessionSetup) {
+ if (interface_version_ < 2) {
+ GTEST_SKIP() << "TwtSessionSetup is available as of sta_iface V2";
+ }
+
+ TwtCapabilities twt_capabilities = {};
+ auto status = wifi_sta_iface_->twtGetCapabilities(&twt_capabilities);
+ if (checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED)) {
+ GTEST_SKIP() << "twtGetCapabilities() is not supported by the vendor";
+ }
+ EXPECT_TRUE(status.isOk());
+ if (!twt_capabilities.isTwtRequesterSupported) {
+ GTEST_SKIP() << "TWT is not supported";
+ }
+
+ TwtRequest twtRequest;
+ twtRequest.mloLinkId = 0;
+ twtRequest.minWakeDurationUs = twt_capabilities.minWakeDurationUs;
+ twtRequest.maxWakeDurationUs = twt_capabilities.maxWakeDurationUs;
+ twtRequest.minWakeIntervalUs = twt_capabilities.minWakeIntervalUs;
+ twtRequest.maxWakeIntervalUs = twt_capabilities.maxWakeIntervalUs;
+ EXPECT_TRUE(wifi_sta_iface_->twtSessionSetup(1, twtRequest).isOk());
+}
+
+TEST_P(WifiStaIfaceAidlTest, TwtSessionGetStats) {
+ if (interface_version_ < 2) {
+ GTEST_SKIP() << "TwtSessionGetStats is available as of sta_iface V2";
+ }
+
+ TwtCapabilities twt_capabilities = {};
+ auto status = wifi_sta_iface_->twtGetCapabilities(&twt_capabilities);
+ if (checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED)) {
+ GTEST_SKIP() << "twtGetCapabilities() is not supported by the vendor";
+ }
+ EXPECT_TRUE(status.isOk());
+ if (!twt_capabilities.isTwtRequesterSupported) {
+ GTEST_SKIP() << "TWT is not supported";
+ }
+
+ // Expecting a IWifiStaIfaceEventCallback.onTwtFailure() with INVALID_PARAMS
+ // as the error code.
+ EXPECT_TRUE(wifi_sta_iface_->twtSessionGetStats(1, 10).isOk());
+}
+
+TEST_P(WifiStaIfaceAidlTest, TwtSessionTeardown) {
+ if (interface_version_ < 2) {
+ GTEST_SKIP() << "TwtSessionTeardown is available as of sta_iface V3";
+ }
+
+ TwtCapabilities twt_capabilities = {};
+ auto status = wifi_sta_iface_->twtGetCapabilities(&twt_capabilities);
+ if (checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED)) {
+ GTEST_SKIP() << "twtGetCapabilities() is not supported by the vendor";
+ }
+ EXPECT_TRUE(status.isOk());
+ if (!twt_capabilities.isTwtRequesterSupported) {
+ GTEST_SKIP() << "TWT is not supported";
+ }
+
+ // Expecting a IWifiStaIfaceEventCallback.onTwtFailure() with INVALID_PARAMS
+ // as the error code.
+ EXPECT_TRUE(wifi_sta_iface_->twtSessionTeardown(1, 10).isOk());
+}
+
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiStaIfaceAidlTest);
INSTANTIATE_TEST_SUITE_P(WifiTest, WifiStaIfaceAidlTest,
testing::ValuesIn(android::getAidlHalInstanceNames(IWifi::descriptor)),