Merge "Audio V4: Add V2 XML in V4 effect" into pi-dev
diff --git a/audio/4.0/config/audio_policy_configuration.xsd b/audio/4.0/config/audio_policy_configuration.xsd
index e5b4449..34c2b11 100644
--- a/audio/4.0/config/audio_policy_configuration.xsd
+++ b/audio/4.0/config/audio_policy_configuration.xsd
@@ -104,7 +104,7 @@
<xs:element name="devicePorts" type="devicePorts" minOccurs="0"/>
<xs:element name="routes" type="routes" minOccurs="0"/>
</xs:sequence>
- <xs:attribute name="name" type="xsd:string" use="required"/>
+ <xs:attribute name="name" type="xs:string" use="required"/>
<xs:attribute name="halVersion" type="halVersion" use="required"/>
</xs:complexType>
<xs:unique name="mixPortNameUniqueness">
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleUtils.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleUtils.h
index ce0b163..f97dfa1 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleUtils.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleUtils.h
@@ -33,10 +33,9 @@
constexpr int32_t kAllSupportedAreas = 0;
/** Returns underlying (integer) value for given enum. */
-template<typename ENUM>
-inline constexpr typename std::underlying_type<ENUM>::type toInt(
- ENUM const value) {
- return static_cast<typename std::underlying_type<ENUM>::type>(value);
+template<typename ENUM, typename U = typename std::underlying_type<ENUM>::type>
+inline constexpr U toInt(ENUM const value) {
+ return static_cast<U>(value);
}
inline constexpr VehiclePropertyType getPropType(int32_t prop) {
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index c1c511f..e54de00 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -429,7 +429,7 @@
{.config = {.prop = toInt(VehicleProperty::AP_POWER_BOOTUP_REASON),
.access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
+ .changeMode = VehiclePropertyChangeMode::STATIC},
.initialValue = {.int32Values = {toInt(VehicleApPowerBootupReason::USER_POWER_ON)}}},
{
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 3001213..87daedc 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -510,6 +510,7 @@
*
* @change_mode VehiclePropertyChangeMode:ON_CHANGE
* @access VehiclePropertyAccess:READ
+ * @data_enum VehicleTurnSignal
*/
TURN_SIGNAL_STATE = (
0x0408
@@ -522,6 +523,7 @@
*
* @change_mode VehiclePropertyChangeMode:ON_CHANGE
* @access VehiclePropertyAccess:READ
+ * @data_enum VehicleIgnitionState
*/
IGNITION_STATE = (
0x0409
diff --git a/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc b/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc
index e1f5faa..5a01ecc 100644
--- a/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc
+++ b/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc
@@ -1,5 +1,6 @@
service vendor.bluetooth-1-0 /vendor/bin/hw/android.hardware.bluetooth@1.0-service
class hal
+ capabilities NET_ADMIN SYS_NICE
user bluetooth
group bluetooth
writepid /dev/stune/foreground/tasks
diff --git a/camera/metadata/3.3/types.hal b/camera/metadata/3.3/types.hal
index 4f3f678..0535be1 100644
--- a/camera/metadata/3.3/types.hal
+++ b/camera/metadata/3.3/types.hal
@@ -33,6 +33,8 @@
ANDROID_LOGICAL_MULTI_CAMERA =
android.hardware.camera.metadata@3.2::CameraMetadataSection:ANDROID_SECTION_COUNT,
+ ANDROID_DISTORTION_CORRECTION,
+
ANDROID_SECTION_COUNT_3_3,
VENDOR_SECTION_3_3 = 0x8000,
@@ -46,6 +48,8 @@
enum CameraMetadataSectionStart : android.hardware.camera.metadata@3.2::CameraMetadataSectionStart {
ANDROID_LOGICAL_MULTI_CAMERA_START = CameraMetadataSection:ANDROID_LOGICAL_MULTI_CAMERA << 16,
+ ANDROID_DISTORTION_CORRECTION_START = CameraMetadataSection:ANDROID_DISTORTION_CORRECTION << 16,
+
VENDOR_SECTION_START_3_3 = CameraMetadataSection:VENDOR_SECTION_3_3 << 16,
};
@@ -164,6 +168,23 @@
ANDROID_LOGICAL_MULTI_CAMERA_END_3_3,
+ /** android.distortionCorrection.mode [dynamic, enum, public]
+ *
+ * <p>Mode of operation for the lens distortion correction block.</p>
+ */
+ ANDROID_DISTORTION_CORRECTION_MODE = CameraMetadataSectionStart:ANDROID_DISTORTION_CORRECTION_START,
+
+ /** android.distortionCorrection.availableModes [static, byte[], public]
+ *
+ * <p>List of distortion correction modes for ANDROID_DISTORTION_CORRECTION_MODE that are
+ * supported by this camera device.</p>
+ *
+ * @see ANDROID_DISTORTION_CORRECTION_MODE
+ */
+ ANDROID_DISTORTION_CORRECTION_AVAILABLE_MODES,
+
+ ANDROID_DISTORTION_CORRECTION_END_3_3,
+
};
/*
@@ -234,3 +255,12 @@
ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_APPROXIMATE,
ANDROID_LOGICAL_MULTI_CAMERA_SENSOR_SYNC_TYPE_CALIBRATED,
};
+
+/** android.distortionCorrection.mode enumeration values
+ * @see ANDROID_DISTORTION_CORRECTION_MODE
+ */
+enum CameraMetadataEnumAndroidDistortionCorrectionMode : uint32_t {
+ ANDROID_DISTORTION_CORRECTION_MODE_OFF,
+ ANDROID_DISTORTION_CORRECTION_MODE_FAST,
+ ANDROID_DISTORTION_CORRECTION_MODE_HIGH_QUALITY,
+};
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index 370ffdd..1b83125 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -225,8 +225,7 @@
<version>1.0</version>
<interface>
<name>IDevice</name>
- <!-- TODO(b/73738616): This should be * (match any) -->
- <instance>hvx</instance>
+ <regex-instance>.*</regex-instance>
</interface>
</hal>
<hal format="hidl" optional="true">
@@ -258,11 +257,11 @@
<version>1.0-1</version>
<interface>
<name>IRadio</name>
- <instance>slot1</instance>
+ <regex-instance>slot[0-9]+</regex-instance>
</interface>
<interface>
<name>ISap</name>
- <instance>slot1</instance>
+ <regex-instance>slot[0-9]+</regex-instance>
</interface>
</hal>
<hal format="hidl" optional="true">
diff --git a/confirmationui/support/include/android/hardware/confirmationui/support/msg_formatting.h b/confirmationui/support/include/android/hardware/confirmationui/support/msg_formatting.h
index 0d03591..6558799 100644
--- a/confirmationui/support/include/android/hardware/confirmationui/support/msg_formatting.h
+++ b/confirmationui/support/include/android/hardware/confirmationui/support/msg_formatting.h
@@ -105,6 +105,7 @@
PromptUserConfirmation,
DeliverSecureInputEvent,
Abort,
+ Vendor,
};
template <Command cmd>
@@ -115,6 +116,7 @@
DECLARE_COMMAND(PromptUserConfirmation);
DECLARE_COMMAND(DeliverSecureInputEvent);
DECLARE_COMMAND(Abort);
+DECLARE_COMMAND(Vendor);
using PromptUserConfirmationMsg = Message<PromptUserConfirmation_t, hidl_string, hidl_vec<uint8_t>,
hidl_string, hidl_vec<UIOption>>;
@@ -166,7 +168,7 @@
}
inline void zero(const volatile uint8_t*, const volatile uint8_t*) {}
// This odd alignment function aligns the stream position to a 4byte and never 8byte boundary
-// It is to accommodate the 4 byte size field which is then followed by 8byte alligned data.
+// It is to accommodate the 4 byte size field which is then followed by 8byte aligned data.
template <typename T>
StreamState<T> unalign(StreamState<T> s) {
uint8_t unalignment = uintptr_t(s.pos_) & 0x3;
diff --git a/current.txt b/current.txt
index fdf17be..71e2d91 100644
--- a/current.txt
+++ b/current.txt
@@ -294,7 +294,7 @@
3b17c1fdfc389e0abe626c37054954b07201127d890c2bc05d47613ec1f4de4f android.hardware.automotive.evs@1.0::types
b3caf524c46a47d67e6453a34419e1881942d059e146cda740502670e9a752c3 android.hardware.automotive.vehicle@2.0::IVehicle
80fb4156fa91ce86e49bd2cabe215078f6b69591d416a09e914532eae6712052 android.hardware.automotive.vehicle@2.0::IVehicleCallback
-442de3a3d3819ff8b8bfe9ec710592ca8af7c16bfdb5eb8911b898b8f12b2bb0 android.hardware.automotive.vehicle@2.0::types
+4ff0dcfb938a5df283eef47de33b4e1284fab73f584cfc0c94e97317bdb7bf26 android.hardware.automotive.vehicle@2.0::types
32cc50cc2a7658ec613c0c2dd2accbf6a05113b749852879e818b8b7b438db19 android.hardware.bluetooth.a2dp@1.0::IBluetoothAudioHost
ff4be64d7992f8bec97dff37f35450e79b3430c61f85f54322ce45bef229dc3b android.hardware.bluetooth.a2dp@1.0::IBluetoothAudioOffload
27f22d2e873e6201f9620cf4d8e2facb25bd0dd30a2b911e441b4600d560fa62 android.hardware.bluetooth.a2dp@1.0::types
@@ -307,7 +307,7 @@
4fb0725c36ed4f77a42b42e3f18d8b5f7919cb62b90098b23143a555aa7dd96d android.hardware.camera.device@3.4::ICameraDeviceCallback
812fa66aa10ba0cba27cfddc2fd7f0ee27a8ab65a1f15aa79fdad97d403e6a14 android.hardware.camera.device@3.4::ICameraDeviceSession
cc288f1f78d1e643eb3d3dbc16e1401d44033d8e6856761f5156814a29986ec7 android.hardware.camera.device@3.4::types
-26462f5a29bef30485f9264115e79e5f5eb6234951dfeb47424709a1b8936030 android.hardware.camera.metadata@3.3::types
+71ee1f46dac4df417d2950e4de760e4145038ae363fc11aeea487350bf603897 android.hardware.camera.metadata@3.3::types
1a46aeae45b7a0e47f79b7207300532986f9d9cd7060779afc7a529f54d712ab android.hardware.confirmationui@1.0::IConfirmationResultCallback
6d8347ff3cd7de471065ac3e8e68385073630cdeebe9f8fa58cb91cf44436c95 android.hardware.confirmationui@1.0::IConfirmationUI
a3ff916784dce87a56c757ab5c86433f0cdf562280999a5f978a6e8a0f3f19e7 android.hardware.confirmationui@1.0::types
@@ -369,4 +369,6 @@
ee08280de21cb41e3ec26d6ed636c701b7f70516e71fb22f4fe60a13e603f406 android.hardware.wifi.hostapd@1.0::IHostapd
b2479cd7a417a1cf4f3a22db4e4579e21bac38fdcaf381e2bf10176d05397e01 android.hardware.wifi.hostapd@1.0::types
e362203b941f18bd4cba29a62adfa02453ed00d6be5b72cdb6c4d7e0bf394a40 android.hardware.wifi.supplicant@1.1::ISupplicant
+21757d0e5dd4b7e4bd981a4a20531bca3c32271ad9777b17b74eb5a1ea508384 android.hardware.wifi.supplicant@1.1::ISupplicantStaIface
+cd4330c3196bda1d642a32abfe23a7d64ebfbda721940643af6867af3b3f0aa9 android.hardware.wifi.supplicant@1.1::ISupplicantStaIfaceCallback
10ff2fae516346b86121368ce5790d5accdfcb73983246b813f3d488b66db45a android.hardware.wifi.supplicant@1.1::ISupplicantStaNetwork
diff --git a/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp b/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp
index 061f2cd..1246616 100644
--- a/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp
+++ b/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp
@@ -43,7 +43,6 @@
using ::android::hardware::drm::V1_0::ICryptoPlugin;
using ::android::hardware::drm::V1_0::KeyedVector;
using ::android::hardware::drm::V1_0::KeyValue;
-using ::android::hardware::drm::V1_0::KeyRequestType;
using ::android::hardware::drm::V1_0::KeyType;
using ::android::hardware::drm::V1_0::Mode;
using ::android::hardware::drm::V1_0::Pattern;
@@ -60,6 +59,8 @@
using ::android::hardware::drm::V1_1::ICryptoFactory;
using ::android::hardware::drm::V1_1::IDrmFactory;
using ::android::hardware::drm::V1_1::IDrmPlugin;
+using ::android::hardware::drm::V1_1::KeyRequestType;
+using ::android::hardware::drm::V1_1::SecureStopRelease;
using ::android::hardware::drm::V1_1::SecurityLevel;
using ::android::hardware::drm::V1_1::SecurityLevel;
@@ -167,7 +168,6 @@
SessionId openSession(SecurityLevel level);
void closeSession(const SessionId& sessionId);
hidl_vec<uint8_t> loadKeys(const SessionId& sessionId, const KeyType& type);
- sp<IMemory> getDecryptMemory(size_t size, size_t index);
private:
sp<IDrmPlugin> createDrmPlugin(sp<IDrmFactory> drmFactory) {
@@ -308,6 +308,125 @@
}
/**
+ * Helper method to load keys for subsequent decrypt tests.
+ * These tests use predetermined key request/response to
+ * avoid requiring a round trip to a license server.
+ */
+hidl_vec<uint8_t> DrmHalClearkeyTest::loadKeys(
+ const SessionId& sessionId, const KeyType& type = KeyType::STREAMING) {
+ hidl_vec<uint8_t> initData = {
+ // BMFF box header (4 bytes size + 'pssh')
+ 0x00, 0x00, 0x00, 0x34, 0x70, 0x73, 0x73, 0x68,
+ // full box header (version = 1 flags = 0)
+ 0x01, 0x00, 0x00, 0x00,
+ // system id
+ 0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, 0xac, 0xe3, 0x3c,
+ 0x1e, 0x52, 0xe2, 0xfb, 0x4b,
+ // number of key ids
+ 0x00, 0x00, 0x00, 0x01,
+ // key id
+ 0x60, 0x06, 0x1e, 0x01, 0x7e, 0x47, 0x7e, 0x87, 0x7e, 0x57, 0xd0,
+ 0x0d, 0x1e, 0xd0, 0x0d, 0x1e,
+ // size of data, must be zero
+ 0x00, 0x00, 0x00, 0x00};
+
+ hidl_vec<uint8_t> expectedKeyRequest = {
+ 0x7b, 0x22, 0x6b, 0x69, 0x64, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x59, 0x41, 0x59, 0x65,
+ 0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2d, 0x56, 0x39, 0x41, 0x4e, 0x48, 0x74,
+ 0x41, 0x4e, 0x48, 0x67, 0x22, 0x5d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a,
+ 0x22, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x79, 0x22, 0x7d};
+
+ hidl_vec<uint8_t> knownKeyResponse = {
+ 0x7b, 0x22, 0x6b, 0x65, 0x79, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x6b, 0x74, 0x79, 0x22,
+ 0x3a, 0x22, 0x6f, 0x63, 0x74, 0x22, 0x2c, 0x22, 0x6b, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x59,
+ 0x41, 0x59, 0x65, 0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2d, 0x56, 0x39, 0x41, 0x4e,
+ 0x48, 0x74, 0x41, 0x4e, 0x48, 0x67, 0x22, 0x2c, 0x22, 0x6b, 0x22, 0x3a, 0x22, 0x47, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x54, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x42, 0x61, 0x73, 0x65,
+ 0x36, 0x34, 0x67, 0x67, 0x67, 0x22, 0x7d, 0x5d, 0x7d, 0x0a};
+
+ hidl_string mimeType = "video/mp4";
+ KeyedVector optionalParameters;
+ auto res = drmPlugin->getKeyRequest_1_1(
+ sessionId, initData, mimeType, type, optionalParameters,
+ [&](Status status, const hidl_vec<uint8_t>& request,
+ KeyRequestType requestType, const hidl_string&) {
+ EXPECT_EQ(Status::OK, status);
+ EXPECT_EQ(KeyRequestType::INITIAL, requestType);
+ EXPECT_EQ(request, expectedKeyRequest);
+ });
+ EXPECT_OK(res);
+
+ hidl_vec<uint8_t> keySetId;
+ res = drmPlugin->provideKeyResponse(
+ sessionId, knownKeyResponse,
+ [&](Status status, const hidl_vec<uint8_t>& myKeySetId) {
+ EXPECT_EQ(Status::OK, status);
+ EXPECT_EQ(0u, myKeySetId.size());
+ keySetId = myKeySetId;
+ });
+ EXPECT_OK(res);
+ return keySetId;
+}
+
+/**
+ * Test openSession negative case: security level higher than supported
+ */
+TEST_F(DrmHalClearkeyTest, OpenSessionBadLevel) {
+ auto res = drmPlugin->openSession_1_1(SecurityLevel::HW_SECURE_ALL,
+ [&](Status status, const SessionId& /* id */) {
+ EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
+ });
+ EXPECT_OK(res);
+}
+
+/**
+ * Test getKeyRequest_1_1 via loadKeys
+ */
+TEST_F(DrmHalClearkeyTest, GetKeyRequest) {
+ auto sessionId = openSession();
+ loadKeys(sessionId);
+ closeSession(sessionId);
+}
+
+/**
+ * A get key request should fail if no sessionId is provided
+ */
+TEST_F(DrmHalClearkeyTest, GetKeyRequestNoSession) {
+ SessionId invalidSessionId;
+ hidl_vec<uint8_t> initData;
+ hidl_string mimeType = "video/mp4";
+ KeyedVector optionalParameters;
+ auto res = drmPlugin->getKeyRequest_1_1(
+ invalidSessionId, initData, mimeType, KeyType::STREAMING,
+ optionalParameters,
+ [&](Status status, const hidl_vec<uint8_t>&, KeyRequestType,
+ const hidl_string&) { EXPECT_EQ(Status::BAD_VALUE, status); });
+ EXPECT_OK(res);
+}
+
+/**
+ * The clearkey plugin doesn't support offline key requests.
+ * Test that the plugin returns the expected error code in
+ * this case.
+ */
+TEST_F(DrmHalClearkeyTest, GetKeyRequestOfflineKeyTypeNotSupported) {
+ auto sessionId = openSession();
+ hidl_vec<uint8_t> initData;
+ hidl_string mimeType = "video/mp4";
+ KeyedVector optionalParameters;
+
+ auto res = drmPlugin->getKeyRequest_1_1(
+ sessionId, initData, mimeType, KeyType::OFFLINE, optionalParameters,
+ [&](Status status, const hidl_vec<uint8_t>&, KeyRequestType,
+ const hidl_string&) {
+ // Clearkey plugin doesn't support offline key type
+ EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
+ });
+ EXPECT_OK(res);
+ closeSession(sessionId);
+}
+
+/**
* Test that the plugin returns valid connected and max HDCP levels
*/
TEST_F(DrmHalClearkeyTest, GetHdcpLevels) {
@@ -322,6 +441,11 @@
}
/**
+ * Since getHdcpLevels only queries information there are no
+ * negative cases.
+ */
+
+/**
* Test that the plugin returns default open and max session counts
*/
TEST_F(DrmHalClearkeyTest, GetDefaultSessionCounts) {
@@ -373,6 +497,11 @@
}
/**
+ * Since getNumberOfSessions only queries information there are no
+ * negative cases.
+ */
+
+/**
* Test that the plugin returns the same security level
* by default as when it is requested explicitly
*/
@@ -428,7 +557,7 @@
/**
* Test metrics are set appropriately for open and close operations.
*/
-TEST_F(DrmHalClearkeyTest, GetMetricsSuccess) {
+TEST_F(DrmHalClearkeyTest, GetMetricsOpenClose) {
SessionId sessionId = openSession();
// The first close should be successful.
closeSession(sessionId);
@@ -449,8 +578,292 @@
(int64_t)Status::ERROR_DRM_SESSION_NOT_OPENED,
"count", (int64_t)1));
});
+ EXPECT_OK(res);
}
+/**
+ * Since getMetrics only queries information there are no
+ * negative cases.
+ */
+
+/**
+ * Test that there are no secure stop ids after clearing them
+ */
+TEST_F(DrmHalClearkeyTest, GetSecureStopIdsCleared) {
+ auto stat = drmPlugin->removeAllSecureStops();
+ EXPECT_OK(stat);
+
+ bool ok = drmPlugin->getSecureStopIds(
+ [&](Status status, const hidl_vec<SecureStopId>& ids) {
+ EXPECT_EQ(Status::OK, status);
+ EXPECT_EQ(0u, ids.size());
+ }).isOk();
+ EXPECT_TRUE(ok);
+}
+
+/**
+ * Test that there are secure stop ids after loading keys once
+ */
+TEST_F(DrmHalClearkeyTest, GetSecureStopIdsOnce) {
+ auto stat = drmPlugin->removeAllSecureStops();
+ EXPECT_OK(stat);
+
+ auto sessionId = openSession();
+ loadKeys(sessionId);
+ closeSession(sessionId);
+
+ auto res = drmPlugin->getSecureStopIds(
+ [&](Status status, const hidl_vec<SecureStopId>& ids) {
+ EXPECT_EQ(Status::OK, status);
+ EXPECT_EQ(1u, ids.size());
+ });
+ EXPECT_OK(res);
+
+ stat = drmPlugin->removeAllSecureStops();
+ EXPECT_OK(stat);
+
+ res = drmPlugin->getSecureStopIds(
+ [&](Status status, const hidl_vec<SecureStopId>& ids) {
+ EXPECT_EQ(Status::OK, status);
+ EXPECT_EQ(0u, ids.size());
+ });
+ EXPECT_OK(res);
+}
+
+/**
+ * Since getSecureStopIds only queries information there are no
+ * negative cases.
+ */
+
+/**
+ * Test that the clearkey plugin reports no secure stops when
+ * there are none.
+ */
+TEST_F(DrmHalClearkeyTest, GetNoSecureStops) {
+ auto stat = drmPlugin->removeAllSecureStops();
+ EXPECT_OK(stat);
+
+ auto res = drmPlugin->getSecureStops(
+ [&](Status status, const hidl_vec<SecureStop>& stops) {
+ EXPECT_EQ(Status::OK, status);
+ EXPECT_EQ(0u, stops.size());
+ });
+ EXPECT_OK(res);
+}
+
+/**
+ * Test get/remove of one secure stop
+ */
+TEST_F(DrmHalClearkeyTest, GetOneSecureStopAndRemoveIt) {
+ auto stat = drmPlugin->removeAllSecureStops();
+ EXPECT_OK(stat);
+
+ auto sessionId = openSession();
+ loadKeys(sessionId);
+ closeSession(sessionId);
+
+ auto res = drmPlugin->getSecureStops(
+ [&](Status status, const hidl_vec<SecureStop>& stops) {
+ EXPECT_EQ(Status::OK, status);
+ EXPECT_EQ(1u, stops.size());
+ });
+ EXPECT_OK(res);
+
+ stat = drmPlugin->removeAllSecureStops();
+ EXPECT_OK(stat);
+
+ res = drmPlugin->getSecureStops(
+ [&](Status status, const hidl_vec<SecureStop>& stops) {
+ EXPECT_EQ(Status::OK, status);
+ EXPECT_EQ(0u, stops.size());
+ });
+ EXPECT_OK(res);
+}
+
+/**
+ * Since getSecureStops only queries information there are no
+ * negative cases.
+ */
+
+/**
+ * Test that there are no secure stops after clearing them
+ */
+TEST_F(DrmHalClearkeyTest, GetSecureStopsCleared) {
+ auto stat = drmPlugin->removeAllSecureStops();
+ EXPECT_OK(stat);
+
+ auto res = drmPlugin->getSecureStops(
+ [&](Status status, const hidl_vec<SecureStop>& stops) {
+ EXPECT_EQ(Status::OK, status);
+ EXPECT_EQ(0u, stops.size());
+ });
+ EXPECT_OK(res);
+}
+
+/**
+ * Test that there are secure stops after loading keys once
+ */
+TEST_F(DrmHalClearkeyTest, GetSecureStopsOnce) {
+ auto stat = drmPlugin->removeAllSecureStops();
+ EXPECT_OK(stat);
+
+ auto sessionId = openSession();
+ loadKeys(sessionId);
+ closeSession(sessionId);
+
+ auto res = drmPlugin->getSecureStops(
+ [&](Status status, const hidl_vec<SecureStop>& stops) {
+ EXPECT_EQ(Status::OK, status);
+ EXPECT_EQ(1u, stops.size());
+ });
+ EXPECT_OK(res);
+
+ stat = drmPlugin->removeAllSecureStops();
+ EXPECT_OK(stat);
+
+ res = drmPlugin->getSecureStops(
+ [&](Status status, const hidl_vec<SecureStop>& stops) {
+ EXPECT_EQ(Status::OK, status);
+ EXPECT_EQ(0u, stops.size());
+ });
+ EXPECT_OK(res);
+}
+
+/**
+ * Since getSecureStops only queries information there are no
+ * negative cases.
+ */
+
+/**
+ * Test that releasing a secure stop with empty
+ * release message fails with the documented error
+ */
+TEST_F(DrmHalClearkeyTest, ReleaseEmptySecureStop) {
+ SecureStopRelease emptyRelease = {.opaqueData = hidl_vec<uint8_t>()};
+ Status status = drmPlugin->releaseSecureStops(emptyRelease);
+ EXPECT_EQ(Status::BAD_VALUE, status);
+}
+
+/**
+ * Helper function to create a secure release message for
+ * a secure stop. The clearkey secure stop release format
+ * is just a count followed by the secure stop opaque data.
+ */
+SecureStopRelease makeSecureRelease(const SecureStop &stop) {
+ std::vector<uint8_t> stopData = stop.opaqueData;
+ std::vector<uint8_t> buffer;
+ std::string count = "0001";
+
+ auto it = buffer.insert(buffer.begin(), count.begin(), count.end());
+ buffer.insert(it + count.size(), stopData.begin(), stopData.end());
+ SecureStopRelease release = { .opaqueData = hidl_vec<uint8_t>(buffer) };
+ return release;
+}
+
+/**
+ * Test that releasing one secure stop works
+ */
+TEST_F(DrmHalClearkeyTest, ReleaseOneSecureStop) {
+
+ auto stat = drmPlugin->removeAllSecureStops();
+ EXPECT_OK(stat);
+
+ auto sessionId = openSession();
+ loadKeys(sessionId);
+ closeSession(sessionId);
+
+ SecureStopRelease release;
+ auto res = drmPlugin->getSecureStops(
+ [&](Status status, const hidl_vec<SecureStop>& stops) {
+ EXPECT_EQ(Status::OK, status);
+ EXPECT_EQ(1u, stops.size());
+ release = makeSecureRelease(stops[0]);
+ });
+ EXPECT_OK(res);
+
+ stat = drmPlugin->releaseSecureStops(release);
+ EXPECT_OK(stat);
+
+ res = drmPlugin->getSecureStops(
+ [&](Status status, const hidl_vec<SecureStop>& stops) {
+ EXPECT_EQ(Status::OK, status);
+ EXPECT_EQ(0u, stops.size());
+ });
+ EXPECT_OK(res);
+}
+
+
+/**
+ * Test that removing a secure stop with an empty ID returns
+ * documented error
+ */
+TEST_F(DrmHalClearkeyTest, RemoveEmptySecureStopId) {
+ hidl_vec<uint8_t> emptyId;
+ auto stat = drmPlugin->removeSecureStop(emptyId);
+ EXPECT_OK(stat);
+ EXPECT_EQ(Status::BAD_VALUE, stat);
+}
+
+/**
+ * Test that removing a secure stop after it has already
+ * been removed fails with the documented error code.
+ */
+TEST_F(DrmHalClearkeyTest, RemoveRemovedSecureStopId) {
+ auto stat = drmPlugin->removeAllSecureStops();
+ EXPECT_OK(stat);
+
+ auto sessionId = openSession();
+ loadKeys(sessionId);
+ closeSession(sessionId);
+ SecureStopId ssid;
+
+ auto res = drmPlugin->getSecureStopIds(
+ [&](Status status, const hidl_vec<SecureStopId>& ids) {
+ EXPECT_EQ(Status::OK, status);
+ EXPECT_EQ(1u, ids.size());
+ ssid = ids[0];
+ });
+ EXPECT_OK(res);
+
+ stat = drmPlugin->removeAllSecureStops();
+ EXPECT_OK(stat);
+
+ Status status = drmPlugin->removeSecureStop(ssid);
+ EXPECT_EQ(Status::BAD_VALUE, status);
+}
+
+/**
+ * Test that removing a secure stop by id works
+ */
+TEST_F(DrmHalClearkeyTest, RemoveSecureStopById) {
+ auto stat = drmPlugin->removeAllSecureStops();
+ EXPECT_OK(stat);
+
+ auto sessionId = openSession();
+ loadKeys(sessionId);
+ closeSession(sessionId);
+ SecureStopId ssid;
+
+ auto res = drmPlugin->getSecureStopIds(
+ [&](Status status, const hidl_vec<SecureStopId>& ids) {
+ EXPECT_EQ(Status::OK, status);
+ EXPECT_EQ(1u, ids.size());
+ ssid = ids[0];
+ });
+ EXPECT_OK(res);
+
+ stat = drmPlugin->removeSecureStop(ssid);
+ EXPECT_OK(stat);
+
+ res = drmPlugin->getSecureStopIds(
+ [&](Status status, const hidl_vec<SecureStopId>& ids) {
+ EXPECT_EQ(Status::OK, status);
+ EXPECT_EQ(0u, ids.size());
+ });
+ EXPECT_OK(res);
+}
+
+
int main(int argc, char** argv) {
::testing::AddGlobalTestEnvironment(DrmHidlEnvironment::Instance());
::testing::InitGoogleTest(&argc, argv);
diff --git a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1BasicTest.cpp b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1BasicTest.cpp
index 17f6744..10591dc 100644
--- a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1BasicTest.cpp
+++ b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworksV1_1BasicTest.cpp
@@ -286,6 +286,169 @@
EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, executionReturnStatus);
}
+class NeuralnetworksInputsOutputsTest
+ : public NeuralnetworksHidlTest,
+ public ::testing::WithParamInterface<std::tuple<bool, bool>> {
+ protected:
+ virtual void SetUp() { NeuralnetworksHidlTest::SetUp(); }
+ virtual void TearDown() { NeuralnetworksHidlTest::TearDown(); }
+ V1_1::Model createModel(const std::vector<uint32_t>& inputs,
+ const std::vector<uint32_t>& outputs) {
+ // We set up the operands as floating-point with no designated
+ // model inputs and outputs, and then patch type and lifetime
+ // later on in this function.
+
+ std::vector<Operand> operands = {
+ {
+ .type = OperandType::TENSOR_FLOAT32,
+ .dimensions = {1},
+ .numberOfConsumers = 1,
+ .scale = 0.0f,
+ .zeroPoint = 0,
+ .lifetime = OperandLifeTime::TEMPORARY_VARIABLE,
+ .location = {.poolIndex = 0, .offset = 0, .length = 0},
+ },
+ {
+ .type = OperandType::TENSOR_FLOAT32,
+ .dimensions = {1},
+ .numberOfConsumers = 1,
+ .scale = 0.0f,
+ .zeroPoint = 0,
+ .lifetime = OperandLifeTime::TEMPORARY_VARIABLE,
+ .location = {.poolIndex = 0, .offset = 0, .length = 0},
+ },
+ {
+ .type = OperandType::INT32,
+ .dimensions = {},
+ .numberOfConsumers = 1,
+ .scale = 0.0f,
+ .zeroPoint = 0,
+ .lifetime = OperandLifeTime::CONSTANT_COPY,
+ .location = {.poolIndex = 0, .offset = 0, .length = sizeof(int32_t)},
+ },
+ {
+ .type = OperandType::TENSOR_FLOAT32,
+ .dimensions = {1},
+ .numberOfConsumers = 0,
+ .scale = 0.0f,
+ .zeroPoint = 0,
+ .lifetime = OperandLifeTime::TEMPORARY_VARIABLE,
+ .location = {.poolIndex = 0, .offset = 0, .length = 0},
+ },
+ };
+
+ const std::vector<Operation> operations = {{
+ .type = OperationType::ADD, .inputs = {0, 1, 2}, .outputs = {3},
+ }};
+
+ std::vector<uint8_t> operandValues;
+ int32_t activation[1] = {static_cast<int32_t>(FusedActivationFunc::NONE)};
+ operandValues.insert(operandValues.end(), reinterpret_cast<const uint8_t*>(&activation[0]),
+ reinterpret_cast<const uint8_t*>(&activation[1]));
+
+ if (kQuantized) {
+ for (auto& operand : operands) {
+ if (operand.type == OperandType::TENSOR_FLOAT32) {
+ operand.type = OperandType::TENSOR_QUANT8_ASYMM;
+ operand.scale = 1.0f;
+ operand.zeroPoint = 0;
+ }
+ }
+ }
+
+ auto patchLifetime = [&operands](const std::vector<uint32_t>& operandIndexes,
+ OperandLifeTime lifetime) {
+ for (uint32_t index : operandIndexes) {
+ operands[index].lifetime = lifetime;
+ }
+ };
+ if (kInputHasPrecedence) {
+ patchLifetime(outputs, OperandLifeTime::MODEL_OUTPUT);
+ patchLifetime(inputs, OperandLifeTime::MODEL_INPUT);
+ } else {
+ patchLifetime(inputs, OperandLifeTime::MODEL_INPUT);
+ patchLifetime(outputs, OperandLifeTime::MODEL_OUTPUT);
+ }
+
+ return {
+ .operands = operands,
+ .operations = operations,
+ .inputIndexes = inputs,
+ .outputIndexes = outputs,
+ .operandValues = operandValues,
+ .pools = {},
+ };
+ }
+ void check(const std::string& name,
+ bool expectation, // true = success
+ const std::vector<uint32_t>& inputs, const std::vector<uint32_t>& outputs) {
+ SCOPED_TRACE(name + " (HAL calls should " + (expectation ? "succeed" : "fail") + ", " +
+ (kInputHasPrecedence ? "input" : "output") + " precedence, " +
+ (kQuantized ? "quantized" : "float"));
+
+ V1_1::Model model = createModel(inputs, outputs);
+
+ // ensure that getSupportedOperations_1_1() checks model validity
+ ErrorStatus supportedOpsErrorStatus = ErrorStatus::GENERAL_FAILURE;
+ Return<void> supportedOpsReturn = device->getSupportedOperations_1_1(
+ model, [&model, &supportedOpsErrorStatus](ErrorStatus status,
+ const hidl_vec<bool>& supported) {
+ supportedOpsErrorStatus = status;
+ if (status == ErrorStatus::NONE) {
+ ASSERT_EQ(supported.size(), model.operations.size());
+ }
+ });
+ ASSERT_TRUE(supportedOpsReturn.isOk());
+ ASSERT_EQ(supportedOpsErrorStatus,
+ (expectation ? ErrorStatus::NONE : ErrorStatus::INVALID_ARGUMENT));
+
+ // ensure that prepareModel_1_1() checks model validity
+ sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback;
+ ASSERT_NE(preparedModelCallback.get(), nullptr);
+ Return<ErrorStatus> prepareLaunchReturn =
+ device->prepareModel_1_1(model, preparedModelCallback);
+ ASSERT_TRUE(prepareLaunchReturn.isOk());
+ ASSERT_TRUE(prepareLaunchReturn == ErrorStatus::NONE ||
+ prepareLaunchReturn == ErrorStatus::INVALID_ARGUMENT);
+ bool preparationOk = (prepareLaunchReturn == ErrorStatus::NONE);
+ if (preparationOk) {
+ preparedModelCallback->wait();
+ preparationOk = (preparedModelCallback->getStatus() == ErrorStatus::NONE);
+ }
+
+ if (preparationOk) {
+ ASSERT_TRUE(expectation);
+ } else {
+ // Preparation can fail for reasons other than an invalid model --
+ // for example, perhaps not all operations are supported, or perhaps
+ // the device hit some kind of capacity limit.
+ bool invalid = prepareLaunchReturn == ErrorStatus::INVALID_ARGUMENT ||
+ preparedModelCallback->getStatus() == ErrorStatus::INVALID_ARGUMENT;
+ ASSERT_NE(expectation, invalid);
+ }
+ }
+
+ // Indicates whether an operand that appears in both the inputs
+ // and outputs vector should have lifetime appropriate for input
+ // rather than for output.
+ const bool kInputHasPrecedence = std::get<0>(GetParam());
+
+ // Indicates whether we should test TENSOR_QUANT8_ASYMM rather
+ // than TENSOR_FLOAT32.
+ const bool kQuantized = std::get<1>(GetParam());
+};
+
+TEST_P(NeuralnetworksInputsOutputsTest, Validate) {
+ check("Ok", true, {0, 1}, {3});
+ check("InputIsOutput", false, {0, 1}, {3, 0});
+ check("OutputIsInput", false, {0, 1, 3}, {3});
+ check("DuplicateInputs", false, {0, 1, 0}, {3});
+ check("DuplicateOutputs", false, {0, 1}, {3, 3});
+}
+
+INSTANTIATE_TEST_CASE_P(Flavor, NeuralnetworksInputsOutputsTest,
+ ::testing::Combine(::testing::Bool(), ::testing::Bool()));
+
} // namespace functional
} // namespace vts
} // namespace V1_1
diff --git a/wifi/1.2/default/android.hardware.wifi@1.0-service.rc b/wifi/1.2/default/android.hardware.wifi@1.0-service.rc
index eecb6d0..cf849d0 100644
--- a/wifi/1.2/default/android.hardware.wifi@1.0-service.rc
+++ b/wifi/1.2/default/android.hardware.wifi@1.0-service.rc
@@ -1,4 +1,5 @@
service vendor.wifi_hal_legacy /vendor/bin/hw/android.hardware.wifi@1.0-service
class hal
+ capabilities NET_ADMIN NET_RAW SYS_MODULE
user wifi
group wifi gps
diff --git a/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp
index 27c8d60..3928c9a 100644
--- a/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp
+++ b/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp
@@ -146,7 +146,7 @@
} else if (type == IfaceType::STA) {
chip_->createStaIface(
[&iface_name](const WifiStatus& status,
- const sp<IWifiStaIface>& iface) {
+ const sp<V1_0::IWifiStaIface>& iface) {
if (WifiStatusCode::SUCCESS == status.code) {
ASSERT_NE(iface.get(), nullptr);
iface->getName([&iface_name](const WifiStatus& status,
diff --git a/wifi/1.2/default/wifi_legacy_hal.cpp b/wifi/1.2/default/wifi_legacy_hal.cpp
index 84af9c4..c314e64 100644
--- a/wifi/1.2/default/wifi_legacy_hal.cpp
+++ b/wifi/1.2/default/wifi_legacy_hal.cpp
@@ -492,6 +492,28 @@
getIfaceHandle(iface_name), program.data(), program.size());
}
+std::pair<wifi_error, std::vector<uint8_t>>
+WifiLegacyHal::readApfPacketFilterData(const std::string& iface_name) {
+ if (global_func_table_.wifi_read_packet_filter == nullptr) {
+ return {WIFI_ERROR_NOT_SUPPORTED, {}};
+ }
+
+ PacketFilterCapabilities caps;
+ wifi_error status = global_func_table_.wifi_get_packet_filter_capabilities(
+ getIfaceHandle(iface_name), &caps.version, &caps.max_len);
+ if (status != WIFI_SUCCESS) {
+ return {status, {}};
+ }
+
+ // Size the buffer to read the entire program & work memory.
+ std::vector<uint8_t> buffer(caps.max_len);
+
+ status = global_func_table_.wifi_read_packet_filter(
+ getIfaceHandle(iface_name), /*src_offset=*/0, buffer.data(),
+ buffer.size());
+ return {status, move(buffer)};
+}
+
std::pair<wifi_error, wifi_gscan_capabilities>
WifiLegacyHal::getGscanCapabilities(const std::string& iface_name) {
wifi_gscan_capabilities caps;
diff --git a/wifi/1.2/default/wifi_legacy_hal.h b/wifi/1.2/default/wifi_legacy_hal.h
index dedbbf8..60905ab 100644
--- a/wifi/1.2/default/wifi_legacy_hal.h
+++ b/wifi/1.2/default/wifi_legacy_hal.h
@@ -156,7 +156,7 @@
* Class that encapsulates all legacy HAL interactions.
* This class manages the lifetime of the event loop thread used by legacy HAL.
*
- * Note: aThere will only be a single instance of this class created in the Wifi
+ * Note: There will only be a single instance of this class created in the Wifi
* object and will be valid for the lifetime of the process.
*/
class WifiLegacyHal {
@@ -188,6 +188,8 @@
const std::string& iface_name);
wifi_error setPacketFilter(const std::string& iface_name,
const std::vector<uint8_t>& program);
+ std::pair<wifi_error, std::vector<uint8_t>> readApfPacketFilterData(
+ const std::string& iface_name);
// Gscan functions.
std::pair<wifi_error, wifi_gscan_capabilities> getGscanCapabilities(
const std::string& iface_name);
diff --git a/wifi/1.2/default/wifi_sta_iface.cpp b/wifi/1.2/default/wifi_sta_iface.cpp
index 6faf009..ab99daa 100644
--- a/wifi/1.2/default/wifi_sta_iface.cpp
+++ b/wifi/1.2/default/wifi_sta_iface.cpp
@@ -94,6 +94,13 @@
hidl_status_cb, cmd_id, program);
}
+Return<void> WifiStaIface::readApfPacketFilterData(
+ readApfPacketFilterData_cb hidl_status_cb) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::readApfPacketFilterDataInternal,
+ hidl_status_cb);
+}
+
Return<void> WifiStaIface::getBackgroundScanCapabilities(
getBackgroundScanCapabilities_cb hidl_status_cb) {
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
@@ -297,6 +304,15 @@
return createWifiStatusFromLegacyError(legacy_status);
}
+std::pair<WifiStatus, std::vector<uint8_t>>
+WifiStaIface::readApfPacketFilterDataInternal() {
+ const std::pair<legacy_hal::wifi_error, std::vector<uint8_t>>
+ legacy_status_and_data =
+ legacy_hal_.lock()->readApfPacketFilterData(ifname_);
+ return {createWifiStatusFromLegacyError(legacy_status_and_data.first),
+ std::move(legacy_status_and_data.second)};
+}
+
std::pair<WifiStatus, StaBackgroundScanCapabilities>
WifiStaIface::getBackgroundScanCapabilitiesInternal() {
legacy_hal::wifi_error legacy_status;
diff --git a/wifi/1.2/default/wifi_sta_iface.h b/wifi/1.2/default/wifi_sta_iface.h
index 423365c..a212888 100644
--- a/wifi/1.2/default/wifi_sta_iface.h
+++ b/wifi/1.2/default/wifi_sta_iface.h
@@ -18,8 +18,8 @@
#define WIFI_STA_IFACE_H_
#include <android-base/macros.h>
-#include <android/hardware/wifi/1.0/IWifiStaIface.h>
#include <android/hardware/wifi/1.0/IWifiStaIfaceEventCallback.h>
+#include <android/hardware/wifi/1.2/IWifiStaIface.h>
#include "hidl_callback_util.h"
#include "wifi_legacy_hal.h"
@@ -34,7 +34,7 @@
/**
* HIDL interface object used to control a STA Iface instance.
*/
-class WifiStaIface : public V1_0::IWifiStaIface {
+class WifiStaIface : public V1_2::IWifiStaIface {
public:
WifiStaIface(const std::string& ifname,
const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
@@ -56,6 +56,8 @@
Return<void> installApfPacketFilter(
uint32_t cmd_id, const hidl_vec<uint8_t>& program,
installApfPacketFilter_cb hidl_status_cb) override;
+ Return<void> readApfPacketFilterData(
+ readApfPacketFilterData_cb hidl_status_cb) override;
Return<void> getBackgroundScanCapabilities(
getBackgroundScanCapabilities_cb hidl_status_cb) override;
Return<void> getValidFrequenciesForBand(
@@ -113,6 +115,8 @@
getApfPacketFilterCapabilitiesInternal();
WifiStatus installApfPacketFilterInternal(
uint32_t cmd_id, const std::vector<uint8_t>& program);
+ std::pair<WifiStatus, std::vector<uint8_t>>
+ readApfPacketFilterDataInternal();
std::pair<WifiStatus, StaBackgroundScanCapabilities>
getBackgroundScanCapabilitiesInternal();
std::pair<WifiStatus, std::vector<WifiChannelInMhz>>
diff --git a/wifi/supplicant/1.1/Android.bp b/wifi/supplicant/1.1/Android.bp
index fafd6ad..832d1ad 100644
--- a/wifi/supplicant/1.1/Android.bp
+++ b/wifi/supplicant/1.1/Android.bp
@@ -8,6 +8,8 @@
},
srcs: [
"ISupplicant.hal",
+ "ISupplicantStaIface.hal",
+ "ISupplicantStaIfaceCallback.hal",
"ISupplicantStaNetwork.hal",
],
interfaces: [
diff --git a/wifi/supplicant/1.1/ISupplicantStaIface.hal b/wifi/supplicant/1.1/ISupplicantStaIface.hal
new file mode 100644
index 0000000..025cc6a
--- /dev/null
+++ b/wifi/supplicant/1.1/ISupplicantStaIface.hal
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant@1.1;
+
+import @1.0::ISupplicantStaIface;
+import @1.1::ISupplicantStaIfaceCallback;
+import @1.0::SupplicantStatus;
+
+/**
+ * Interface exposed by the supplicant for each station mode network
+ * interface (e.g wlan0) it controls.
+ */
+interface ISupplicantStaIface extends @1.0::ISupplicantStaIface {
+
+ /**
+ * Register for callbacks from this interface.
+ *
+ * These callbacks are invoked for events that are specific to this interface.
+ * Registration of multiple callback objects is supported. These objects must
+ * be automatically deleted when the corresponding client process is dead or
+ * if this interface is removed.
+ *
+ * @param callback An instance of the |ISupplicantStaIfaceCallback| HIDL
+ * interface object.
+ * @return status Status of the operation.
+ * Possible status codes:
+ * |SupplicantStatusCode.SUCCESS|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+ */
+ registerCallback_1_1(ISupplicantStaIfaceCallback callback)
+ generates (SupplicantStatus status);
+};
+
diff --git a/wifi/supplicant/1.1/ISupplicantStaIfaceCallback.hal b/wifi/supplicant/1.1/ISupplicantStaIfaceCallback.hal
new file mode 100644
index 0000000..8b92ee5
--- /dev/null
+++ b/wifi/supplicant/1.1/ISupplicantStaIfaceCallback.hal
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant@1.1;
+
+import @1.0::ISupplicantStaIfaceCallback;
+
+/**
+ * Callback Interface exposed by the supplicant service
+ * for each station mode interface (ISupplicantStaIface).
+ *
+ * Clients need to host an instance of this HIDL interface object and
+ * pass a reference of the object to the supplicant via the
+ * corresponding |ISupplicantStaIface.registerCallback_1_1| method.
+ */
+interface ISupplicantStaIfaceCallback extends @1.0::ISupplicantStaIfaceCallback {
+
+ /* EapErrorCode: Error code for EAP or EAP Method as per RFC-4186 */
+ enum EapErrorCode : uint32_t {
+ SIM_GENERAL_FAILURE_AFTER_AUTH = 0,
+ SIM_TEMPORARILY_DENIED = 1026,
+ SIM_NOT_SUBSCRIBED = 1031,
+ SIM_GENERAL_FAILURE_BEFORE_AUTH = 16384,
+ SIM_VENDOR_SPECIFIC_EXPIRED_CERT = 16385,
+ };
+
+ /**
+ * Used to indicate an EAP authentication failure.
+ */
+ oneway onEapFailure_1_1(EapErrorCode errorCode);
+};
+
diff --git a/wifi/supplicant/1.1/vts/functional/Android.bp b/wifi/supplicant/1.1/vts/functional/Android.bp
index 3efe15d..3e65453 100644
--- a/wifi/supplicant/1.1/vts/functional/Android.bp
+++ b/wifi/supplicant/1.1/vts/functional/Android.bp
@@ -40,6 +40,7 @@
srcs: [
"VtsHalWifiSupplicantV1_1TargetTest.cpp",
"supplicant_hidl_test.cpp",
+ "supplicant_sta_iface_hidl_test.cpp",
"supplicant_sta_network_hidl_test.cpp",
],
static_libs: [
diff --git a/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.cpp b/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.cpp
index 3f17740..04a5ed9 100644
--- a/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.cpp
+++ b/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.cpp
@@ -21,6 +21,7 @@
#include "supplicant_hidl_test_utils_1_1.h"
using ::android::hardware::wifi::supplicant::V1_1::ISupplicant;
+using ::android::hardware::wifi::supplicant::V1_1::ISupplicantStaIface;
using ::android::hardware::wifi::supplicant::V1_1::ISupplicantStaNetwork;
using ::android::sp;
@@ -28,6 +29,10 @@
return ISupplicant::castFrom(getSupplicant());
}
+sp<ISupplicantStaIface> getSupplicantStaIface_1_1() {
+ return ISupplicantStaIface::castFrom(getSupplicantStaIface());
+}
+
sp<ISupplicantStaNetwork> createSupplicantStaNetwork_1_1() {
return ISupplicantStaNetwork::castFrom(createSupplicantStaNetwork());
}
diff --git a/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.h b/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.h
index e7ce54a..1c13325 100644
--- a/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.h
+++ b/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.h
@@ -18,11 +18,15 @@
#define SUPPLICANT_HIDL_TEST_UTILS_1_1_H
#include <android/hardware/wifi/supplicant/1.1/ISupplicant.h>
+#include <android/hardware/wifi/supplicant/1.1/ISupplicantStaIface.h>
#include <android/hardware/wifi/supplicant/1.1/ISupplicantStaNetwork.h>
android::sp<android::hardware::wifi::supplicant::V1_1::ISupplicant>
getSupplicant_1_1();
+android::sp<android::hardware::wifi::supplicant::V1_1::ISupplicantStaIface>
+ getSupplicantStaIface_1_1();
+
android::sp<android::hardware::wifi::supplicant::V1_1::ISupplicantStaNetwork>
createSupplicantStaNetwork_1_1();
diff --git a/wifi/supplicant/1.1/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.1/vts/functional/supplicant_sta_iface_hidl_test.cpp
new file mode 100644
index 0000000..c5e6319
--- /dev/null
+++ b/wifi/supplicant/1.1/vts/functional/supplicant_sta_iface_hidl_test.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+#include <android/hardware/wifi/supplicant/1.1/ISupplicantStaIface.h>
+
+#include "supplicant_hidl_test_utils.h"
+#include "supplicant_hidl_test_utils_1_1.h"
+
+using ::android::sp;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::wifi::supplicant::V1_1::ISupplicantStaIface;
+using ::android::hardware::wifi::supplicant::V1_1::ISupplicantStaIfaceCallback;
+using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
+using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
+
+class SupplicantStaIfaceHidlTest
+ : public ::testing::VtsHalHidlTargetTestBase {
+ public:
+ virtual void SetUp() override {
+ startSupplicantAndWaitForHidlService();
+ EXPECT_TRUE(turnOnExcessiveLogging());
+ sta_iface_ = getSupplicantStaIface_1_1();
+ ASSERT_NE(sta_iface_.get(), nullptr);
+ }
+
+ virtual void TearDown() override { stopSupplicant(); }
+
+ protected:
+ // ISupplicantStaIface object used for all tests in this fixture.
+ sp<ISupplicantStaIface> sta_iface_;
+};
+
+class IfaceCallback : public ISupplicantStaIfaceCallback {
+ Return<void> onNetworkAdded(uint32_t /* id */) override { return Void(); }
+ Return<void> onNetworkRemoved(uint32_t /* id */) override { return Void(); }
+ Return<void> onStateChanged(
+ ISupplicantStaIfaceCallback::State /* newState */,
+ const hidl_array<uint8_t, 6>& /*bssid */, uint32_t /* id */,
+ const hidl_vec<uint8_t>& /* ssid */) override {
+ return Void();
+ }
+ Return<void> onAnqpQueryDone(
+ const hidl_array<uint8_t, 6>& /* bssid */,
+ const ISupplicantStaIfaceCallback::AnqpData& /* data */,
+ const ISupplicantStaIfaceCallback::Hs20AnqpData& /* hs20Data */)
+ override {
+ return Void();
+ }
+ virtual Return<void> onHs20IconQueryDone(
+ const hidl_array<uint8_t, 6>& /* bssid */,
+ const hidl_string& /* fileName */,
+ const hidl_vec<uint8_t>& /* data */) override {
+ return Void();
+ }
+ virtual Return<void> onHs20SubscriptionRemediation(
+ const hidl_array<uint8_t, 6>& /* bssid */,
+ ISupplicantStaIfaceCallback::OsuMethod /* osuMethod */,
+ const hidl_string& /* url*/) override {
+ return Void();
+ }
+ Return<void> onHs20DeauthImminentNotice(
+ const hidl_array<uint8_t, 6>& /* bssid */, uint32_t /* reasonCode */,
+ uint32_t /* reAuthDelayInSec */,
+ const hidl_string& /* url */) override {
+ return Void();
+ }
+ Return<void> onDisconnected(const hidl_array<uint8_t, 6>& /* bssid */,
+ bool /* locallyGenerated */,
+ ISupplicantStaIfaceCallback::ReasonCode
+ /* reasonCode */) override {
+ return Void();
+ }
+ Return<void> onAssociationRejected(
+ const hidl_array<uint8_t, 6>& /* bssid */,
+ ISupplicantStaIfaceCallback::StatusCode /* statusCode */,
+ bool /*timedOut */) override {
+ return Void();
+ }
+ Return<void> onAuthenticationTimeout(
+ const hidl_array<uint8_t, 6>& /* bssid */) override {
+ return Void();
+ }
+ Return<void> onBssidChanged(
+ ISupplicantStaIfaceCallback::BssidChangeReason /* reason */,
+ const hidl_array<uint8_t, 6>& /* bssid */) override {
+ return Void();
+ }
+ Return<void> onEapFailure() override { return Void(); }
+ Return<void> onEapFailure_1_1(
+ ISupplicantStaIfaceCallback::EapErrorCode /* eapErrorCode */) override {
+ return Void();
+ }
+ Return<void> onWpsEventSuccess() override { return Void(); }
+ Return<void> onWpsEventFail(
+ const hidl_array<uint8_t, 6>& /* bssid */,
+ ISupplicantStaIfaceCallback::WpsConfigError /* configError */,
+ ISupplicantStaIfaceCallback::WpsErrorIndication /* errorInd */)
+ override {
+ return Void();
+ }
+ Return<void> onWpsEventPbcOverlap() override { return Void(); }
+ Return<void> onExtRadioWorkStart(uint32_t /* id */) override {
+ return Void();
+ }
+ Return<void> onExtRadioWorkTimeout(uint32_t /* id*/) override {
+ return Void();
+ }
+};
+
+/*
+ * RegisterCallback_1_1
+ */
+TEST_F(SupplicantStaIfaceHidlTest, RegisterCallback_1_1) {
+ sta_iface_->registerCallback_1_1(
+ new IfaceCallback(), [](const SupplicantStatus& status) {
+ EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+ });
+}