Merge changes I620f3cc0,I5ff86539
* changes:
gralloc: update doc to reflect security change
[email protected]: Document previously-implicit accessRegion behavior.
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index f9c25d1..2050038 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -62,6 +62,7 @@
"impl/vhal_v2_0/EmulatedVehicleHal.cpp",
"impl/vhal_v2_0/VehicleEmulator.cpp",
"impl/vhal_v2_0/PipeComm.cpp",
+ "impl/vhal_v2_0/ProtoMessageConverter.cpp",
"impl/vhal_v2_0/SocketComm.cpp",
"impl/vhal_v2_0/LinearFakeValueGenerator.cpp",
"impl/vhal_v2_0/JsonFakeValueGenerator.cpp",
@@ -98,6 +99,21 @@
test_suites: ["general-tests"],
}
+cc_test {
+ name: "[email protected]",
+ vendor: true,
+ defaults: ["vhal_v2_0_defaults"],
+ srcs: [
+ "impl/vhal_v2_0/tests/ProtoMessageConverter_test.cpp",
+ ],
+ static_libs: [
+ "[email protected]",
+ "[email protected]",
+ "libprotobuf-cpp-lite",
+ ],
+ test_suites: ["general-tests"],
+}
+
cc_binary {
name: "[email protected]",
defaults: ["vhal_v2_0_defaults"],
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.cpp
index bf1de81..136b2e0 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.cpp
@@ -41,7 +41,7 @@
}
}
-void CommConn::sendMessage(emulator::EmulatorMessage const& msg) {
+void CommConn::sendMessage(vhal_proto::EmulatorMessage const& msg) {
int numBytes = msg.ByteSize();
std::vector<uint8_t> buffer(static_cast<size_t>(numBytes));
if (!msg.SerializeToArray(buffer.data(), numBytes)) {
@@ -61,9 +61,9 @@
break;
}
- emulator::EmulatorMessage rxMsg;
+ vhal_proto::EmulatorMessage rxMsg;
if (rxMsg.ParseFromArray(buffer.data(), static_cast<int32_t>(buffer.size()))) {
- emulator::EmulatorMessage respMsg;
+ vhal_proto::EmulatorMessage respMsg;
mMessageProcessor->processMessage(rxMsg, respMsg);
sendMessage(respMsg);
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.h
index 87b0dfc..6d36da4 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.h
@@ -44,8 +44,8 @@
* Process a single message received over a CommConn. Populate the given respMsg with the reply
* message we should send.
*/
- virtual void processMessage(emulator::EmulatorMessage const& rxMsg,
- emulator::EmulatorMessage& respMsg) = 0;
+ virtual void processMessage(vhal_proto::EmulatorMessage const& rxMsg,
+ vhal_proto::EmulatorMessage& respMsg) = 0;
};
/**
@@ -93,7 +93,7 @@
/**
* Serialized and send the given message to the other side.
*/
- void sendMessage(emulator::EmulatorMessage const& msg);
+ void sendMessage(vhal_proto::EmulatorMessage const& msg);
protected:
std::unique_ptr<std::thread> mReadThread;
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/ProtoMessageConverter.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/ProtoMessageConverter.cpp
new file mode 100644
index 0000000..77cb114
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/ProtoMessageConverter.cpp
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "ProtoMsgConverter"
+
+#include <memory>
+#include <vector>
+
+#include <log/log.h>
+
+#include <vhal_v2_0/VehicleUtils.h>
+
+#include "ProtoMessageConverter.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+namespace proto_msg_converter {
+
+// If protobuf class PROTO_VALUE has value in field PROTO_VARNAME,
+// then casting the value by CAST and copying it to VHAL_TYPE_VALUE->VHAL_TYPE_VARNAME
+#define CHECK_CAST_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(PROTO_VALUE, PROTO_VARNAME, VHAL_TYPE_VALUE, \
+ VHAL_TYPE_VARNAME, CAST) \
+ if (PROTO_VALUE.has_##PROTO_VARNAME()) { \
+ (VHAL_TYPE_VALUE)->VHAL_TYPE_VARNAME = CAST(PROTO_VALUE.PROTO_VARNAME()); \
+ }
+
+// Copying the vector PROTO_VECNAME of protobuf class PROTO_VALUE to
+// VHAL_TYPE_VALUE->VHAL_TYPE_VECNAME, every element of PROTO_VECNAME
+// is casted by CAST
+#define CAST_COPY_PROTOBUF_VEC_TO_VHAL_TYPE(PROTO_VALUE, PROTO_VECNAME, VHAL_TYPE_VALUE, \
+ VHAL_TYPE_VECNAME, CAST) \
+ do { \
+ (VHAL_TYPE_VALUE)->VHAL_TYPE_VECNAME.resize(PROTO_VALUE.PROTO_VECNAME##_size()); \
+ size_t idx = 0; \
+ for (auto& value : PROTO_VALUE.PROTO_VECNAME()) { \
+ VHAL_TYPE_VALUE->VHAL_TYPE_VECNAME[idx++] = CAST(value); \
+ } \
+ } while (0)
+
+// If protobuf message has value in field PROTO_VARNAME,
+// then copying it to VHAL_TYPE_VALUE->VHAL_TYPE_VARNAME
+#define CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(PROTO_VALUE, PROTO_VARNAME, VHAL_TYPE_VALUE, \
+ VHAL_TYPE_VARNAME) \
+ CHECK_CAST_COPY_PROTOBUF_VAR_TO_VHAL_TYPE( \
+ PROTO_VALUE, PROTO_VARNAME, VHAL_TYPE_VALUE, VHAL_TYPE_VARNAME, /*NO CAST*/)
+
+// Copying the vector PROTO_VECNAME of protobuf class PROTO_VALUE to
+// VHAL_TYPE_VALUE->VHAL_TYPE_VECNAME
+#define COPY_PROTOBUF_VEC_TO_VHAL_TYPE(PROTO_VALUE, PROTO_VECNAME, VHAL_TYPE_VALUE, \
+ VHAL_TYPE_VECNAME) \
+ CAST_COPY_PROTOBUF_VEC_TO_VHAL_TYPE( \
+ PROTO_VALUE, PROTO_VECNAME, VHAL_TYPE_VALUE, VHAL_TYPE_VECNAME, /*NO CAST*/)
+
+void toProto(vhal_proto::VehiclePropConfig* protoCfg, const VehiclePropConfig& cfg) {
+ protoCfg->set_prop(cfg.prop);
+ protoCfg->set_access(toInt(cfg.access));
+ protoCfg->set_change_mode(toInt(cfg.changeMode));
+ protoCfg->set_value_type(toInt(getPropType(cfg.prop)));
+
+ for (auto& configElement : cfg.configArray) {
+ protoCfg->add_config_array(configElement);
+ }
+
+ if (cfg.configString.size() > 0) {
+ protoCfg->set_config_string(cfg.configString.c_str(), cfg.configString.size());
+ }
+
+ protoCfg->clear_area_configs();
+ for (auto& areaConfig : cfg.areaConfigs) {
+ auto* protoACfg = protoCfg->add_area_configs();
+ protoACfg->set_area_id(areaConfig.areaId);
+
+ switch (getPropType(cfg.prop)) {
+ case VehiclePropertyType::STRING:
+ case VehiclePropertyType::BOOLEAN:
+ case VehiclePropertyType::INT32_VEC:
+ case VehiclePropertyType::INT64_VEC:
+ case VehiclePropertyType::FLOAT_VEC:
+ case VehiclePropertyType::BYTES:
+ case VehiclePropertyType::MIXED:
+ // Do nothing. These types don't have min/max values
+ break;
+ case VehiclePropertyType::INT64:
+ protoACfg->set_min_int64_value(areaConfig.minInt64Value);
+ protoACfg->set_max_int64_value(areaConfig.maxInt64Value);
+ break;
+ case VehiclePropertyType::FLOAT:
+ protoACfg->set_min_float_value(areaConfig.minFloatValue);
+ protoACfg->set_max_float_value(areaConfig.maxFloatValue);
+ break;
+ case VehiclePropertyType::INT32:
+ protoACfg->set_min_int32_value(areaConfig.minInt32Value);
+ protoACfg->set_max_int32_value(areaConfig.maxInt32Value);
+ break;
+ default:
+ ALOGW("%s: Unknown property type: 0x%x", __func__, toInt(getPropType(cfg.prop)));
+ break;
+ }
+ }
+
+ protoCfg->set_min_sample_rate(cfg.minSampleRate);
+ protoCfg->set_max_sample_rate(cfg.maxSampleRate);
+}
+
+void fromProto(VehiclePropConfig* cfg, const vhal_proto::VehiclePropConfig& protoCfg) {
+ CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoCfg, prop, cfg, prop);
+ CHECK_CAST_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoCfg, access, cfg, access,
+ static_cast<VehiclePropertyAccess>);
+ CHECK_CAST_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoCfg, change_mode, cfg, changeMode,
+ static_cast<VehiclePropertyChangeMode>);
+ COPY_PROTOBUF_VEC_TO_VHAL_TYPE(protoCfg, config_array, cfg, configArray);
+ CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoCfg, config_string, cfg, configString);
+
+ auto cast_to_acfg = [](const vhal_proto::VehicleAreaConfig& protoAcfg) {
+ VehicleAreaConfig acfg;
+ CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoAcfg, area_id, &acfg, areaId);
+ CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoAcfg, min_int32_value, &acfg, minInt32Value);
+ CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoAcfg, max_int32_value, &acfg, maxInt32Value);
+ CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoAcfg, min_int64_value, &acfg, minInt64Value);
+ CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoAcfg, max_int64_value, &acfg, maxInt64Value);
+ CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoAcfg, min_float_value, &acfg, minFloatValue);
+ CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoAcfg, max_float_value, &acfg, maxFloatValue);
+ return acfg;
+ };
+
+ CAST_COPY_PROTOBUF_VEC_TO_VHAL_TYPE(protoCfg, area_configs, cfg, areaConfigs, cast_to_acfg);
+
+ CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoCfg, min_sample_rate, cfg, minSampleRate);
+ CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoCfg, max_sample_rate, cfg, maxSampleRate);
+}
+
+void toProto(vhal_proto::VehiclePropValue* protoVal, const VehiclePropValue& val) {
+ protoVal->set_prop(val.prop);
+ protoVal->set_value_type(toInt(getPropType(val.prop)));
+ protoVal->set_timestamp(val.timestamp);
+ protoVal->set_status((vhal_proto::VehiclePropStatus)(val.status));
+ protoVal->set_area_id(val.areaId);
+
+ // Copy value data if it is set.
+ // - for bytes and strings, this is indicated by size > 0
+ // - for int32, int64, and float, copy the values if vectors have data
+ if (val.value.stringValue.size() > 0) {
+ protoVal->set_string_value(val.value.stringValue.c_str(), val.value.stringValue.size());
+ }
+
+ if (val.value.bytes.size() > 0) {
+ protoVal->set_bytes_value(val.value.bytes.data(), val.value.bytes.size());
+ }
+
+ for (auto& int32Value : val.value.int32Values) {
+ protoVal->add_int32_values(int32Value);
+ }
+
+ for (auto& int64Value : val.value.int64Values) {
+ protoVal->add_int64_values(int64Value);
+ }
+
+ for (auto& floatValue : val.value.floatValues) {
+ protoVal->add_float_values(floatValue);
+ }
+}
+
+void fromProto(VehiclePropValue* val, const vhal_proto::VehiclePropValue& protoVal) {
+ CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoVal, prop, val, prop);
+ CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoVal, timestamp, val, timestamp);
+ CHECK_CAST_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoVal, status, val, status,
+ static_cast<VehiclePropertyStatus>);
+ CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoVal, area_id, val, areaId);
+
+ // Copy value data
+ CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoVal, string_value, val, value.stringValue);
+
+ auto cast_proto_bytes_to_vec = [](auto&& bytes) {
+ return std::vector<uint8_t>(bytes.begin(), bytes.end());
+ };
+ CHECK_CAST_COPY_PROTOBUF_VAR_TO_VHAL_TYPE(protoVal, bytes_value, val, value.bytes,
+ cast_proto_bytes_to_vec);
+
+ COPY_PROTOBUF_VEC_TO_VHAL_TYPE(protoVal, int32_values, val, value.int32Values);
+ COPY_PROTOBUF_VEC_TO_VHAL_TYPE(protoVal, int64_values, val, value.int64Values);
+ COPY_PROTOBUF_VEC_TO_VHAL_TYPE(protoVal, float_values, val, value.floatValues);
+}
+
+#undef COPY_PROTOBUF_VEC_TO_VHAL_TYPE
+#undef CHECK_COPY_PROTOBUF_VAR_TO_VHAL_TYPE
+#undef CAST_COPY_PROTOBUF_VEC_TO_VHAL_TYPE
+#undef CHECK_CAST_COPY_PROTOBUF_VAR_TO_VHAL_TYPE
+
+} // namespace proto_msg_converter
+
+} // namespace impl
+
+} // namespace V2_0
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/ProtoMessageConverter.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/ProtoMessageConverter.h
new file mode 100644
index 0000000..01f3beb
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/ProtoMessageConverter.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_automotive_vehicle_V2_0_impl_ProtoMessageConverter_H_
+#define android_hardware_automotive_vehicle_V2_0_impl_ProtoMessageConverter_H_
+
+#include <android/hardware/automotive/vehicle/2.0/types.h>
+
+#include "VehicleHalProto.pb.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+namespace proto_msg_converter {
+
+// VehiclePropConfig
+
+void toProto(vhal_proto::VehiclePropConfig* protoCfg, const VehiclePropConfig& cfg);
+
+void fromProto(VehiclePropConfig* cfg, const vhal_proto::VehiclePropConfig& protoCfg);
+
+// VehiclePropValue
+
+void toProto(vhal_proto::VehiclePropValue* protoVal, const VehiclePropValue& val);
+
+void fromProto(VehiclePropValue* val, const vhal_proto::VehiclePropValue& protoVal);
+
+} // namespace proto_msg_converter
+
+} // namespace impl
+
+} // namespace V2_0
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_automotive_vehicle_V2_0_impl_VehicleHalEmulator_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.cpp
index 068333c..916c320 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.cpp
@@ -60,7 +60,7 @@
}
}
-void SocketComm::sendMessage(emulator::EmulatorMessage const& msg) {
+void SocketComm::sendMessage(vhal_proto::EmulatorMessage const& msg) {
std::lock_guard<std::mutex> lock(mMutex);
for (std::unique_ptr<SocketConn> const& conn : mOpenConnections) {
conn->sendMessage(msg);
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.h
index 88b852b..52326b9 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.h
@@ -47,7 +47,7 @@
/**
* Serialized and send the given message to all connected clients.
*/
- void sendMessage(emulator::EmulatorMessage const& msg);
+ void sendMessage(vhal_proto::EmulatorMessage const& msg);
private:
int mListenFd;
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp
index 9dc7085..263ca62 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp
@@ -24,6 +24,7 @@
#include <vhal_v2_0/VehicleUtils.h>
#include "PipeComm.h"
+#include "ProtoMessageConverter.h"
#include "SocketComm.h"
#include "VehicleEmulator.h"
@@ -62,11 +63,11 @@
* changed.
*/
void VehicleEmulator::doSetValueFromClient(const VehiclePropValue& propValue) {
- emulator::EmulatorMessage msg;
- emulator::VehiclePropValue *val = msg.add_value();
+ vhal_proto::EmulatorMessage msg;
+ vhal_proto::VehiclePropValue* val = msg.add_value();
populateProtoVehiclePropValue(val, &propValue);
- msg.set_status(emulator::RESULT_OK);
- msg.set_msg_type(emulator::SET_PROPERTY_ASYNC);
+ msg.set_status(vhal_proto::RESULT_OK);
+ msg.set_msg_type(vhal_proto::SET_PROPERTY_ASYNC);
mSocketComm->sendMessage(msg);
if (mPipeComm) {
@@ -77,17 +78,17 @@
void VehicleEmulator::doGetConfig(VehicleEmulator::EmulatorMessage const& rxMsg,
VehicleEmulator::EmulatorMessage& respMsg) {
std::vector<VehiclePropConfig> configs = mHal->listProperties();
- emulator::VehiclePropGet getProp = rxMsg.prop(0);
+ vhal_proto::VehiclePropGet getProp = rxMsg.prop(0);
- respMsg.set_msg_type(emulator::GET_CONFIG_RESP);
- respMsg.set_status(emulator::ERROR_INVALID_PROPERTY);
+ respMsg.set_msg_type(vhal_proto::GET_CONFIG_RESP);
+ respMsg.set_status(vhal_proto::ERROR_INVALID_PROPERTY);
for (auto& config : configs) {
// Find the config we are looking for
if (config.prop == getProp.prop()) {
- emulator::VehiclePropConfig* protoCfg = respMsg.add_config();
+ vhal_proto::VehiclePropConfig* protoCfg = respMsg.add_config();
populateProtoVehicleConfig(protoCfg, config);
- respMsg.set_status(emulator::RESULT_OK);
+ respMsg.set_status(vhal_proto::RESULT_OK);
break;
}
}
@@ -97,11 +98,11 @@
VehicleEmulator::EmulatorMessage& respMsg) {
std::vector<VehiclePropConfig> configs = mHal->listProperties();
- respMsg.set_msg_type(emulator::GET_CONFIG_ALL_RESP);
- respMsg.set_status(emulator::RESULT_OK);
+ respMsg.set_msg_type(vhal_proto::GET_CONFIG_ALL_RESP);
+ respMsg.set_status(vhal_proto::RESULT_OK);
for (auto& config : configs) {
- emulator::VehiclePropConfig* protoCfg = respMsg.add_config();
+ vhal_proto::VehiclePropConfig* protoCfg = respMsg.add_config();
populateProtoVehicleConfig(protoCfg, config);
}
}
@@ -109,11 +110,11 @@
void VehicleEmulator::doGetProperty(VehicleEmulator::EmulatorMessage const& rxMsg,
VehicleEmulator::EmulatorMessage& respMsg) {
int32_t areaId = 0;
- emulator::VehiclePropGet getProp = rxMsg.prop(0);
+ vhal_proto::VehiclePropGet getProp = rxMsg.prop(0);
int32_t propId = getProp.prop();
- emulator::Status status = emulator::ERROR_INVALID_PROPERTY;
+ vhal_proto::Status status = vhal_proto::ERROR_INVALID_PROPERTY;
- respMsg.set_msg_type(emulator::GET_PROPERTY_RESP);
+ respMsg.set_msg_type(vhal_proto::GET_PROPERTY_RESP);
if (getProp.has_area_id()) {
areaId = getProp.area_id();
@@ -127,9 +128,9 @@
StatusCode halStatus;
auto val = mHal->get(request, &halStatus);
if (val != nullptr) {
- emulator::VehiclePropValue* protoVal = respMsg.add_value();
+ vhal_proto::VehiclePropValue* protoVal = respMsg.add_value();
populateProtoVehiclePropValue(protoVal, val.get());
- status = emulator::RESULT_OK;
+ status = vhal_proto::RESULT_OK;
}
}
@@ -138,12 +139,12 @@
void VehicleEmulator::doGetPropertyAll(VehicleEmulator::EmulatorMessage const& /* rxMsg */,
VehicleEmulator::EmulatorMessage& respMsg) {
- respMsg.set_msg_type(emulator::GET_PROPERTY_ALL_RESP);
- respMsg.set_status(emulator::RESULT_OK);
+ respMsg.set_msg_type(vhal_proto::GET_PROPERTY_ALL_RESP);
+ respMsg.set_status(vhal_proto::RESULT_OK);
{
for (const auto& prop : mHal->getAllProperties()) {
- emulator::VehiclePropValue* protoVal = respMsg.add_value();
+ vhal_proto::VehiclePropValue* protoVal = respMsg.add_value();
populateProtoVehiclePropValue(protoVal, &prop);
}
}
@@ -151,7 +152,7 @@
void VehicleEmulator::doSetProperty(VehicleEmulator::EmulatorMessage const& rxMsg,
VehicleEmulator::EmulatorMessage& respMsg) {
- emulator::VehiclePropValue protoVal = rxMsg.value(0);
+ vhal_proto::VehiclePropValue protoVal = rxMsg.value(0);
VehiclePropValue val = {
.timestamp = elapsedRealtimeNano(),
.areaId = protoVal.area_id(),
@@ -159,7 +160,7 @@
.status = (VehiclePropertyStatus)protoVal.status(),
};
- respMsg.set_msg_type(emulator::SET_PROPERTY_RESP);
+ respMsg.set_msg_type(vhal_proto::SET_PROPERTY_RESP);
// Copy value data if it is set. This automatically handles complex data types if needed.
if (protoVal.has_string_value()) {
@@ -187,120 +188,42 @@
}
bool halRes = mHal->setPropertyFromVehicle(val);
- respMsg.set_status(halRes ? emulator::RESULT_OK : emulator::ERROR_INVALID_PROPERTY);
+ respMsg.set_status(halRes ? vhal_proto::RESULT_OK : vhal_proto::ERROR_INVALID_PROPERTY);
}
-void VehicleEmulator::processMessage(emulator::EmulatorMessage const& rxMsg,
- emulator::EmulatorMessage& respMsg) {
+void VehicleEmulator::processMessage(vhal_proto::EmulatorMessage const& rxMsg,
+ vhal_proto::EmulatorMessage& respMsg) {
switch (rxMsg.msg_type()) {
- case emulator::GET_CONFIG_CMD:
+ case vhal_proto::GET_CONFIG_CMD:
doGetConfig(rxMsg, respMsg);
break;
- case emulator::GET_CONFIG_ALL_CMD:
+ case vhal_proto::GET_CONFIG_ALL_CMD:
doGetConfigAll(rxMsg, respMsg);
break;
- case emulator::GET_PROPERTY_CMD:
+ case vhal_proto::GET_PROPERTY_CMD:
doGetProperty(rxMsg, respMsg);
break;
- case emulator::GET_PROPERTY_ALL_CMD:
+ case vhal_proto::GET_PROPERTY_ALL_CMD:
doGetPropertyAll(rxMsg, respMsg);
break;
- case emulator::SET_PROPERTY_CMD:
+ case vhal_proto::SET_PROPERTY_CMD:
doSetProperty(rxMsg, respMsg);
break;
default:
ALOGW("%s: Unknown message received, type = %d", __func__, rxMsg.msg_type());
- respMsg.set_status(emulator::ERROR_UNIMPLEMENTED_CMD);
+ respMsg.set_status(vhal_proto::ERROR_UNIMPLEMENTED_CMD);
break;
}
}
-void VehicleEmulator::populateProtoVehicleConfig(emulator::VehiclePropConfig* protoCfg,
+void VehicleEmulator::populateProtoVehicleConfig(vhal_proto::VehiclePropConfig* protoCfg,
const VehiclePropConfig& cfg) {
- protoCfg->set_prop(cfg.prop);
- protoCfg->set_access(toInt(cfg.access));
- protoCfg->set_change_mode(toInt(cfg.changeMode));
- protoCfg->set_value_type(toInt(getPropType(cfg.prop)));
-
- for (auto& configElement : cfg.configArray) {
- protoCfg->add_config_array(configElement);
- }
-
- if (cfg.configString.size() > 0) {
- protoCfg->set_config_string(cfg.configString.c_str(), cfg.configString.size());
- }
-
- // Populate the min/max values based on property type
- switch (getPropType(cfg.prop)) {
- case VehiclePropertyType::STRING:
- case VehiclePropertyType::BOOLEAN:
- case VehiclePropertyType::INT32_VEC:
- case VehiclePropertyType::INT64_VEC:
- case VehiclePropertyType::FLOAT_VEC:
- case VehiclePropertyType::BYTES:
- case VehiclePropertyType::MIXED:
- // Do nothing. These types don't have min/max values
- break;
- case VehiclePropertyType::INT64:
- if (cfg.areaConfigs.size() > 0) {
- emulator::VehicleAreaConfig* aCfg = protoCfg->add_area_configs();
- aCfg->set_min_int64_value(cfg.areaConfigs[0].minInt64Value);
- aCfg->set_max_int64_value(cfg.areaConfigs[0].maxInt64Value);
- }
- break;
- case VehiclePropertyType::FLOAT:
- if (cfg.areaConfigs.size() > 0) {
- emulator::VehicleAreaConfig* aCfg = protoCfg->add_area_configs();
- aCfg->set_min_float_value(cfg.areaConfigs[0].minFloatValue);
- aCfg->set_max_float_value(cfg.areaConfigs[0].maxFloatValue);
- }
- break;
- case VehiclePropertyType::INT32:
- if (cfg.areaConfigs.size() > 0) {
- emulator::VehicleAreaConfig* aCfg = protoCfg->add_area_configs();
- aCfg->set_min_int32_value(cfg.areaConfigs[0].minInt32Value);
- aCfg->set_max_int32_value(cfg.areaConfigs[0].maxInt32Value);
- }
- break;
- default:
- ALOGW("%s: Unknown property type: 0x%x", __func__, toInt(getPropType(cfg.prop)));
- break;
- }
-
- protoCfg->set_min_sample_rate(cfg.minSampleRate);
- protoCfg->set_max_sample_rate(cfg.maxSampleRate);
+ return proto_msg_converter::toProto(protoCfg, cfg);
}
-void VehicleEmulator::populateProtoVehiclePropValue(emulator::VehiclePropValue* protoVal,
+void VehicleEmulator::populateProtoVehiclePropValue(vhal_proto::VehiclePropValue* protoVal,
const VehiclePropValue* val) {
- protoVal->set_prop(val->prop);
- protoVal->set_value_type(toInt(getPropType(val->prop)));
- protoVal->set_timestamp(val->timestamp);
- protoVal->set_status((emulator::VehiclePropStatus)(val->status));
- protoVal->set_area_id(val->areaId);
-
- // Copy value data if it is set.
- // - for bytes and strings, this is indicated by size > 0
- // - for int32, int64, and float, copy the values if vectors have data
- if (val->value.stringValue.size() > 0) {
- protoVal->set_string_value(val->value.stringValue.c_str(), val->value.stringValue.size());
- }
-
- if (val->value.bytes.size() > 0) {
- protoVal->set_bytes_value(val->value.bytes.data(), val->value.bytes.size());
- }
-
- for (auto& int32Value : val->value.int32Values) {
- protoVal->add_int32_values(int32Value);
- }
-
- for (auto& int64Value : val->value.int64Values) {
- protoVal->add_int64_values(int64Value);
- }
-
- for (auto& floatValue : val->value.floatValues) {
- protoVal->add_float_values(floatValue);
- }
+ return proto_msg_converter::toProto(protoVal, *val);
}
} // impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h
index 58e387a..82947be 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h
@@ -72,21 +72,21 @@
virtual ~VehicleEmulator();
void doSetValueFromClient(const VehiclePropValue& propValue);
- void processMessage(emulator::EmulatorMessage const& rxMsg,
- emulator::EmulatorMessage& respMsg) override;
+ void processMessage(vhal_proto::EmulatorMessage const& rxMsg,
+ vhal_proto::EmulatorMessage& respMsg) override;
private:
friend class ConnectionThread;
- using EmulatorMessage = emulator::EmulatorMessage;
+ using EmulatorMessage = vhal_proto::EmulatorMessage;
void doGetConfig(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg);
void doGetConfigAll(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg);
void doGetProperty(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg);
void doGetPropertyAll(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg);
void doSetProperty(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg);
- void populateProtoVehicleConfig(emulator::VehiclePropConfig* protoCfg,
+ void populateProtoVehicleConfig(vhal_proto::VehiclePropConfig* protoCfg,
const VehiclePropConfig& cfg);
- void populateProtoVehiclePropValue(emulator::VehiclePropValue* protoVal,
+ void populateProtoVehiclePropValue(vhal_proto::VehiclePropValue* protoVal,
const VehiclePropValue* val);
private:
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleHalProto.proto b/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleHalProto.proto
index 04df5a8..4902a5d 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleHalProto.proto
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleHalProto.proto
@@ -16,7 +16,7 @@
syntax = "proto2";
-package emulator;
+package vhal_proto;
// CMD messages are from workstation --> VHAL
// RESP messages are from VHAL --> workstation
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleServer.proto b/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleServer.proto
index 7ce3c32..2cc6595 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleServer.proto
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/VehicleServer.proto
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-syntax = "proto2";
+syntax = "proto3";
-package emulator;
+package vhal_proto;
import "google/protobuf/empty.proto";
import "VehicleHalProto.proto";
@@ -32,7 +32,7 @@
}
message VehicleHalCallStatus {
- required VehicleHalStatusCode status_code = 1;
+ VehicleHalStatusCode status_code = 1;
}
service VehicleServer {
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/ProtoMessageConverter_test.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/ProtoMessageConverter_test.cpp
new file mode 100644
index 0000000..3817e44
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/tests/ProtoMessageConverter_test.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2019 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 <gtest/gtest.h>
+
+#include <utils/SystemClock.h>
+
+#include "vhal_v2_0/DefaultConfig.h"
+#include "vhal_v2_0/ProtoMessageConverter.h"
+#include "vhal_v2_0/VehicleUtils.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+namespace impl {
+namespace proto_msg_converter {
+
+namespace {
+
+void CheckPropConfigConversion(const VehiclePropConfig& config) {
+ vhal_proto::VehiclePropConfig protoCfg;
+ VehiclePropConfig tmpConfig;
+
+ toProto(&protoCfg, config);
+ fromProto(&tmpConfig, protoCfg);
+
+ EXPECT_EQ(config.prop, tmpConfig.prop);
+ EXPECT_EQ(config.access, tmpConfig.access);
+ EXPECT_EQ(config.changeMode, tmpConfig.changeMode);
+ EXPECT_EQ(config.configString, tmpConfig.configString);
+ EXPECT_EQ(config.minSampleRate, tmpConfig.minSampleRate);
+ EXPECT_EQ(config.maxSampleRate, tmpConfig.maxSampleRate);
+ EXPECT_EQ(config.configArray, tmpConfig.configArray);
+
+ EXPECT_EQ(config.areaConfigs.size(), tmpConfig.areaConfigs.size());
+
+ auto cfgType = getPropType(config.prop);
+ for (size_t idx = 0; idx < std::min(config.areaConfigs.size(), tmpConfig.areaConfigs.size());
+ ++idx) {
+ auto& lhs = config.areaConfigs[idx];
+ auto& rhs = tmpConfig.areaConfigs[idx];
+ EXPECT_EQ(lhs.areaId, rhs.areaId);
+ switch (cfgType) {
+ case VehiclePropertyType::INT64:
+ EXPECT_EQ(lhs.minInt64Value, rhs.minInt64Value);
+ EXPECT_EQ(lhs.maxInt64Value, rhs.maxInt64Value);
+ break;
+ case VehiclePropertyType::FLOAT:
+ EXPECT_EQ(lhs.minFloatValue, rhs.minFloatValue);
+ EXPECT_EQ(lhs.maxFloatValue, rhs.maxFloatValue);
+ break;
+ case VehiclePropertyType::INT32:
+ EXPECT_EQ(lhs.minInt32Value, rhs.minInt32Value);
+ EXPECT_EQ(lhs.maxInt32Value, rhs.maxInt32Value);
+ break;
+ default:
+ // ignore min/max values
+ break;
+ }
+ }
+}
+
+void CheckPropValueConversion(const VehiclePropValue& val) {
+ vhal_proto::VehiclePropValue protoVal;
+ VehiclePropValue tmpVal;
+
+ toProto(&protoVal, val);
+ fromProto(&tmpVal, protoVal);
+
+ EXPECT_EQ(val, tmpVal);
+}
+
+TEST(ProtoMessageConverterTest, basic) {
+ for (auto& property : impl::kVehicleProperties) {
+ CheckPropConfigConversion(property.config);
+
+ VehiclePropValue prop;
+ prop.timestamp = elapsedRealtimeNano();
+ prop.areaId = 123;
+ prop.prop = property.config.prop;
+ prop.value = property.initialValue;
+ prop.status = VehiclePropertyStatus::ERROR;
+ CheckPropValueConversion(prop);
+ }
+}
+
+} // namespace
+
+} // namespace proto_msg_converter
+} // namespace impl
+} // namespace V2_0
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/camera/metadata/3.5/types.hal b/camera/metadata/3.5/types.hal
index 2fd8a0d..62899ec 100644
--- a/camera/metadata/3.5/types.hal
+++ b/camera/metadata/3.5/types.hal
@@ -35,12 +35,22 @@
* '/system/media/camera/docs/docs.html' in the corresponding Android source tree.</p>
*/
enum CameraMetadataTag : @3.4::CameraMetadataTag {
- /** android.control.availableBokehCapabilities [static, int32[], public]
+ /** android.control.availableBokehMaxSizes [static, int32[], ndk_public]
*
- * <p>The list of bokeh modes that are supported by this camera device, and each bokeh mode's
- * maximum streaming (non-stall) size with bokeh effect.</p>
+ * <p>The list of bokeh modes for ANDROID_CONTROL_BOKEH_MODE that are supported by this camera
+ * device, and each bokeh mode's maximum streaming (non-stall) size with bokeh effect.</p>
+ *
+ * @see ANDROID_CONTROL_BOKEH_MODE
*/
- ANDROID_CONTROL_AVAILABLE_BOKEH_CAPABILITIES = [email protected]::CameraMetadataTag:ANDROID_CONTROL_END_3_3,
+ ANDROID_CONTROL_AVAILABLE_BOKEH_MAX_SIZES = [email protected]::CameraMetadataTag:ANDROID_CONTROL_END_3_3,
+
+ /** android.control.availableBokehZoomRatioRanges [static, float[], ndk_public]
+ *
+ * <p>The ranges of supported zoom ratio for non-OFF ANDROID_CONTROL_BOKEH_MODE.</p>
+ *
+ * @see ANDROID_CONTROL_BOKEH_MODE
+ */
+ ANDROID_CONTROL_AVAILABLE_BOKEH_ZOOM_RATIO_RANGES,
/** android.control.bokehMode [dynamic, enum, public]
*
@@ -48,6 +58,18 @@
*/
ANDROID_CONTROL_BOKEH_MODE,
+ /** android.control.zoomRatioRange [static, float[], public]
+ *
+ * <p>Minimum and maximum zoom ratios supported by this camera device.</p>
+ */
+ ANDROID_CONTROL_ZOOM_RATIO_RANGE,
+
+ /** android.control.zoomRatio [dynamic, float, public]
+ *
+ * <p>The desired zoom ratio</p>
+ */
+ ANDROID_CONTROL_ZOOM_RATIO,
+
ANDROID_CONTROL_END_3_5,
};
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 69ec0d9..650ec8b 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -20,6 +20,7 @@
#include <chrono>
#include <mutex>
#include <regex>
+#include <string>
#include <unordered_map>
#include <unordered_set>
#include <condition_variable>
@@ -755,6 +756,7 @@
const hidl_vec<hidl_string>& deviceNames);
void verifyCameraCharacteristics(Status status, const CameraMetadata& chars);
void verifyBokehCharacteristics(const camera_metadata_t* metadata);
+ void verifyZoomCharacteristics(const camera_metadata_t* metadata);
void verifyRecommendedConfigs(const CameraMetadata& metadata);
void verifyMonochromeCharacteristics(const CameraMetadata& chars, int deviceVersion);
void verifyMonochromeCameraResult(
@@ -776,6 +778,8 @@
void verifySessionReconfigurationQuery(sp<device::V3_5::ICameraDeviceSession> session3_5,
camera_metadata* oldSessionParams, camera_metadata* newSessionParams);
+ void verifyRequestTemplate(const camera_metadata_t* metadata, RequestTemplate requestTemplate);
+
bool isDepthOnly(camera_metadata_t* staticMeta);
static Status getAvailableOutputStreams(const camera_metadata_t *staticMeta,
@@ -2857,13 +2861,7 @@
metadata, &expectedSize);
ASSERT_TRUE((result == 0) ||
(result == CAMERA_METADATA_VALIDATION_SHIFTED));
- size_t entryCount =
- get_camera_metadata_entry_count(metadata);
- // TODO: we can do better than 0 here. Need to check how many required
- // request keys we've defined for each template
- ASSERT_GT(entryCount, 0u);
- ALOGI("template %u metadata entry count is %zu",
- t, entryCount);
+ verifyRequestTemplate(metadata, reqTemplate);
} else {
ASSERT_EQ(0u, req.size());
}
@@ -5671,6 +5669,11 @@
return;
}
+ camera_metadata_ro_entry entry;
+ int retcode = find_camera_metadata_ro_entry(metadata,
+ ANDROID_CONTROL_ZOOM_RATIO_RANGE, &entry);
+ bool hasZoomRatioRange = (0 == retcode && entry.count == 2);
+
std::string version, cameraId;
ASSERT_TRUE(::matchDeviceName(cameraName, mProviderType, &version, &cameraId));
std::unordered_set<std::string> physicalIds;
@@ -5678,15 +5681,37 @@
for (auto physicalId : physicalIds) {
ASSERT_NE(physicalId, cameraId);
bool isPublicId = false;
+ std::string fullPublicId;
for (auto& deviceName : deviceNames) {
std::string publicVersion, publicId;
ASSERT_TRUE(::matchDeviceName(deviceName, mProviderType, &publicVersion, &publicId));
if (physicalId == publicId) {
isPublicId = true;
+ fullPublicId = deviceName;
break;
}
}
if (isPublicId) {
+ ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> subDevice;
+ Return<void> ret;
+ ret = mProvider->getCameraDeviceInterface_V3_x(
+ fullPublicId, [&](auto status, const auto& device) {
+ ASSERT_EQ(Status::OK, status);
+ ASSERT_NE(device, nullptr);
+ subDevice = device;
+ });
+ ASSERT_TRUE(ret.isOk());
+
+ ret = subDevice->getCameraCharacteristics(
+ [&](auto status, const auto& chars) {
+ ASSERT_EQ(Status::OK, status);
+ retcode = find_camera_metadata_ro_entry(
+ (const camera_metadata_t *)chars.data(),
+ ANDROID_CONTROL_ZOOM_RATIO_RANGE, &entry);
+ bool subCameraHasZoomRatioRange = (0 == retcode && entry.count == 2);
+ ASSERT_EQ(hasZoomRatioRange, subCameraHasZoomRatioRange);
+ });
+ ASSERT_TRUE(ret.isOk());
continue;
}
@@ -5702,6 +5727,12 @@
[&](auto status, const auto& chars) {
verifyCameraCharacteristics(status, chars);
verifyMonochromeCharacteristics(chars, deviceVersion);
+
+ retcode = find_camera_metadata_ro_entry(
+ (const camera_metadata_t *)chars.data(),
+ ANDROID_CONTROL_ZOOM_RATIO_RANGE, &entry);
+ bool subCameraHasZoomRatioRange = (0 == retcode && entry.count == 2);
+ ASSERT_EQ(hasZoomRatioRange, subCameraHasZoomRatioRange);
});
ASSERT_TRUE(ret.isOk());
@@ -5721,8 +5752,7 @@
// Make sure ANDROID_LOGICAL_MULTI_CAMERA_ACTIVE_PHYSICAL_ID is available in
// result keys.
if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_5) {
- camera_metadata_ro_entry entry;
- int retcode = find_camera_metadata_ro_entry(metadata,
+ retcode = find_camera_metadata_ro_entry(metadata,
ANDROID_REQUEST_AVAILABLE_RESULT_KEYS, &entry);
if ((0 == retcode) && (entry.count > 0)) {
ASSERT_NE(std::find(entry.data.i32, entry.data.i32 + entry.count,
@@ -5822,6 +5852,7 @@
}
verifyBokehCharacteristics(metadata);
+ verifyZoomCharacteristics(metadata);
}
void CameraHidlTest::verifyBokehCharacteristics(const camera_metadata_t* metadata) {
@@ -5852,38 +5883,51 @@
retcode = find_camera_metadata_ro_entry(metadata,
ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, &entry);
- bool hasBokehCharacteristicsKey = false;
+ bool hasBokehMaxSizesKey = false;
+ bool hasBokehZoomRatioRangesKey = false;
if ((0 == retcode) && (entry.count > 0)) {
- hasBokehCharacteristicsKey = std::find(entry.data.i32, entry.data.i32+entry.count,
- ANDROID_CONTROL_AVAILABLE_BOKEH_CAPABILITIES) != entry.data.i32+entry.count;
+ hasBokehMaxSizesKey = std::find(entry.data.i32, entry.data.i32+entry.count,
+ ANDROID_CONTROL_AVAILABLE_BOKEH_MAX_SIZES) != entry.data.i32+entry.count;
+ hasBokehZoomRatioRangesKey = std::find(entry.data.i32, entry.data.i32+entry.count,
+ ANDROID_CONTROL_AVAILABLE_BOKEH_ZOOM_RATIO_RANGES) != entry.data.i32+entry.count;
} else {
ADD_FAILURE() << "Get camera availableCharacteristicsKeys failed!";
}
+
+ camera_metadata_ro_entry maxSizesEntry;
retcode = find_camera_metadata_ro_entry(metadata,
- ANDROID_CONTROL_AVAILABLE_BOKEH_CAPABILITIES, &entry);
- bool hasAvailableBokehCaps = (0 == retcode && entry.count > 0);
+ ANDROID_CONTROL_AVAILABLE_BOKEH_MAX_SIZES, &maxSizesEntry);
+ bool hasBokehMaxSizes = (0 == retcode && maxSizesEntry.count > 0);
+
+ camera_metadata_ro_entry zoomRatioRangesEntry;
+ retcode = find_camera_metadata_ro_entry(metadata,
+ ANDROID_CONTROL_AVAILABLE_BOKEH_ZOOM_RATIO_RANGES, &zoomRatioRangesEntry);
+ bool hasBokehZoomRatioRanges = (0 == retcode && zoomRatioRangesEntry.count > 0);
// Bokeh keys must all be available, or all be unavailable.
- bool noBokeh = !hasBokehRequestKey && !hasBokehResultKey && !hasBokehCharacteristicsKey &&
- !hasAvailableBokehCaps;
+ bool noBokeh = !hasBokehRequestKey && !hasBokehResultKey && !hasBokehMaxSizesKey &&
+ !hasBokehZoomRatioRangesKey && !hasBokehMaxSizes && !hasBokehZoomRatioRanges;
if (noBokeh) {
return;
}
- bool hasBokeh = hasBokehRequestKey && hasBokehResultKey && hasBokehCharacteristicsKey &&
- hasAvailableBokehCaps;
+ bool hasBokeh = hasBokehRequestKey && hasBokehResultKey && hasBokehMaxSizesKey &&
+ hasBokehZoomRatioRangesKey && hasBokehMaxSizes && hasBokehZoomRatioRanges;
ASSERT_TRUE(hasBokeh);
// Must have OFF, and must have one of STILL_CAPTURE and CONTINUOUS.
- ASSERT_TRUE(entry.count == 6 || entry.count == 9);
+ // Only valid combinations: {OFF, CONTINUOUS}, {OFF, STILL_CAPTURE}, and
+ // {OFF, CONTINUOUS, STILL_CAPTURE}.
+ ASSERT_TRUE((maxSizesEntry.count == 6 && zoomRatioRangesEntry.count == 2) ||
+ (maxSizesEntry.count == 9 && zoomRatioRangesEntry.count == 4));
bool hasOffMode = false;
bool hasStillCaptureMode = false;
bool hasContinuousMode = false;
std::vector<AvailableStream> outputStreams;
ASSERT_EQ(Status::OK, getAvailableOutputStreams(metadata, outputStreams));
- for (int i = 0; i < entry.count; i += 3) {
- int32_t mode = entry.data.i32[i];
- int32_t maxWidth = entry.data.i32[i+1];
- int32_t maxHeight = entry.data.i32[i+2];
+ for (int i = 0, j = 0; i < maxSizesEntry.count && j < zoomRatioRangesEntry.count; i += 3) {
+ int32_t mode = maxSizesEntry.data.i32[i];
+ int32_t maxWidth = maxSizesEntry.data.i32[i+1];
+ int32_t maxHeight = maxSizesEntry.data.i32[i+2];
switch (mode) {
case ANDROID_CONTROL_BOKEH_MODE_OFF:
hasOffMode = true;
@@ -5891,9 +5935,11 @@
break;
case ANDROID_CONTROL_BOKEH_MODE_STILL_CAPTURE:
hasStillCaptureMode = true;
+ j += 2;
break;
case ANDROID_CONTROL_BOKEH_MODE_CONTINUOUS:
hasContinuousMode = true;
+ j += 2;
break;
default:
ADD_FAILURE() << "Invalid bokehMode advertised: " << mode;
@@ -5901,6 +5947,7 @@
}
if (mode != ANDROID_CONTROL_BOKEH_MODE_OFF) {
+ // Make sure size is supported.
bool sizeSupported = false;
for (const auto& stream : outputStreams) {
if ((stream.format == static_cast<int32_t>(PixelFormat::YCBCR_420_888) ||
@@ -5911,12 +5958,102 @@
}
}
ASSERT_TRUE(sizeSupported);
+
+ // Make sure zoom range is valid
+ float minZoomRatio = zoomRatioRangesEntry.data.f[0];
+ float maxZoomRatio = zoomRatioRangesEntry.data.f[1];
+ ASSERT_GT(minZoomRatio, 0.0f);
+ ASSERT_LE(minZoomRatio, maxZoomRatio);
}
}
ASSERT_TRUE(hasOffMode);
ASSERT_TRUE(hasStillCaptureMode || hasContinuousMode);
}
+void CameraHidlTest::verifyZoomCharacteristics(const camera_metadata_t* metadata) {
+ camera_metadata_ro_entry entry;
+ int retcode = 0;
+
+ // Check key availability in capabilities, request and result.
+ retcode = find_camera_metadata_ro_entry(metadata,
+ ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM, &entry);
+ float maxDigitalZoom = 1.0;
+ if ((0 == retcode) && (entry.count == 1)) {
+ maxDigitalZoom = entry.data.f[0];
+ } else {
+ ADD_FAILURE() << "Get camera scalerAvailableMaxDigitalZoom failed!";
+ }
+
+ retcode = find_camera_metadata_ro_entry(metadata,
+ ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS, &entry);
+ bool hasZoomRequestKey = false;
+ if ((0 == retcode) && (entry.count > 0)) {
+ hasZoomRequestKey = std::find(entry.data.i32, entry.data.i32+entry.count,
+ ANDROID_CONTROL_ZOOM_RATIO) != entry.data.i32+entry.count;
+ } else {
+ ADD_FAILURE() << "Get camera availableRequestKeys failed!";
+ }
+
+ retcode = find_camera_metadata_ro_entry(metadata,
+ ANDROID_REQUEST_AVAILABLE_RESULT_KEYS, &entry);
+ bool hasZoomResultKey = false;
+ if ((0 == retcode) && (entry.count > 0)) {
+ hasZoomResultKey = std::find(entry.data.i32, entry.data.i32+entry.count,
+ ANDROID_CONTROL_ZOOM_RATIO) != entry.data.i32+entry.count;
+ } else {
+ ADD_FAILURE() << "Get camera availableResultKeys failed!";
+ }
+
+ retcode = find_camera_metadata_ro_entry(metadata,
+ ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, &entry);
+ bool hasZoomCharacteristicsKey = false;
+ if ((0 == retcode) && (entry.count > 0)) {
+ hasZoomCharacteristicsKey = std::find(entry.data.i32, entry.data.i32+entry.count,
+ ANDROID_CONTROL_ZOOM_RATIO_RANGE) != entry.data.i32+entry.count;
+ } else {
+ ADD_FAILURE() << "Get camera availableCharacteristicsKeys failed!";
+ }
+
+ retcode = find_camera_metadata_ro_entry(metadata,
+ ANDROID_CONTROL_ZOOM_RATIO_RANGE, &entry);
+ bool hasZoomRatioRange = (0 == retcode && entry.count == 2);
+
+ // Zoom keys must all be available, or all be unavailable.
+ bool noZoomRatio = !hasZoomRequestKey && !hasZoomResultKey && !hasZoomCharacteristicsKey &&
+ !hasZoomRatioRange;
+ if (noZoomRatio) {
+ return;
+ }
+ bool hasZoomRatio = hasZoomRequestKey && hasZoomResultKey && hasZoomCharacteristicsKey &&
+ hasZoomRatioRange;
+ ASSERT_TRUE(hasZoomRatio);
+
+ float minZoomRatio = entry.data.f[0];
+ float maxZoomRatio = entry.data.f[1];
+ if (maxDigitalZoom != maxZoomRatio) {
+ ADD_FAILURE() << "Maximum zoom ratio is different than maximum digital zoom!";
+ }
+ if (minZoomRatio > maxZoomRatio) {
+ ADD_FAILURE() << "Maximum zoom ratio is less than minimum zoom ratio!";
+ }
+ if (minZoomRatio > 1.0f) {
+ ADD_FAILURE() << "Minimum zoom ratio is more than 1.0!";
+ }
+ if (maxZoomRatio < 1.0f) {
+ ADD_FAILURE() << "Maximum zoom ratio is less than 1.0!";
+ }
+
+ // Make sure CROPPING_TYPE is CENTER_ONLY
+ retcode = find_camera_metadata_ro_entry(metadata,
+ ANDROID_SCALER_CROPPING_TYPE, &entry);
+ if ((0 == retcode) && (entry.count == 1)) {
+ int8_t croppingType = entry.data.u8[0];
+ ASSERT_EQ(croppingType, ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY);
+ } else {
+ ADD_FAILURE() << "Get camera scalerCroppingType failed!";
+ }
+}
+
void CameraHidlTest::verifyMonochromeCharacteristics(const CameraMetadata& chars,
int deviceVersion) {
const camera_metadata_t* metadata = (camera_metadata_t*)chars.data();
@@ -6415,6 +6552,26 @@
}
}
+void CameraHidlTest::verifyRequestTemplate(const camera_metadata_t* metadata,
+ RequestTemplate requestTemplate) {
+ ASSERT_NE(nullptr, metadata);
+ size_t entryCount =
+ get_camera_metadata_entry_count(metadata);
+ ALOGI("template %u metadata entry count is %zu", (int32_t)requestTemplate, entryCount);
+ // TODO: we can do better than 0 here. Need to check how many required
+ // request keys we've defined for each template
+ ASSERT_GT(entryCount, 0u);
+
+ // Check zoomRatio
+ camera_metadata_ro_entry zoomRatioEntry;
+ int foundZoomRatio = find_camera_metadata_ro_entry(metadata,
+ ANDROID_CONTROL_ZOOM_RATIO, &zoomRatioEntry);
+ if (foundZoomRatio == 0) {
+ ASSERT_EQ(zoomRatioEntry.count, 1);
+ ASSERT_EQ(zoomRatioEntry.data.f[0], 1.0f);
+ }
+}
+
INSTANTIATE_TEST_SUITE_P(
PerInstance, CameraHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(ICameraProvider::descriptor)),
diff --git a/current.txt b/current.txt
index 279167f..30bee15 100644
--- a/current.txt
+++ b/current.txt
@@ -586,7 +586,6 @@
d3a344b7bd4c0d2658ae7209f55a979b8f53f361fd00f4fca29d5baa56d11fd2 [email protected]::types
2410dd02d67786a732d36e80b0f8ccf55086604ef37f9838e2013ff2c571e404 [email protected]::types
cd06a7911b9acd4a653bbf7133888878fbcb3f84be177c7a3f1becaae3d8618f [email protected]::types
-2bdc6baf3f80f7a87fb5a5d03599e2ee37aadd3dbb107b7c9c060657702942a8 [email protected]::types
b69a7615c508acf5c5201efd1bfa3262167874fc3594e2db5a3ff93addd8ac75 [email protected]::IKeymasterDevice
eb2fa0c883c2185d514be0b84c179b283753ef0c1b77b45b4f359bd23bba8b75 [email protected]::IPreparedModel
f1109cbb10297b7429a11fab42afa912710b303c9bf20bd5cdb8bd57b9c84186 [email protected]::types
@@ -651,12 +650,12 @@
94e803236398bed1febb11cc21051bc42ec003700139b099d6c479e02a7ca3c3 [email protected]::IPreparedModelCallback
cf1d55e8c68300090747ab90b94c22e4c859b29c84ced68a317c595bb115eab2 [email protected]::types
3e01d4446cd69fd1c48f8572efd97487bc179564b32bd795800b97bbe10be37b [email protected]::IWifi
-03d37dfebbc27b13adce1ed6389ac483bf7cf32488ca14037c5569bc3e903e4f [email protected]::IHostapd
+36b3acf78ac4ecf8156be8741c1d8332cdce7a1ebf4dfa1562952f14a94e6c87 [email protected]::IHostapd
2defa258951e25a132aaeb36e3febe6f41bf9c6dbb1b1ebdf0b41708ab4e107e [email protected]::types
a64467bae843569f0d465c5be7f0c7a5b987985b55a3ef4794dd5afc68538650 [email protected]::ISupplicant
-44445b8a03d7b9e68b2fbd954672c18a8fce9e32851b0692f4f4ab3407f86ecb [email protected]::ISupplicantStaIface
+213457930af81ff3ea344fbc9d4a0d0a2bb70527f96b7b6a32ee3b5e4c17057e [email protected]::ISupplicantStaIface
619fc9839ec6e369cfa9b28e3e9412e6885720ff8f9b5750c1b6ffb905120391 [email protected]::ISupplicantStaIfaceCallback
-c9273429fcf98d797d3bb07fdba6f1be95bf960f9255cde169fd1ca4db85f856 [email protected]::ISupplicantStaNetwork
+a6163000e2804472924733bcf8b4269db776460cc4df64f9c4dc8350d7aeafc5 [email protected]::ISupplicantStaNetwork
9b0a3ab6f4f74b971ed094426d8a443e29b512ff03e1ab50c07156396cdb2483 [email protected]::types
0e3c23f1c815469fdcdc39bc33a486817771c7c6b6e5303f2f25569499fc6c69 [email protected]::types
2bc87cde08fcd8d9a0f5d4a2b8560ea793264d94f5b763a6b22d4a63d0f3cd5a [email protected]::IRadio
diff --git a/graphics/common/aidl/android/hardware/graphics/common/Cta861_3.aidl b/graphics/common/aidl/android/hardware/graphics/common/Cta861_3.aidl
new file mode 100644
index 0000000..4fbc6b2
--- /dev/null
+++ b/graphics/common/aidl/android/hardware/graphics/common/Cta861_3.aidl
@@ -0,0 +1,34 @@
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.common;
+
+/**
+ * HDR static metadata extension as specified by CTA-861.3.
+ *
+ * This is an AIDL counterpart of the NDK struct `AHdrMetadata_cta861_3`.
+ */
+@VintfStability
+parcelable Cta861_3 {
+ /**
+ * Maximum content light level.
+ */
+ float maxContentLightLevel;
+ /**
+ * Maximum frame average light level.
+ */
+ float maxFrameAverageLightLevel;
+}
diff --git a/graphics/common/aidl/android/hardware/graphics/common/Smpte2086.aidl b/graphics/common/aidl/android/hardware/graphics/common/Smpte2086.aidl
new file mode 100644
index 0000000..60614cd
--- /dev/null
+++ b/graphics/common/aidl/android/hardware/graphics/common/Smpte2086.aidl
@@ -0,0 +1,51 @@
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.common;
+import android.hardware.graphics.common.XyColor;
+
+/**
+ * Mastering display metadata as specified by SMPTE ST 2086.
+ *
+ * This is an AIDL counterpart of the NDK struct `AHdrMetadata_smpte2086`.
+ */
+@VintfStability
+parcelable Smpte2086 {
+ /**
+ * CIE XYZ chromaticity for red in the RGB primaries.
+ */
+ XyColor primaryRed;
+ /**
+ * CIE XYZ chromaticity for green in the RGB primaries.
+ */
+ XyColor primaryGreen;
+ /**
+ * CIE XYZ chromaticity for blue in the RGB primaries.
+ */
+ XyColor primaryBlue;
+ /**
+ * CIE XYZ chromaticity for the white point.
+ */
+ XyColor whitePoint;
+ /**
+ * Maximum luminance in candelas per square meter.
+ */
+ float maxLuminance;
+ /**
+ * Minimum luminance in candelas per square meter.
+ */
+ float minLuminance;
+}
diff --git a/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl b/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl
index e5a189e..43cf672 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl
@@ -288,4 +288,43 @@
* 4 bytes written in little endian.
*/
BLEND_MODE = 17,
+
+ /**
+ * Can be used to get or set static HDR metadata specified by SMPTE ST 2086.
+ *
+ * This metadata is a stable aidl android.hardware.graphics.common.Smpte2086.
+ *
+ * This is not used in tone mapping until it has been set for the first time.
+ *
+ * When it is encoded into a byte stream, each float member is represented by 4 bytes written in
+ * little endian. The ordering of float values follows the definition of Smpte2086 and XyColor.
+ * If this is unset when encoded into a byte stream, the byte stream is empty.
+ */
+ SMPTE2086 = 18,
+
+ /**
+ * Can be used to get or set static HDR metadata specified by CTA 861.3.
+ *
+ * This metadata is a stable aidl android.hardware.graphics.common.Cta861_3.
+ *
+ * This is not used in tone mapping until it has been set for the first time.
+ *
+ * When it is encoded into a byte stream, each float member is represented by 4 bytes written in
+ * little endian. The ordering of float values follows the definition of Cta861_3.
+ * If this is unset when encoded into a byte stream, the byte stream is empty.
+ */
+ CTA861_3 = 19,
+
+ /**
+ * Can be used to get or set dynamic HDR metadata specified by SMPTE ST 2094-40:2016.
+ *
+ * This metadata is uint8_t byte array.
+ *
+ * This is not used in tone mapping until it has been set for the first time.
+ *
+ * When it is encoded into a byte stream, the length of the HDR metadata byte array is written
+ * using 8 bytes in little endian. It is followed by the uint8_t byte array.
+ * If this is unset when encoded into a byte stream, the byte stream is empty.
+ */
+ SMPTE2094_40 = 20,
}
diff --git a/graphics/common/aidl/android/hardware/graphics/common/XyColor.aidl b/graphics/common/aidl/android/hardware/graphics/common/XyColor.aidl
new file mode 100644
index 0000000..9571273
--- /dev/null
+++ b/graphics/common/aidl/android/hardware/graphics/common/XyColor.aidl
@@ -0,0 +1,30 @@
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.common;
+
+/**
+ * Chromaticity based on 2 parameters.
+ *
+ * This is an AIDL counterpart of the NDK struct `AColor_xy`.
+ *
+ * @note This can be used to represent any 2-dimensional chromaticity.
+ */
+@VintfStability
+parcelable XyColor {
+ float x;
+ float y;
+}
diff --git a/graphics/mapper/4.0/IMapper.hal b/graphics/mapper/4.0/IMapper.hal
index d024c6e..93c85bd 100644
--- a/graphics/mapper/4.0/IMapper.hal
+++ b/graphics/mapper/4.0/IMapper.hal
@@ -481,7 +481,7 @@
* particular Metadata field.
*
* The framework may attempt to set the following StandardMetadataType
- * values: DATASPACE, PER_FRAME_METADATA, PER_FRAME_METADATA_BLOB and BLEND_MODE.
+ * values: DATASPACE, SMPTE2086, CTA861_3, SMPTE2094_40 and BLEND_MODE.
* We strongly encourage everyone to support setting as many of those fields as
* possible. If a device's Composer implementation supports a field, it should be
* supported here. Over time these metadata fields will be moved out of
diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
index c4b1c53..2aad242 100644
--- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
+++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
@@ -44,11 +44,13 @@
using android::hardware::graphics::common::V1_2::PixelFormat;
using MetadataType = android::hardware::graphics::mapper::V4_0::IMapper::MetadataType;
using aidl::android::hardware::graphics::common::BlendMode;
+using aidl::android::hardware::graphics::common::Cta861_3;
using aidl::android::hardware::graphics::common::Dataspace;
using aidl::android::hardware::graphics::common::ExtendableType;
using aidl::android::hardware::graphics::common::PlaneLayout;
using aidl::android::hardware::graphics::common::PlaneLayoutComponent;
using aidl::android::hardware::graphics::common::PlaneLayoutComponentType;
+using aidl::android::hardware::graphics::common::Smpte2086;
using aidl::android::hardware::graphics::common::StandardMetadataType;
using DecodeFunction = std::function<void(const IMapper::BufferDescriptorInfo& descriptorInfo,
@@ -1020,6 +1022,42 @@
}
/**
+ * Test IMapper::get(Smpte2086)
+ */
+TEST_P(GraphicsMapperHidlTest, GetSmpte2086) {
+ testGet(mDummyDescriptorInfo, gralloc4::MetadataType_Smpte2086,
+ [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+ std::optional<Smpte2086> smpte2086;
+ ASSERT_EQ(NO_ERROR, gralloc4::decodeSmpte2086(vec, &smpte2086));
+ EXPECT_FALSE(smpte2086.has_value());
+ });
+}
+
+/**
+ * Test IMapper::get(Cta861_3)
+ */
+TEST_P(GraphicsMapperHidlTest, GetCta861_3) {
+ testGet(mDummyDescriptorInfo, gralloc4::MetadataType_Cta861_3,
+ [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+ std::optional<Cta861_3> cta861_3;
+ ASSERT_EQ(NO_ERROR, gralloc4::decodeCta861_3(vec, &cta861_3));
+ EXPECT_FALSE(cta861_3.has_value());
+ });
+}
+
+/**
+ * Test IMapper::get(Smpte2094_40)
+ */
+TEST_P(GraphicsMapperHidlTest, GetSmpte2094_40) {
+ testGet(mDummyDescriptorInfo, gralloc4::MetadataType_Smpte2094_40,
+ [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+ std::optional<std::vector<uint8_t>> smpte2094_40;
+ ASSERT_EQ(NO_ERROR, gralloc4::decodeSmpte2094_40(vec, &smpte2094_40));
+ EXPECT_FALSE(smpte2094_40.has_value());
+ });
+}
+
+/**
* Test IMapper::get(metadata) with a bad buffer
*/
TEST_P(GraphicsMapperHidlTest, GetMetadataBadValue) {
@@ -1072,6 +1110,15 @@
ASSERT_EQ(Error::BAD_BUFFER,
mGralloc->get(bufferHandle, gralloc4::MetadataType_BlendMode, &vec));
ASSERT_EQ(0, vec.size());
+ ASSERT_EQ(Error::BAD_BUFFER,
+ mGralloc->get(bufferHandle, gralloc4::MetadataType_Smpte2086, &vec));
+ ASSERT_EQ(0, vec.size());
+ ASSERT_EQ(Error::BAD_BUFFER,
+ mGralloc->get(bufferHandle, gralloc4::MetadataType_Cta861_3, &vec));
+ ASSERT_EQ(0, vec.size());
+ ASSERT_EQ(Error::BAD_BUFFER,
+ mGralloc->get(bufferHandle, gralloc4::MetadataType_Smpte2094_40, &vec));
+ ASSERT_EQ(0, vec.size());
}
/**
@@ -1428,6 +1475,90 @@
}
/**
+ * Test IMapper::set(Smpte2086)
+ */
+TEST_P(GraphicsMapperHidlTest, SetSmpte2086) {
+ /**
+ * DISPLAY_P3 is a color space that uses the DCI_P3 primaries,
+ * the D65 white point and the SRGB transfer functions.
+ * Rendering Intent: Colorimetric
+ * Primaries:
+ * x y
+ * green 0.265 0.690
+ * blue 0.150 0.060
+ * red 0.680 0.320
+ * white (D65) 0.3127 0.3290
+ */
+ std::optional<Smpte2086> smpte2086;
+ smpte2086->primaryRed.x = 0.680;
+ smpte2086->primaryRed.y = 0.320;
+ smpte2086->primaryGreen.x = 0.265;
+ smpte2086->primaryGreen.y = 0.690;
+ smpte2086->primaryBlue.x = 0.150;
+ smpte2086->primaryBlue.y = 0.060;
+ smpte2086->whitePoint.x = 0.3127;
+ smpte2086->whitePoint.y = 0.3290;
+ smpte2086->maxLuminance = 100.0;
+ smpte2086->minLuminance = 0.1;
+
+ hidl_vec<uint8_t> vec;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeSmpte2086(smpte2086, &vec));
+
+ testSet(mDummyDescriptorInfo, gralloc4::MetadataType_Smpte2086, vec,
+ [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+ std::optional<Smpte2086> realSmpte2086;
+ ASSERT_EQ(NO_ERROR, gralloc4::decodeSmpte2086(vec, &realSmpte2086));
+ ASSERT_TRUE(realSmpte2086.has_value());
+ EXPECT_EQ(smpte2086->primaryRed.x, realSmpte2086->primaryRed.x);
+ EXPECT_EQ(smpte2086->primaryRed.y, realSmpte2086->primaryRed.y);
+ EXPECT_EQ(smpte2086->primaryGreen.x, realSmpte2086->primaryGreen.x);
+ EXPECT_EQ(smpte2086->primaryGreen.y, realSmpte2086->primaryGreen.y);
+ EXPECT_EQ(smpte2086->primaryBlue.x, realSmpte2086->primaryBlue.x);
+ EXPECT_EQ(smpte2086->primaryBlue.y, realSmpte2086->primaryBlue.y);
+ EXPECT_EQ(smpte2086->whitePoint.x, realSmpte2086->whitePoint.x);
+ EXPECT_EQ(smpte2086->whitePoint.y, realSmpte2086->whitePoint.y);
+ EXPECT_EQ(smpte2086->maxLuminance, realSmpte2086->maxLuminance);
+ EXPECT_EQ(smpte2086->minLuminance, realSmpte2086->minLuminance);
+ });
+}
+
+/**
+ * Test IMapper::set(Cta8613)
+ */
+TEST_P(GraphicsMapperHidlTest, SetCta861_3) {
+ std::optional<Cta861_3> cta861_3;
+ cta861_3->maxContentLightLevel = 78.0;
+ cta861_3->maxFrameAverageLightLevel = 62.0;
+
+ hidl_vec<uint8_t> vec;
+ ASSERT_EQ(NO_ERROR, gralloc4::encodeCta861_3(cta861_3, &vec));
+
+ testSet(mDummyDescriptorInfo, gralloc4::MetadataType_Cta861_3, vec,
+ [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+ std::optional<Cta861_3> realCta861_3;
+ ASSERT_EQ(NO_ERROR, gralloc4::decodeCta861_3(vec, &realCta861_3));
+ ASSERT_TRUE(realCta861_3.has_value());
+ EXPECT_EQ(cta861_3->maxContentLightLevel, realCta861_3->maxContentLightLevel);
+ EXPECT_EQ(cta861_3->maxFrameAverageLightLevel,
+ realCta861_3->maxFrameAverageLightLevel);
+ });
+}
+
+/**
+ * Test IMapper::set(Smpte2094_40)
+ */
+TEST_P(GraphicsMapperHidlTest, SetSmpte2094_40) {
+ hidl_vec<uint8_t> vec;
+
+ testSet(mDummyDescriptorInfo, gralloc4::MetadataType_Smpte2094_40, vec,
+ [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+ std::optional<std::vector<uint8_t>> realSmpte2094_40;
+ ASSERT_EQ(NO_ERROR, gralloc4::decodeSmpte2094_40(vec, &realSmpte2094_40));
+ EXPECT_FALSE(realSmpte2094_40.has_value());
+ });
+}
+
+/**
* Test IMapper::set(metadata) with a bad buffer
*/
TEST_P(GraphicsMapperHidlTest, SetMetadataNullBuffer) {
@@ -1462,6 +1593,11 @@
mGralloc->set(bufferHandle, gralloc4::MetadataType_Dataspace, vec));
ASSERT_EQ(Error::BAD_BUFFER,
mGralloc->set(bufferHandle, gralloc4::MetadataType_BlendMode, vec));
+ ASSERT_EQ(Error::BAD_BUFFER,
+ mGralloc->set(bufferHandle, gralloc4::MetadataType_Smpte2086, vec));
+ ASSERT_EQ(Error::BAD_BUFFER, mGralloc->set(bufferHandle, gralloc4::MetadataType_Cta861_3, vec));
+ ASSERT_EQ(Error::BAD_BUFFER,
+ mGralloc->set(bufferHandle, gralloc4::MetadataType_Smpte2094_40, vec));
}
/**
@@ -1521,6 +1657,10 @@
mGralloc->set(bufferHandle, gralloc4::MetadataType_Dataspace, vec));
ASSERT_EQ(Error::UNSUPPORTED,
mGralloc->set(bufferHandle, gralloc4::MetadataType_BlendMode, vec));
+ ASSERT_EQ(Error::UNSUPPORTED,
+ mGralloc->set(bufferHandle, gralloc4::MetadataType_Smpte2086, vec));
+ ASSERT_EQ(Error::UNSUPPORTED,
+ mGralloc->set(bufferHandle, gralloc4::MetadataType_Cta861_3, vec));
}
/**
@@ -1753,6 +1893,45 @@
}
/**
+ * Test IMapper::getFromBufferDescriptorInfo(Smpte2086)
+ */
+TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoSmpte2086) {
+ hidl_vec<uint8_t> vec;
+ ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo(
+ mDummyDescriptorInfo, gralloc4::MetadataType_Smpte2086, &vec));
+
+ std::optional<Smpte2086> smpte2086;
+ ASSERT_EQ(NO_ERROR, gralloc4::decodeSmpte2086(vec, &smpte2086));
+ EXPECT_FALSE(smpte2086.has_value());
+}
+
+/**
+ * Test IMapper::getFromBufferDescriptorInfo(Cta861_3)
+ */
+TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoCta861_3) {
+ hidl_vec<uint8_t> vec;
+ ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo(
+ mDummyDescriptorInfo, gralloc4::MetadataType_Cta861_3, &vec));
+
+ std::optional<Cta861_3> cta861_3;
+ ASSERT_EQ(NO_ERROR, gralloc4::decodeCta861_3(vec, &cta861_3));
+ EXPECT_FALSE(cta861_3.has_value());
+}
+
+/**
+ * Test IMapper::getFromBufferDescriptorInfo(Smpte2094_40)
+ */
+TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoSmpte2094_40) {
+ hidl_vec<uint8_t> vec;
+ ASSERT_EQ(Error::NONE,
+ mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo,
+ gralloc4::MetadataType_Smpte2094_40, &vec));
+ std::optional<std::vector<uint8_t>> smpte2094_40;
+ ASSERT_EQ(NO_ERROR, gralloc4::decodeSmpte2094_40(vec, &smpte2094_40));
+ EXPECT_FALSE(smpte2094_40.has_value());
+}
+
+/**
* Test IMapper::getFromBufferDescriptorInfo(metadata) for unsupported metadata
*/
TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoUnsupportedMetadata) {
diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
index 35a2fb1..f78eb43 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -423,27 +423,33 @@
EXPECT_EQ(ErrorCode::OK, error);
if (avb_verification_enabled()) {
- property_get("ro.boot.vbmeta.digest", property_value, "nogood");
- EXPECT_NE(strcmp(property_value, "nogood"), 0);
+ EXPECT_NE(property_get("ro.boot.vbmeta.digest", property_value, ""), 0);
string prop_string(property_value);
EXPECT_EQ(prop_string.size(), 64);
EXPECT_EQ(prop_string, bin2hex(verified_boot_hash));
- property_get("ro.boot.vbmeta.device_state", property_value, "nogood");
- EXPECT_NE(strcmp(property_value, "nogood"), 0);
+ EXPECT_NE(property_get("ro.boot.vbmeta.device_state", property_value, ""), 0);
if (!strcmp(property_value, "unlocked")) {
EXPECT_FALSE(device_locked);
} else {
EXPECT_TRUE(device_locked);
}
+
+ // Check that the expected result from VBMeta matches the build type. Only a user build
+ // should have AVB reporting the device is locked.
+ EXPECT_NE(property_get("ro.build.type", property_value, ""), 0);
+ if (!strcmp(property_value, "user")) {
+ EXPECT_TRUE(device_locked);
+ } else {
+ EXPECT_FALSE(device_locked);
+ }
}
// Verified boot key should be all 0's if the boot state is not verified or self signed
std::string empty_boot_key(32, '\0');
std::string verified_boot_key_str((const char*)verified_boot_key.data(),
verified_boot_key.size());
- property_get("ro.boot.verifiedbootstate", property_value, "nogood");
- EXPECT_NE(property_value, "nogood");
+ EXPECT_NE(property_get("ro.boot.verifiedbootstate", property_value, ""), 0);
if (!strcmp(property_value, "green")) {
EXPECT_EQ(verified_boot_state, KM_VERIFIED_BOOT_VERIFIED);
EXPECT_NE(0, memcmp(verified_boot_key.data(), empty_boot_key.data(),
@@ -546,7 +552,7 @@
EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::RSA));
EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
<< "Key size " << key_size << "missing";
- EXPECT_TRUE(crypto_params.Contains(TAG_RSA_PUBLIC_EXPONENT, 3U));
+ EXPECT_TRUE(crypto_params.Contains(TAG_RSA_PUBLIC_EXPONENT, 65537U));
CheckedDeleteKey(&key_blob);
}
diff --git a/rebootescrow/aidl/default/Android.bp b/rebootescrow/aidl/default/Android.bp
new file mode 100644
index 0000000..eb228ad
--- /dev/null
+++ b/rebootescrow/aidl/default/Android.bp
@@ -0,0 +1,47 @@
+//
+// Copyright (C) 2019 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.
+//
+
+cc_library_static {
+ name: "libhadamardutils",
+ vendor_available: true,
+ host_supported: true,
+ shared_libs: [
+ "libbase",
+ ],
+ srcs: [
+ "HadamardUtils.cpp",
+ ],
+ visibility: [
+ ":__subpackages__",
+ ],
+}
+
+cc_test {
+ name: "HadamardUtilsTest",
+ host_supported: true,
+ srcs: [
+ "HadamardUtilsTest.cpp",
+ ],
+ static_libs: [
+ "libhadamardutils",
+ "libgtest_prod",
+ ],
+ shared_libs: [
+ "liblog",
+ "libbase",
+ ],
+ test_suites: ["device-tests"],
+}
diff --git a/rebootescrow/aidl/default/HadamardUtils.cpp b/rebootescrow/aidl/default/HadamardUtils.cpp
new file mode 100644
index 0000000..5853d2d
--- /dev/null
+++ b/rebootescrow/aidl/default/HadamardUtils.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2019 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 <HadamardUtils.h>
+
+#include <android-base/logging.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace rebootescrow {
+namespace hadamard {
+
+constexpr auto BYTE_LENGTH = 8u;
+
+std::vector<uint8_t> BitsetToBytes(const std::bitset<ENCODE_LENGTH>& encoded_bits) {
+ CHECK_EQ(0, (encoded_bits.size() % BYTE_LENGTH));
+ std::vector<uint8_t> result;
+ for (size_t i = 0; i < encoded_bits.size(); i += 8) {
+ uint8_t current = 0;
+ // Set each byte starting from the LSB.
+ for (size_t j = 0; j < BYTE_LENGTH; j++) {
+ CHECK_LE(i + j, encoded_bits.size());
+ if (encoded_bits[i + j]) {
+ current |= (1u << j);
+ }
+ }
+ result.push_back(current);
+ }
+ return result;
+}
+
+std::bitset<ENCODE_LENGTH> BytesToBitset(const std::vector<uint8_t>& encoded) {
+ CHECK_EQ(ENCODE_LENGTH, encoded.size() * BYTE_LENGTH);
+
+ std::bitset<ENCODE_LENGTH> result;
+ size_t offset = 0;
+ for (const auto& byte : encoded) {
+ // Set each byte starting from the LSB.
+ for (size_t j = 0; j < BYTE_LENGTH; j++) {
+ result[offset + j] = byte & (1u << j);
+ }
+ offset += BYTE_LENGTH;
+ }
+ return result;
+}
+
+// The encoding is equivalent to multiply the word with the generator matrix (and take the module
+// of 2). Here is an example of encoding a number with 3 bits. The encoded length is thus
+// 2^(3-1) = 4 bits.
+// |1 1 1 1| |0|
+// |0 1 1| * |0 0 1 1| = |1|
+// |0 1 0 1| |1|
+// |0|
+std::bitset<ENCODE_LENGTH> EncodeWord(uint16_t word) {
+ std::bitset<ENCODE_LENGTH> result;
+ for (uint64_t i = ENCODE_LENGTH; i < 2 * ENCODE_LENGTH; i++) {
+ uint32_t wi = word & i;
+ // Sum all the bits in the word and check its parity.
+ wi ^= wi >> 8u;
+ wi ^= wi >> 4u;
+ wi ^= wi >> 2u;
+ wi ^= wi >> 1u;
+ result[i - ENCODE_LENGTH] = wi & 1u;
+ }
+ return result;
+}
+
+std::vector<uint8_t> EncodeKey(const std::vector<uint8_t>& key) {
+ CHECK_EQ(KEY_SIZE_IN_BYTES, key.size());
+
+ std::vector<uint8_t> result;
+ for (size_t i = 0; i < key.size(); i += 2) {
+ uint16_t word = static_cast<uint16_t>(key[i + 1]) << BYTE_LENGTH | key[i];
+ auto encoded_bits = EncodeWord(word);
+ auto byte_array = BitsetToBytes(encoded_bits);
+ std::move(byte_array.begin(), byte_array.end(), std::back_inserter(result));
+ }
+ return result;
+}
+
+std::vector<uint8_t> DecodeKey(const std::vector<uint8_t>& encoded) {
+ CHECK_EQ(0, (encoded.size() * 8) % ENCODE_LENGTH);
+ std::vector<uint8_t> result;
+ for (size_t i = 0; i < encoded.size(); i += ENCODE_LENGTH / 8) {
+ auto current =
+ std::vector<uint8_t>{encoded.begin() + i, encoded.begin() + i + ENCODE_LENGTH / 8};
+ auto bits = BytesToBitset(current);
+ auto candidates = DecodeWord(bits);
+ CHECK(!candidates.empty());
+ // TODO(xunchang) Do we want to try other candidates?
+ uint16_t val = candidates.top().second;
+ result.push_back(val & 0xffu);
+ result.push_back(val >> BYTE_LENGTH);
+ }
+
+ return result;
+}
+
+std::priority_queue<std::pair<int32_t, uint16_t>> DecodeWord(
+ const std::bitset<ENCODE_LENGTH>& encoded) {
+ std::vector<int32_t> scores;
+ scores.reserve(ENCODE_LENGTH);
+ // Convert 0 -> -1 in the encoded bits. e.g [0, 1, 1, 0] -> [-1, 1, 1, -1]
+ for (uint32_t i = 0; i < ENCODE_LENGTH; i++) {
+ scores.push_back(2 * encoded[i] - 1);
+ }
+
+ // Multiply the hadamard matrix by the transformed input.
+ // |1 1 1 1| |-1| | 0|
+ // |1 -1 1 -1| * | 1| = | 0|
+ // |1 1 -1 -1| | 1| | 0|
+ // |1 -1 -1 1| |-1| |-4|
+ for (uint32_t i = 0; i < CODE_K; i++) {
+ uint16_t step = 1u << i;
+ for (uint32_t j = 0; j < ENCODE_LENGTH; j += 2 * step) {
+ for (uint32_t k = j; k < j + step; k++) {
+ auto a0 = scores[k];
+ auto a1 = scores[k + step];
+ scores[k] = a0 + a1;
+ scores[k + step] = a0 - a1;
+ }
+ }
+ }
+
+ // Assign the corresponding score to each index; larger score indicates higher probability. e.g.
+ // value 3, encoding [0, 1, 1, 0] -> score: 4
+ // value 7, encoding [1, 0, 0, 1] (3's complement) -> score: -4
+ std::priority_queue<std::pair<int32_t, uint16_t>> candidates;
+ // TODO(xunchang) limit the candidate size since we don't need all of them?
+ for (uint32_t i = 0; i < scores.size(); i++) {
+ candidates.emplace(-scores[i], i);
+ candidates.emplace(scores[i], (1u << CODE_K) | i);
+ }
+
+ CHECK_EQ(2 * ENCODE_LENGTH, candidates.size());
+ return candidates;
+}
+
+} // namespace hadamard
+} // namespace rebootescrow
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/rebootescrow/aidl/default/HadamardUtils.h b/rebootescrow/aidl/default/HadamardUtils.h
new file mode 100644
index 0000000..21cfc78
--- /dev/null
+++ b/rebootescrow/aidl/default/HadamardUtils.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#include <bitset>
+#include <queue>
+#include <utility>
+#include <vector>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace rebootescrow {
+namespace hadamard {
+
+constexpr uint32_t CODE_K = 15;
+constexpr uint32_t ENCODE_LENGTH = 1u << CODE_K;
+constexpr auto KEY_SIZE_IN_BYTES = 32u;
+
+// Encodes a 2 bytes word with hadamard code. The encoding expands a word of k+1 bits to a 2^k
+// bitset. Returns the encoded bitset.
+std::bitset<ENCODE_LENGTH> EncodeWord(uint16_t word);
+
+// Decodes the input bitset, and returns a sorted list of pair with (score, value). The value with
+// a higher score indicates a greater likehood.
+std::priority_queue<std::pair<int32_t, uint16_t>> DecodeWord(
+ const std::bitset<ENCODE_LENGTH>& encoded);
+
+// Encodes a key that has a size of KEY_SIZE_IN_BYTES. Returns a byte array representation of the
+// encoded bitset. So a 32 bytes key will expand to 16*(2^15) bits = 64KiB.
+std::vector<uint8_t> EncodeKey(const std::vector<uint8_t>& input);
+
+// Given a byte array representation of the encoded keys, decodes it and return the result.
+std::vector<uint8_t> DecodeKey(const std::vector<uint8_t>& encoded);
+
+// Converts a bitset of length |ENCODE_LENGTH| to a byte array.
+std::vector<uint8_t> BitsetToBytes(const std::bitset<ENCODE_LENGTH>& encoded_bits);
+
+// Converts a byte array of encoded words back to the bitset.
+std::bitset<ENCODE_LENGTH> BytesToBitset(const std::vector<uint8_t>& encoded);
+
+} // namespace hadamard
+} // namespace rebootescrow
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/rebootescrow/aidl/default/HadamardUtilsTest.cpp b/rebootescrow/aidl/default/HadamardUtilsTest.cpp
new file mode 100644
index 0000000..e397e76
--- /dev/null
+++ b/rebootescrow/aidl/default/HadamardUtilsTest.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2019 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 <stdint.h>
+#include <random>
+
+#include <bitset>
+#include <utility>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include <HadamardUtils.h>
+
+using namespace aidl::android::hardware::rebootescrow::hadamard;
+
+class HadamardTest : public testing::Test {
+ protected:
+ void SetUp() override {
+ auto ones = std::bitset<ENCODE_LENGTH>{}.set();
+ // Expects 0x4000 to encode as top half as ones, and lower half as zeros. i.e.
+ // [1, 1 .. 1, 0, 0 .. 0]
+ expected_half_size_ = ones << half_size_;
+
+ // Expects 0x1 to encode as interleaved 1 and 0s i.e. [1, 0, 1, 0 ..]
+ expected_one_ = ones;
+ for (uint32_t i = ENCODE_LENGTH / 2; i >= 1; i /= 2) {
+ expected_one_ ^= (expected_one_ >> i);
+ }
+ }
+
+ uint16_t half_size_ = ENCODE_LENGTH / 2;
+ std::bitset<ENCODE_LENGTH> expected_one_;
+ std::bitset<ENCODE_LENGTH> expected_half_size_;
+};
+
+static void AddError(std::bitset<ENCODE_LENGTH>* corrupted_bits) {
+ // The hadamard code has a hamming distance of ENCODE_LENGTH/2. So we should always be able to
+ // correct the data if less than a quarter of the encoded bits are corrupted.
+ auto corrupted_max = 0.24f * corrupted_bits->size();
+ auto corrupted_num = 0;
+ for (size_t i = 0; i < corrupted_bits->size() && corrupted_num < corrupted_max; i++) {
+ if (random() % 2 == 0) {
+ (*corrupted_bits)[i] = !(*corrupted_bits)[i];
+ corrupted_num += 1;
+ }
+ }
+}
+
+static void EncodeAndDecodeKeys(const std::vector<uint8_t>& key) {
+ auto encoded = EncodeKey(key);
+ ASSERT_EQ(64 * 1024, encoded.size());
+ auto decoded = DecodeKey(encoded);
+ ASSERT_EQ(key, std::vector<uint8_t>(decoded.begin(), decoded.begin() + key.size()));
+}
+
+TEST_F(HadamardTest, Encode_smoke) {
+ ASSERT_EQ(expected_half_size_, EncodeWord(half_size_));
+ ASSERT_EQ(expected_one_, EncodeWord(1));
+ // Check the complement of 1.
+ ASSERT_EQ(~expected_one_, EncodeWord(1u << CODE_K | 1u));
+}
+
+TEST_F(HadamardTest, Decode_smoke) {
+ auto candidate = DecodeWord(expected_half_size_);
+ auto expected = std::pair<int32_t, uint16_t>{ENCODE_LENGTH, half_size_};
+ ASSERT_EQ(expected, candidate.top());
+
+ candidate = DecodeWord(expected_one_);
+ expected = std::pair<int32_t, uint16_t>{ENCODE_LENGTH, 1};
+ ASSERT_EQ(expected, candidate.top());
+}
+
+TEST_F(HadamardTest, Decode_error_correction) {
+ constexpr auto iteration = 10;
+ for (int i = 0; i < iteration; i++) {
+ uint16_t word = random() % (ENCODE_LENGTH * 2);
+ auto corrupted_bits = EncodeWord(word);
+ AddError(&corrupted_bits);
+
+ auto candidate = DecodeWord(corrupted_bits);
+ ASSERT_EQ(word, candidate.top().second);
+ }
+}
+
+TEST_F(HadamardTest, BytesToBitset_smoke) {
+ auto bytes = BitsetToBytes(expected_one_);
+
+ auto read_back = BytesToBitset(bytes);
+ ASSERT_EQ(expected_one_, read_back);
+}
+
+TEST_F(HadamardTest, EncodeAndDecodeKey) {
+ std::vector<uint8_t> KEY_1{
+ 0xA5, 0x00, 0xFF, 0x01, 0xA5, 0x5a, 0xAA, 0x55, 0x00, 0xD3, 0x2A,
+ 0x8C, 0x2E, 0x83, 0x0E, 0x65, 0x9E, 0x8D, 0xC6, 0xAC, 0x1E, 0x83,
+ 0x21, 0xB3, 0x95, 0x02, 0x89, 0x64, 0x64, 0x92, 0x12, 0x1F,
+ };
+ std::vector<uint8_t> KEY_2{
+ 0xFF, 0x00, 0x00, 0xAA, 0x5A, 0x19, 0x20, 0x71, 0x9F, 0xFB, 0xDA,
+ 0xB6, 0x2D, 0x06, 0xD5, 0x49, 0x7E, 0xEF, 0x63, 0xAC, 0x18, 0xFF,
+ 0x5A, 0xA3, 0x40, 0xBB, 0x64, 0xFA, 0x67, 0xC1, 0x10, 0x18,
+ };
+
+ EncodeAndDecodeKeys(KEY_1);
+ EncodeAndDecodeKeys(KEY_2);
+
+ std::vector<uint8_t> key;
+ for (uint8_t i = 0; i < KEY_SIZE_IN_BYTES; i++) {
+ key.push_back(i);
+ };
+ EncodeAndDecodeKeys(key);
+}
diff --git a/wifi/hostapd/1.2/IHostapd.hal b/wifi/hostapd/1.2/IHostapd.hal
index 31ade13..1bac1e7 100644
--- a/wifi/hostapd/1.2/IHostapd.hal
+++ b/wifi/hostapd/1.2/IHostapd.hal
@@ -16,6 +16,7 @@
package [email protected];
+import @1.0::IHostapd.NetworkParams;
import @1.1::IHostapd;
import HostapdStatus;
import MacAddress;
@@ -26,6 +27,86 @@
*/
interface IHostapd extends @1.1::IHostapd {
/**
+ * Band bitmMask to use for the SoftAp operations.
+ * A combinatoin of these bits are used to identify the allowed bands
+ * to start the softAp
+ */
+ enum BandMask : uint32_t {
+ /**
+ * 2.4 GHz band.
+ */
+ BAND_2_GHZ = 1 << 0,
+ /**
+ * 5 GHz band.
+ */
+ BAND_5_GHZ = 1 << 1,
+ /**
+ * 6 GHz band.
+ */
+ BAND_6_GHZ = 1 << 2,
+ };
+
+ /**
+ * Parameters to control the HW mode for the interface.
+ */
+ struct HwModeParams {
+ /**
+ * Whether IEEE 802.11ax (HE) is enabled or not.
+ * Note: hw_mode=a is used to specify that 5 GHz band or 6 GHz band is
+ * used with HE.
+ */
+ bool enable80211AX;
+ /**
+ * Whether 6GHz band enabled or not on softAp.
+ * Note: hw_mode=a is used to specify that 5 GHz band or 6 GHz band is
+ * used.
+ */
+ bool enable6GhzBand;
+ };
+
+ /**
+ * Parameters to control the channel selection for the interface.
+ */
+ struct ChannelParams {
+ /**
+ * Band to use for the SoftAp operations.
+ */
+ bitfield<BandMask> bandMask;
+ };
+
+ /**
+ * Parameters to use for setting up the access point interface.
+ */
+ struct IfaceParams {
+ /**
+ * Baseline information as defined in HAL 1.1.
+ */
+ @1.1::IHostapd.IfaceParams V1_1;
+ /** Additional Hw mode params for the interface */
+ HwModeParams hwModeParams;
+ /** Additional Channel params for the interface */
+ ChannelParams channelParams;
+ };
+
+ /**
+ * Adds a new access point for hostapd to control.
+ *
+ * This should trigger the setup of an access point with the specified
+ * interface and network params.
+ *
+ * @param ifaceParams AccessPoint Params for the access point.
+ * @param nwParams Network Params for the access point.
+ * @return status Status of the operation.
+ * Possible status codes:
+ * |HostapdStatusCode.SUCCESS|,
+ * |HostapdStatusCode.FAILURE_ARGS_INVALID|,
+ * |HostapdStatusCode.FAILURE_UNKNOWN|,
+ * |HostapdStatusCode.FAILURE_IFACE_EXISTS|
+ */
+ addAccessPoint_1_2(IfaceParams ifaceParams, NetworkParams nwParams)
+ generates(HostapdStatus status);
+
+ /**
* force one of the hotspot clients disconnect..
*
* @param ifaceName Name of the interface.
diff --git a/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp
index 0d37221..b092d00 100644
--- a/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp
+++ b/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp
@@ -39,7 +39,9 @@
namespace {
constexpr unsigned char kNwSsid[] = {'t', 'e', 's', 't', '1',
'2', '3', '4', '5'};
+constexpr char kNwPassphrase[] = "test12345";
constexpr int kIfaceChannel = 6;
+constexpr int kIfaceInvalidChannel = 567;
constexpr uint8_t kTestZeroMacAddr[] = {[0 ... 5] = 0x0};
constexpr Ieee80211ReasonCode kTestDisconnectReasonCode =
Ieee80211ReasonCode::WLAN_REASON_UNSPECIFIED;
@@ -73,7 +75,9 @@
IHostapd::IfaceParams getIfaceParamsWithoutAcs() {
::android::hardware::wifi::hostapd::V1_0::IHostapd::IfaceParams
iface_params;
- IHostapd::IfaceParams iface_params_1_1;
+ ::android::hardware::wifi::hostapd::V1_1::IHostapd::IfaceParams
+ iface_params_1_1;
+ IHostapd::IfaceParams iface_params_1_2;
iface_params.ifaceName = getPrimaryWlanIfaceName();
iface_params.hwModeParams.enable80211N = true;
@@ -81,9 +85,52 @@
iface_params.channelParams.enableAcs = false;
iface_params.channelParams.acsShouldExcludeDfs = false;
iface_params.channelParams.channel = kIfaceChannel;
- iface_params.channelParams.band = IHostapd::Band::BAND_2_4_GHZ;
iface_params_1_1.V1_0 = iface_params;
- return iface_params_1_1;
+ iface_params_1_2.V1_1 = iface_params_1_1;
+ // Newly added attributes in V1_2
+ iface_params_1_2.hwModeParams.enable80211AX = false;
+ iface_params_1_2.hwModeParams.enable6GhzBand = false;
+ iface_params_1_2.channelParams.bandMask = 0;
+ iface_params_1_2.channelParams.bandMask |=
+ IHostapd::BandMask::BAND_2_GHZ;
+ return iface_params_1_2;
+ }
+
+ IHostapd::IfaceParams getIfaceParamsWithAcs() {
+ // First get the settings for WithoutAcs and then make changes
+ IHostapd::IfaceParams iface_params_1_2 = getIfaceParamsWithoutAcs();
+ iface_params_1_2.V1_1.V1_0.channelParams.enableAcs = true;
+ iface_params_1_2.V1_1.V1_0.channelParams.acsShouldExcludeDfs = true;
+ iface_params_1_2.V1_1.V1_0.channelParams.channel = 0;
+ iface_params_1_2.channelParams.bandMask |=
+ IHostapd::BandMask::BAND_5_GHZ;
+
+ return iface_params_1_2;
+ }
+
+ IHostapd::IfaceParams getIfaceParamsWithAcsAndChannelRange() {
+ IHostapd::IfaceParams iface_params_1_2 = getIfaceParamsWithAcs();
+ ::android::hardware::wifi::hostapd::V1_1::IHostapd::ChannelParams
+ channelParams;
+ ::android::hardware::wifi::hostapd::V1_1::IHostapd::AcsChannelRange
+ acsChannelRange;
+ acsChannelRange.start = 1;
+ acsChannelRange.end = 11;
+ std::vector<
+ ::android::hardware::wifi::hostapd::V1_1::IHostapd::AcsChannelRange>
+ vec_acsChannelRange;
+ vec_acsChannelRange.push_back(acsChannelRange);
+ channelParams.acsChannelRanges = vec_acsChannelRange;
+ iface_params_1_2.V1_1.channelParams = channelParams;
+ return iface_params_1_2;
+ }
+
+ IHostapd::IfaceParams getIfaceParamsWithAcsAndInvalidChannelRange() {
+ IHostapd::IfaceParams iface_params_1_2 =
+ getIfaceParamsWithAcsAndChannelRange();
+ iface_params_1_2.V1_1.channelParams.acsChannelRanges[0].start = 222;
+ iface_params_1_2.V1_1.channelParams.acsChannelRanges[0].end = 999;
+ return iface_params_1_2;
}
IHostapd::NetworkParams getOpenNwParams() {
@@ -95,6 +142,31 @@
return nw_params;
}
+ IHostapd::NetworkParams getPskNwParams() {
+ IHostapd::NetworkParams nw_params;
+ nw_params.ssid =
+ std::vector<uint8_t>(kNwSsid, kNwSsid + sizeof(kNwSsid));
+ nw_params.isHidden = false;
+ nw_params.encryptionType = IHostapd::EncryptionType::WPA2;
+ nw_params.pskPassphrase = kNwPassphrase;
+ return nw_params;
+ }
+
+ IHostapd::NetworkParams getInvalidPskNwParams() {
+ IHostapd::NetworkParams nw_params;
+ nw_params.ssid =
+ std::vector<uint8_t>(kNwSsid, kNwSsid + sizeof(kNwSsid));
+ nw_params.isHidden = false;
+ nw_params.encryptionType = IHostapd::EncryptionType::WPA2;
+ return nw_params;
+ }
+
+ IHostapd::IfaceParams getIfaceParamsWithInvalidChannel() {
+ IHostapd::IfaceParams iface_params_1_2 = getIfaceParamsWithoutAcs();
+ iface_params_1_2.V1_1.V1_0.channelParams.channel = kIfaceInvalidChannel;
+ return iface_params_1_2;
+ }
+
// IHostapd object used for all tests in this fixture.
sp<IHostapd> hostapd_;
std::string wifi_instance_name_;
@@ -102,6 +174,125 @@
};
/**
+ * Adds an access point with PSK network config & ACS enabled.
+ * Access point creation should pass.
+ */
+TEST_P(HostapdHidlTest, AddPskAccessPointWithAcs) {
+ auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
+ getIfaceParamsWithAcs(), getPskNwParams());
+ // TODO: b/140172237, fix this in R.
+ // EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with PSK network config, ACS enabled & channel Range.
+ * Access point creation should pass.
+ */
+TEST_P(HostapdHidlTest, AddPskAccessPointWithAcsAndChannelRange) {
+ auto status =
+ HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
+ getIfaceParamsWithAcsAndChannelRange(), getPskNwParams());
+ // TODO: b/140172237, fix this in R
+ // EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with invalid channel range.
+ * Access point creation should fail.
+ */
+TEST_P(HostapdHidlTest, AddPskAccessPointWithAcsAndInvalidChannelRange) {
+ auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
+ getIfaceParamsWithAcsAndInvalidChannelRange(),
+ getPskNwParams());
+ // TODO: b/140172237, fix this in R
+ // EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with Open network config & ACS enabled.
+ * Access point creation should pass.
+ */
+TEST_P(HostapdHidlTest, AddOpenAccessPointWithAcs) {
+ auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
+ getIfaceParamsWithAcs(), getOpenNwParams());
+ // TODO: b/140172237, fix this in R
+ // EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with PSK network config & ACS disabled.
+ * Access point creation should pass.
+ */
+TEST_P(HostapdHidlTest, AddPskAccessPointWithoutAcs) {
+ auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
+ getIfaceParamsWithoutAcs(), getPskNwParams());
+ EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with Open network config & ACS disabled.
+ * Access point creation should pass.
+ */
+TEST_P(HostapdHidlTest, AddOpenAccessPointWithoutAcs) {
+ auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
+ getIfaceParamsWithoutAcs(), getOpenNwParams());
+ EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds & then removes an access point with PSK network config & ACS enabled.
+ * Access point creation & removal should pass.
+ */
+TEST_P(HostapdHidlTest, RemoveAccessPointWithAcs) {
+ auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
+ getIfaceParamsWithAcs(), getPskNwParams());
+ // TODO: b/140172237, fix this in R
+ /*
+ EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+ status =
+ HIDL_INVOKE(hostapd_, removeAccessPoint, getPrimaryWlanIfaceName());
+ EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
+ */
+}
+
+/**
+ * Adds & then removes an access point with PSK network config & ACS disabled.
+ * Access point creation & removal should pass.
+ */
+TEST_P(HostapdHidlTest, RemoveAccessPointWithoutAcs) {
+ auto status_1_2 = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
+ getIfaceParamsWithoutAcs(), getPskNwParams());
+ EXPECT_EQ(HostapdStatusCode::SUCCESS, status_1_2.code);
+ auto status =
+ HIDL_INVOKE(hostapd_, removeAccessPoint, getPrimaryWlanIfaceName());
+ EXPECT_EQ(
+ android::hardware::wifi::hostapd::V1_0::HostapdStatusCode::SUCCESS,
+ status.code);
+}
+
+/**
+ * Adds an access point with invalid channel.
+ * Access point creation should fail.
+ */
+TEST_P(HostapdHidlTest, AddPskAccessPointWithInvalidChannel) {
+ auto status =
+ HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
+ getIfaceParamsWithInvalidChannel(), getPskNwParams());
+ EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
+ * Adds an access point with invalid PSK network config.
+ * Access point creation should fail.
+ */
+TEST_P(HostapdHidlTest, AddInvalidPskAccessPointWithoutAcs) {
+ auto status =
+ HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(),
+ getInvalidPskNwParams());
+ EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
+}
+
+/**
* forceClientDisconnect should return FAILURE_IFACE_UNKNOWN
* when hotspot interface doesn't init..
*/
@@ -117,14 +308,12 @@
* when hotspot interface available.
*/
TEST_P(HostapdHidlTest, DisconnectClientWhenIfacAvailable) {
- auto status_1_0 =
- HIDL_INVOKE(hostapd_, addAccessPoint_1_1, getIfaceParamsWithoutAcs(),
- getOpenNwParams());
- EXPECT_EQ(
- android::hardware::wifi::hostapd::V1_0::HostapdStatusCode::SUCCESS,
- status_1_0.code);
-
auto status_1_2 =
+ HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(),
+ getOpenNwParams());
+ EXPECT_EQ(HostapdStatusCode::SUCCESS, status_1_2.code);
+
+ status_1_2 =
HIDL_INVOKE(hostapd_, forceClientDisconnect, getPrimaryWlanIfaceName(),
kTestZeroMacAddr, kTestDisconnectReasonCode);
EXPECT_EQ(HostapdStatusCode::FAILURE_CLIENT_UNKNOWN, status_1_2.code);
diff --git a/wifi/supplicant/1.0/vts/functional/Android.bp b/wifi/supplicant/1.0/vts/functional/Android.bp
index 15525bb..332ee4a 100644
--- a/wifi/supplicant/1.0/vts/functional/Android.bp
+++ b/wifi/supplicant/1.0/vts/functional/Android.bp
@@ -19,7 +19,7 @@
defaults: ["VtsHalTargetTestDefaults"],
srcs: ["supplicant_hidl_test_utils.cpp"],
export_include_dirs: [
- "."
+ ".",
],
static_libs: [
"VtsHalWifiV1_0TargetTestUtil",
@@ -51,14 +51,17 @@
"libwifi-system",
"libwifi-system-iface",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: [
+ "general-tests",
+ "vts-core",
+ ],
}
cc_test {
name: "VtsHalWifiSupplicantP2pV1_0TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
srcs: [
- "VtsHalWifiSupplicantV1_0TargetTest.cpp",
+ "VtsHalWifiSupplicantP2pV1_0TargetTest.cpp",
"supplicant_p2p_iface_hidl_test.cpp",
],
static_libs: [
@@ -71,5 +74,8 @@
"libwifi-system",
"libwifi-system-iface",
],
- test_suites: ["general-tests", "vts-core"],
+ test_suites: [
+ "general-tests",
+ "vts-core",
+ ],
}
diff --git a/wifi/supplicant/1.0/vts/functional/VtsHalWifiSupplicantP2pV1_0TargetTest.cpp b/wifi/supplicant/1.0/vts/functional/VtsHalWifiSupplicantP2pV1_0TargetTest.cpp
new file mode 100644
index 0000000..a132707
--- /dev/null
+++ b/wifi/supplicant/1.0/vts/functional/VtsHalWifiSupplicantP2pV1_0TargetTest.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2019 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 <VtsCoreUtil.h>
+#include "supplicant_hidl_test_utils.h"
+
+// TODO(b/143892896): Remove this line after wifi_hidl_test_utils.cpp is
+// updated.
+WifiSupplicantHidlEnvironment* gEnv = nullptr;
+
+int main(int argc, char** argv) {
+ if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct"))
+ return 0;
+
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/wifi/supplicant/1.3/ISupplicantStaIface.hal b/wifi/supplicant/1.3/ISupplicantStaIface.hal
index bfd8946..fa88b91 100644
--- a/wifi/supplicant/1.3/ISupplicantStaIface.hal
+++ b/wifi/supplicant/1.3/ISupplicantStaIface.hal
@@ -18,6 +18,7 @@
import @1.0::SupplicantStatus;
import @1.2::ISupplicantStaIface;
+import @1.3::ISupplicantStaNetwork;
import ISupplicantStaIfaceCallback;
/**
@@ -76,4 +77,17 @@
* |SupplicantStatusCode.FAILURE_UNKNOWN|
*/
setMboCellularDataStatus(bool available) generates (SupplicantStatus status);
+
+ /**
+ * Get Key management capabilities of the device
+ *
+ * @return status Status of the operation, and a bitmap of key management mask.
+ * Possible status codes:
+ * |SupplicantStatusCode.SUCCESS|,
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ getKeyMgmtCapabilities_1_3()
+ generates (SupplicantStatus status, bitfield<KeyMgmtMask> keyMgmtMask);
};
diff --git a/wifi/supplicant/1.3/ISupplicantStaNetwork.hal b/wifi/supplicant/1.3/ISupplicantStaNetwork.hal
index ab08cff..1bcf7bc 100644
--- a/wifi/supplicant/1.3/ISupplicantStaNetwork.hal
+++ b/wifi/supplicant/1.3/ISupplicantStaNetwork.hal
@@ -16,6 +16,7 @@
package [email protected];
+import @1.0::ISupplicantStaNetwork;
import @1.0::SupplicantStatus;
import @1.2::ISupplicantStaNetwork;
@@ -24,6 +25,32 @@
* configuration it controls.
*/
interface ISupplicantStaNetwork extends @1.2::ISupplicantStaNetwork {
+ /** Possble mask of values for Proto param. */
+ enum ProtoMask : @1.0::ISupplicantStaNetwork.ProtoMask {
+ WAPI = 1 << 2,
+ };
+
+ /** Possble mask of values for KeyMgmt param. */
+ enum KeyMgmtMask : @1.2::ISupplicantStaNetwork.KeyMgmtMask {
+ /* WAPI Psk */
+ WAPI_PSK = 1 << 12,
+
+ /** WAPI Cert */
+ WAPI_CERT = 1 << 13,
+ };
+
+ /** Possble mask of values for PairwiseCipher param. */
+ enum PairwiseCipherMask : @1.2::ISupplicantStaNetwork.PairwiseCipherMask {
+ /** SMS4 Pairwise Cipher */
+ SMS4 = 1 << 7,
+ };
+
+ /** Possble mask of values for GroupCipher param. */
+ enum GroupCipherMask : @1.2::ISupplicantStaNetwork.GroupCipherMask {
+ /** SMS4 Group Cipher */
+ SMS4 = 1 << 7,
+ };
+
/**
* Set OCSP (Online Certificate Status Protocol) type for this network.
*
@@ -49,6 +76,142 @@
getOcsp() generates (SupplicantStatus status, OcspType ocspType);
/**
+ * Set key management mask for the network.
+ *
+ * @param keyMgmtMask value to set.
+ * Combination of |KeyMgmtMask| values.
+ * @return status Status of the operation.
+ * Possible status codes:
+ * |SupplicantStatusCode.SUCCESS|,
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ setKeyMgmt_1_3(bitfield<KeyMgmtMask> keyMgmtMask) generates (SupplicantStatus status);
+
+ /**
+ * Get the key mgmt mask set for the network.
+ *
+ * @return status Status of the operation.
+ * Possible status codes:
+ * |SupplicantStatusCode.SUCCESS|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ * @return keyMgmtMask Combination of |KeyMgmtMask| values.
+ */
+ getKeyMgmt_1_3()
+ generates (SupplicantStatus status, bitfield<KeyMgmtMask> keyMgmtMask);
+
+ /**
+ * Set proto mask for the network.
+ *
+ * @param protoMask value to set.
+ * Combination of |ProtoMask| values.
+ * @return status Status of the operation.
+ * Possible status codes:
+ * |SupplicantStatusCode.SUCCESS|,
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ setProto_1_3(bitfield<ProtoMask> protoMask) generates (SupplicantStatus status);
+
+ /**
+ * Get the proto mask set for the network.
+ *
+ * @return status Status of the operation.
+ * Possible status codes:
+ * |SupplicantStatusCode.SUCCESS|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ * @return protoMask Combination of |ProtoMask| values.
+ */
+ getProto_1_3() generates (SupplicantStatus status, bitfield<ProtoMask> protoMask);
+
+ /**
+ * Set group cipher mask for the network.
+ *
+ * @param groupCipherMask value to set.
+ * Combination of |ProtoMask| values.
+ * @return status Status of the operation.
+ * Possible status codes:
+ * |SupplicantStatusCode.SUCCESS|,
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ setGroupCipher_1_3(bitfield<GroupCipherMask> groupCipherMask)
+ generates (SupplicantStatus status);
+
+ /**
+ * Get the pairwise cipher mask set for the network.
+ *
+ * @return status Status of the operation.
+ * Possible status codes:
+ * |SupplicantStatusCode.SUCCESS|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ * @return pairwiseCipherMask Combination of |PairwiseCipherMask| values.
+ */
+ getPairwiseCipher_1_3()
+ generates (SupplicantStatus status,
+ bitfield<PairwiseCipherMask> pairwiseCipherMask);
+
+ /**
+ * Set pairwise cipher mask for the network.
+ *
+ * @param pairwiseCipherMask value to set.
+ * Combination of |ProtoMask| values.
+ * @return status Status of the operation.
+ * Possible status codes:
+ * |SupplicantStatusCode.SUCCESS|,
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ setPairwiseCipher_1_3(bitfield<PairwiseCipherMask> pairwiseCipherMask)
+ generates (SupplicantStatus status);
+
+ /**
+ * Get the group cipher mask set for the network.
+ *
+ * @return status Status of the operation.
+ * Possible status codes:
+ * |SupplicantStatusCode.SUCCESS|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ * @return groupCipherMask Combination of |GroupCipherMask| values.
+ */
+ getGroupCipher_1_3()
+ generates (SupplicantStatus status,
+ bitfield<GroupCipherMask> groupCipherMask);
+
+ /**
+ * Set WAPI certificate suite for this network.
+ *
+ * @param suite value to set.
+ * @return status Status of the operation.
+ * Possible status codes:
+ * |SupplicantStatusCode.SUCCESS|,
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ */
+ setWapiCertSuite(string suite) generates (SupplicantStatus status);
+
+ /**
+ * Get WAPI certificate suite set for this network.
+ *
+ * @return status Status of the operation.
+ * Possible status codes:
+ * |SupplicantStatusCode.SUCCESS|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|
+ * @return suite The name of a suite.
+ */
+ getWapiCertSuite() generates (SupplicantStatus status, string suite);
+
+ /**
* Add a PMK into supplicant PMK cache.
*
* @param serializedEntry is serialized PMK cache entry, the content is
diff --git a/wifi/supplicant/1.3/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.3/vts/functional/supplicant_sta_iface_hidl_test.cpp
index 2cf5881..ca3265e 100644
--- a/wifi/supplicant/1.3/vts/functional/supplicant_sta_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.3/vts/functional/supplicant_sta_iface_hidl_test.cpp
@@ -227,3 +227,22 @@
EXPECT_EQ(expectedStatusCode, status.code);
});
}
+
+/*
+ * GetKeyMgmtCapabilities_1_3
+ */
+TEST_F(SupplicantStaIfaceHidlTest, GetKeyMgmtCapabilities_1_3) {
+ sta_iface_->getKeyMgmtCapabilities_1_3([&](const SupplicantStatus& status,
+ uint32_t keyMgmtMask) {
+ if (SupplicantStatusCode::SUCCESS != status.code) {
+ // for unsupport case
+ EXPECT_EQ(SupplicantStatusCode::FAILURE_UNKNOWN, status.code);
+ } else {
+ // Even though capabilities vary, these two are always set in HAL
+ // v1.3
+ EXPECT_TRUE(keyMgmtMask & ISupplicantStaNetwork::KeyMgmtMask::NONE);
+ EXPECT_TRUE(keyMgmtMask &
+ ISupplicantStaNetwork::KeyMgmtMask::IEEE8021X);
+ }
+ });
+}
diff --git a/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp b/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp
index 07bc9d8..d6f55f5 100644
--- a/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp
+++ b/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp
@@ -17,15 +17,18 @@
#include <android-base/logging.h>
#include <VtsHalHidlTargetTestBase.h>
+#include <android/hardware/wifi/supplicant/1.3/ISupplicantStaIface.h>
#include <android/hardware/wifi/supplicant/1.3/ISupplicantStaNetwork.h>
#include "supplicant_hidl_test_utils.h"
#include "supplicant_hidl_test_utils_1_3.h"
using ::android::sp;
+using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
+using ::android::hardware::wifi::supplicant::V1_3::ISupplicantStaIface;
using ::android::hardware::wifi::supplicant::V1_3::ISupplicantStaNetwork;
using ::android::hardware::wifi::supplicant::V1_3::OcspType;
namespace {
@@ -39,15 +42,37 @@
virtual void SetUp() override {
startSupplicantAndWaitForHidlService();
EXPECT_TRUE(turnOnExcessiveLogging());
+ sta_iface_ = getSupplicantStaIface_1_3();
+ ASSERT_NE(nullptr, sta_iface_.get());
sta_network_ = createSupplicantStaNetwork_1_3();
- ASSERT_NE(sta_network_.get(), nullptr);
+ ASSERT_NE(nullptr, sta_network_.get());
}
virtual void TearDown() override { stopSupplicant(); }
protected:
+ sp<ISupplicantStaIface> sta_iface_;
// ISupplicantStaNetwork object used for all tests in this fixture.
sp<ISupplicantStaNetwork> sta_network_;
+
+ bool isWapiSupported() {
+ uint32_t keyMgmtMask = 0;
+
+ // We need to first get the key management capabilities from the device.
+ // If WAPI is not supported, we just pass the test.
+ sta_iface_->getKeyMgmtCapabilities_1_3(
+ [&](const SupplicantStatus &status, uint32_t keyMgmtMaskInternal) {
+ EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+ keyMgmtMask = keyMgmtMaskInternal;
+ });
+
+ if (!(keyMgmtMask & ISupplicantStaNetwork::KeyMgmtMask::WAPI_PSK)) {
+ // WAPI not supported
+ return false;
+ }
+
+ return true;
+ }
};
/*
@@ -84,3 +109,160 @@
EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
});
}
+
+/*
+ * SetGetKeyMgmt_1_3, check new WAPI proto support
+ */
+TEST_F(SupplicantStaNetworkHidlTest, SetGetKeyMgmt_1_3) {
+ uint32_t keyMgmt = (uint32_t)ISupplicantStaNetwork::KeyMgmtMask::WAPI_PSK;
+
+ sta_network_->setKeyMgmt_1_3(keyMgmt, [](const SupplicantStatus &status) {
+ if (SupplicantStatusCode::SUCCESS != status.code) {
+ // for unsupport case
+ EXPECT_EQ(SupplicantStatusCode::FAILURE_UNKNOWN, status.code);
+ }
+ });
+
+ sta_network_->getKeyMgmt_1_3(
+ [&keyMgmt](const SupplicantStatus &status, uint32_t keyMgmtOut) {
+ if (SupplicantStatusCode::SUCCESS != status.code) {
+ // for unsupport case
+ EXPECT_EQ(SupplicantStatusCode::FAILURE_UNKNOWN, status.code);
+ } else {
+ EXPECT_EQ(keyMgmtOut, keyMgmt);
+ }
+ });
+
+ keyMgmt = (uint32_t)ISupplicantStaNetwork::KeyMgmtMask::WAPI_CERT;
+ sta_network_->setKeyMgmt_1_3(keyMgmt, [](const SupplicantStatus &status) {
+ if (SupplicantStatusCode::SUCCESS != status.code) {
+ // for unsupport case
+ EXPECT_EQ(SupplicantStatusCode::FAILURE_UNKNOWN, status.code);
+ }
+ });
+
+ sta_network_->getKeyMgmt_1_3(
+ [&keyMgmt](const SupplicantStatus &status, uint32_t keyMgmtOut) {
+ if (SupplicantStatusCode::SUCCESS != status.code) {
+ // for unsupport case
+ EXPECT_EQ(SupplicantStatusCode::FAILURE_UNKNOWN, status.code);
+ } else {
+ EXPECT_EQ(keyMgmtOut, keyMgmt);
+ }
+ });
+}
+
+/*
+ * SetGetProto_1_3, check new WAPI proto support
+ */
+TEST_F(SupplicantStaNetworkHidlTest, SetGetProto_1_3) {
+ uint32_t wapiProto = (uint32_t)ISupplicantStaNetwork::ProtoMask::WAPI;
+ sta_network_->setProto(wapiProto, [](const SupplicantStatus &status) {
+ if (SupplicantStatusCode::SUCCESS != status.code) {
+ // for unsupport case
+ EXPECT_EQ(SupplicantStatusCode::FAILURE_UNKNOWN, status.code);
+ }
+ });
+ sta_network_->getProto([&](const SupplicantStatus &status, uint32_t proto) {
+ if (SupplicantStatusCode::SUCCESS != status.code) {
+ // for unsupport case
+ EXPECT_EQ(SupplicantStatusCode::FAILURE_UNKNOWN, status.code);
+ } else {
+ EXPECT_EQ(proto, wapiProto);
+ }
+ });
+}
+
+/*
+ * SetGetGroupCipher_1_3, check new WAPI support
+ */
+TEST_F(SupplicantStaNetworkHidlTest, SetGetGroupCipher_1_3) {
+ uint32_t groupCipher =
+ (uint32_t)ISupplicantStaNetwork::GroupCipherMask::SMS4;
+
+ sta_network_->setGroupCipher_1_3(
+ groupCipher, [](const SupplicantStatus &status) {
+ if (SupplicantStatusCode::SUCCESS != status.code) {
+ // for unsupport case
+ EXPECT_EQ(SupplicantStatusCode::FAILURE_UNKNOWN, status.code);
+ }
+ });
+
+ sta_network_->getGroupCipher_1_3(
+ [&groupCipher](const SupplicantStatus &status,
+ uint32_t groupCipherOut) {
+ if (SupplicantStatusCode::SUCCESS != status.code) {
+ // for unsupport case
+ EXPECT_EQ(SupplicantStatusCode::FAILURE_UNKNOWN, status.code);
+ } else {
+ EXPECT_EQ(groupCipherOut, groupCipher);
+ }
+ });
+}
+
+/*
+ * SetGetPairwiseCipher_1_3, check new WAPI support
+ */
+TEST_F(SupplicantStaNetworkHidlTest, SetGetPairwiseCipher_1_3) {
+ uint32_t pairwiseCipher =
+ (uint32_t)ISupplicantStaNetwork::PairwiseCipherMask::SMS4;
+
+ sta_network_->setPairwiseCipher_1_3(
+ pairwiseCipher, [](const SupplicantStatus &status) {
+ if (SupplicantStatusCode::SUCCESS != status.code) {
+ // for unsupport case
+ EXPECT_EQ(SupplicantStatusCode::FAILURE_UNKNOWN, status.code);
+ }
+ });
+
+ sta_network_->getPairwiseCipher_1_3(
+ [&pairwiseCipher](const SupplicantStatus &status,
+ uint32_t pairwiseCipherOut) {
+ if (SupplicantStatusCode::SUCCESS != status.code) {
+ // for unsupport case
+ EXPECT_EQ(SupplicantStatusCode::FAILURE_UNKNOWN, status.code);
+ } else {
+ EXPECT_EQ(pairwiseCipherOut, pairwiseCipher);
+ }
+ });
+}
+
+/*
+ * SetGetWapiCertSuite
+ */
+TEST_F(SupplicantStaNetworkHidlTest, SetGetWapiCertSuite) {
+ hidl_string testWapiCertSuite = "suite";
+
+ if (isWapiSupported()) {
+ sta_network_->setWapiCertSuite(
+ testWapiCertSuite, [](const SupplicantStatus &status) {
+ if (SupplicantStatusCode::SUCCESS != status.code) {
+ // for unsupport case
+ EXPECT_EQ(SupplicantStatusCode::FAILURE_UNKNOWN,
+ status.code);
+ }
+ });
+
+ sta_network_->getWapiCertSuite([testWapiCertSuite](
+ const SupplicantStatus &status,
+ const hidl_string &wapiCertSuite) {
+ if (SupplicantStatusCode::SUCCESS != status.code) {
+ // for unsupport case
+ EXPECT_EQ(SupplicantStatusCode::FAILURE_UNKNOWN, status.code);
+ } else {
+ EXPECT_EQ(testWapiCertSuite, wapiCertSuite);
+ }
+ });
+ } else {
+ sta_network_->setWapiCertSuite(
+ testWapiCertSuite, [](const SupplicantStatus &status) {
+ EXPECT_EQ(SupplicantStatusCode::FAILURE_UNKNOWN, status.code);
+ });
+
+ sta_network_->getWapiCertSuite(
+ [testWapiCertSuite](const SupplicantStatus &status,
+ const hidl_string &wapiCertSuite __unused) {
+ EXPECT_EQ(SupplicantStatusCode::FAILURE_UNKNOWN, status.code);
+ });
+ }
+}