Merge "Update 1.5 IRadio interface with missing structs/functions" into rvc-dev
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index 8e57901..e529675 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -63,6 +63,8 @@
"impl/vhal_v2_0/CommConn.cpp",
"impl/vhal_v2_0/EmulatedVehicleConnector.cpp",
"impl/vhal_v2_0/EmulatedVehicleHal.cpp",
+ "impl/vhal_v2_0/VehicleHalClient.cpp",
+ "impl/vhal_v2_0/VehicleHalServer.cpp",
"impl/vhal_v2_0/VehicleEmulator.cpp",
"impl/vhal_v2_0/PipeComm.cpp",
"impl/vhal_v2_0/ProtoMessageConverter.cpp",
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleClient.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleClient.h
new file mode 100644
index 0000000..5e4bf27
--- /dev/null
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleClient.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <vector>
+
+#include <android/hardware/automotive/vehicle/2.0/types.h>
+
+namespace android::hardware::automotive::vehicle::V2_0 {
+
+/**
+ * Vehicle HAL talks to the vehicle through a client, instead of accessing
+ * the car bus directly, to give us more flexibility on the implementation.
+ * Android OS do not need direct access to the vehicle, and the communication
+ * channel is also customizable.
+ *
+ * Client lives on the Android (HAL) side to talk to the vehicle
+ */
+class IVehicleClient {
+ public:
+ IVehicleClient() = default;
+
+ IVehicleClient(const IVehicleClient&) = delete;
+
+ IVehicleClient& operator=(const IVehicleClient&) = delete;
+
+ IVehicleClient(IVehicleClient&&) = default;
+
+ virtual ~IVehicleClient() = default;
+
+ // Get configuration of all properties from server
+ virtual std::vector<VehiclePropConfig> getAllPropertyConfig() const = 0;
+
+ // Send the set property request to server
+ // updateStatus indicate if VHal should change the status of the value
+ // it should be false except injecting values for e2e tests
+ virtual StatusCode setProperty(const VehiclePropValue& value, bool updateStatus) = 0;
+
+ // Receive a new property value from server
+ // updateStatus is true if and only if the value is
+ // generated by car (ECU/fake generator/injected)
+ virtual void onPropertyValue(const VehiclePropValue& value, bool updateStatus) = 0;
+
+ // Dump method forwarded from HIDL's debug()
+ // If implemented, it must return whether the caller should dump its state.
+ virtual bool dump(const hidl_handle& /* handle */, const hidl_vec<hidl_string>& /* options */) {
+ return true;
+ }
+};
+
+} // namespace android::hardware::automotive::vehicle::V2_0
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleConnector.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleConnector.h
index 00b5afe..2908a55 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleConnector.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleConnector.h
@@ -21,6 +21,9 @@
#include <android/hardware/automotive/vehicle/2.0/types.h>
+#include "VehicleClient.h"
+#include "VehicleServer.h"
+
namespace android {
namespace hardware {
namespace automotive {
@@ -34,85 +37,6 @@
*/
/**
- * Vehicle HAL talks to the vehicle through a client, instead of accessing
- * the car bus directly, to give us more flexibility on the implementation.
- * Android OS do not need direct access to the vehicle, and the communication
- * channel is also customizable.
- *
- * Client lives on the Android (HAL) side to talk to the vehicle
- */
-class IVehicleClient {
- public:
- IVehicleClient() = default;
-
- IVehicleClient(const IVehicleClient&) = delete;
-
- IVehicleClient& operator=(const IVehicleClient&) = delete;
-
- IVehicleClient(IVehicleClient&&) = default;
-
- virtual ~IVehicleClient() = default;
-
- // Get configuration of all properties from server
- virtual std::vector<VehiclePropConfig> getAllPropertyConfig() const = 0;
-
- // Send the set property request to server
- // updateStatus indicate if VHal should change the status of the value
- // it should be false except injecting values for e2e tests
- virtual StatusCode setProperty(const VehiclePropValue& value, bool updateStatus) = 0;
-
- // Receive a new property value from server
- // updateStatus is true if and only if the value is
- // generated by car (ECU/fake generator/injected)
- virtual void onPropertyValue(const VehiclePropValue& value, bool updateStatus) = 0;
-
- // Dump method forwarded from HIDL's debug()
- // If implemented, it must return whether the caller should dump its state.
- virtual bool dump(const hidl_handle& /* handle */, const hidl_vec<hidl_string>& /* options */) {
- return true;
- }
-};
-
-/**
- * Server lives on the vehicle side to talk to Android HAL
- */
-class IVehicleServer {
- public:
- IVehicleServer() = default;
-
- IVehicleServer(const IVehicleServer&) = delete;
-
- IVehicleServer& operator=(const IVehicleServer&) = delete;
-
- IVehicleServer(IVehicleServer&&) = default;
-
- virtual ~IVehicleServer() = default;
-
- // Receive the get property configuration request from HAL.
- // Return a list of all property config
- virtual std::vector<VehiclePropConfig> onGetAllPropertyConfig() const = 0;
-
- // Receive the set property request from HAL.
- // Process the setting and return the status code
- // updateStatus indicate if VHal should change the status of the value
- // it should be false except injecting values for e2e tests
- virtual StatusCode onSetProperty(const VehiclePropValue& value, bool updateStatus) = 0;
-
- // Receive a new property value from car (via direct connection to the car bus or the emulator)
- // and forward the value to HAL
- // updateStatus is true if and only if the value is
- // generated by car (ECU/fake generator/injected)
- virtual void onPropertyValueFromCar(const VehiclePropValue& value, bool updateStatus) = 0;
-
- // Dump method forwarded from HIDL's debug()
- // If implemented, it must return whether the caller should dump its state.
- virtual bool onDump(const hidl_handle& /* handle */,
- const hidl_vec<hidl_string>& /* options */) {
- return true;
- }
-};
-
-/**
* If Android has direct access to the vehicle, then the client and
* the server may act in passthrough mode to avoid extra IPC
*
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleObjectPool.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleObjectPool.h
index 946e74d..e3cbf2e 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleObjectPool.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleObjectPool.h
@@ -21,6 +21,7 @@
#include <deque>
#include <map>
#include <mutex>
+#include <memory>
#include <android/hardware/automotive/vehicle/2.0/types.h>
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleServer.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleServer.h
new file mode 100644
index 0000000..ba9799a
--- /dev/null
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleServer.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <vector>
+
+#include <android/hardware/automotive/vehicle/2.0/types.h>
+
+namespace android::hardware::automotive::vehicle::V2_0 {
+
+/**
+ * Server lives on the vehicle side to talk to Android HAL.
+ * Note that the server may not be run on Android
+ */
+class IVehicleServer {
+ public:
+ IVehicleServer() = default;
+
+ IVehicleServer(const IVehicleServer&) = delete;
+
+ IVehicleServer& operator=(const IVehicleServer&) = delete;
+
+ IVehicleServer(IVehicleServer&&) = default;
+
+ virtual ~IVehicleServer() = default;
+
+ // Receive the get property configuration request from HAL.
+ // Return a list of all property config
+ virtual std::vector<VehiclePropConfig> onGetAllPropertyConfig() const = 0;
+
+ // Receive the set property request from HAL.
+ // Process the setting and return the status code
+ // updateStatus indicate if VHal should change the status of the value
+ // it should be false except injecting values for e2e tests
+ virtual StatusCode onSetProperty(const VehiclePropValue& value, bool updateStatus) = 0;
+
+ // Receive a new property value from car (via direct connection to the car bus or the emulator)
+ // and forward the value to HAL
+ // updateStatus is true if and only if the value is
+ // generated by car (ECU/fake generator/injected)
+ virtual void onPropertyValueFromCar(const VehiclePropValue& value, bool updateStatus) = 0;
+
+ // TODO (chenhaosjtuacm): fix this since there are no HIDL in non-Android OS
+#ifdef __ANDROID__
+ // Dump method forwarded from HIDL's debug()
+ // If implemented, it must return whether the caller should dump its state.
+ virtual bool onDump(const hidl_handle& /* handle */,
+ const hidl_vec<hidl_string>& /* options */) {
+ return true;
+ }
+#endif // __ANDROID__
+};
+
+} // namespace android::hardware::automotive::vehicle::V2_0
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleUtils.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleUtils.h
index f97dfa1..9553415 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleUtils.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleUtils.h
@@ -19,7 +19,9 @@
#include <memory>
+#ifdef __ANDROID__
#include <hidl/HidlSupport.h>
+#endif
#include <android/hardware/automotive/vehicle/2.0/types.h>
@@ -69,6 +71,8 @@
void copyVehicleRawValue(VehiclePropValue::RawValue* dest,
const VehiclePropValue::RawValue& src);
+#ifdef __ANDROID__
+
template<typename T>
void shallowCopyHidlVec(hidl_vec<T>* dest, const hidl_vec<T>& src);
@@ -76,6 +80,8 @@
void shallowCopy(VehiclePropValue* dest, const VehiclePropValue& src);
+#endif // __ANDROID__
+
} // namespace V2_0
} // namespace vehicle
} // namespace automotive
diff --git a/automotive/vehicle/2.0/default/common/src/VehicleObjectPool.cpp b/automotive/vehicle/2.0/default/common/src/VehicleObjectPool.cpp
index 40dd56e..0947c9f 100644
--- a/automotive/vehicle/2.0/default/common/src/VehicleObjectPool.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VehicleObjectPool.cpp
@@ -131,7 +131,7 @@
ALOGE("Discarding value for prop 0x%x because it contains "
"data that is not consistent with this pool. "
"Expected type: %d, vector size: %zu",
- o->prop, mPropType, mVectorSize);
+ o->prop, toInt(mPropType), mVectorSize);
delete o;
} else {
ObjectPool<VehiclePropValue>::recycle(o);
diff --git a/automotive/vehicle/2.0/default/common/src/VehicleUtils.cpp b/automotive/vehicle/2.0/default/common/src/VehicleUtils.cpp
index 5b6816e..c16b29a 100644
--- a/automotive/vehicle/2.0/default/common/src/VehicleUtils.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VehicleUtils.cpp
@@ -52,7 +52,7 @@
case VehiclePropertyType::MIXED:
break; // Valid, but nothing to do.
default:
- ALOGE("createVehiclePropValue: unknown type: %d", type);
+ ALOGE("createVehiclePropValue: unknown type: %d", toInt(type));
val.reset(nullptr);
}
return val;
@@ -78,13 +78,6 @@
}
}
-template<typename T>
-inline void copyHidlVec(hidl_vec <T>* dest, const hidl_vec <T>& src) {
- for (size_t i = 0; i < std::min(dest->size(), src.size()); i++) {
- (*dest)[i] = src[i];
- }
-}
-
void copyVehicleRawValue(VehiclePropValue::RawValue* dest,
const VehiclePropValue::RawValue& src) {
dest->int32Values = src.int32Values;
@@ -94,6 +87,15 @@
dest->stringValue = src.stringValue;
}
+#ifdef __ANDROID__
+
+template<typename T>
+inline void copyHidlVec(hidl_vec <T>* dest, const hidl_vec <T>& src) {
+ for (size_t i = 0; i < std::min(dest->size(), src.size()); i++) {
+ (*dest)[i] = src[i];
+ }
+}
+
template<typename T>
void shallowCopyHidlVec(hidl_vec <T>* dest, const hidl_vec <T>& src) {
if (src.size() > 0) {
@@ -123,6 +125,7 @@
shallowCopyHidlStr(&dest->value.stringValue, src.value.stringValue);
}
+#endif // __ANDROID__
//} // namespace utils
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index 4b94800..53c9ffb 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -17,9 +17,11 @@
#ifndef android_hardware_automotive_vehicle_V2_0_impl_DefaultConfig_H_
#define android_hardware_automotive_vehicle_V2_0_impl_DefaultConfig_H_
-#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
+#include <android/hardware/automotive/vehicle/2.0/types.h>
#include <vhal_v2_0/VehicleUtils.h>
+#include <map>
+
namespace android {
namespace hardware {
namespace automotive {
@@ -1017,7 +1019,6 @@
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
},
},
-
};
} // impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
index 7f90914..9c3c95f 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
@@ -35,346 +35,16 @@
namespace impl {
-void EmulatedVehicleClient::onPropertyValue(const VehiclePropValue& value, bool updateStatus) {
- if (!mPropCallback) {
- LOG(ERROR) << __func__ << ": PropertyCallBackType is not registered!";
- return;
- }
- return mPropCallback(value, updateStatus);
-}
+class EmulatedPassthroughConnector : public PassthroughConnector {
+ public:
+ bool onDump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
-void EmulatedVehicleClient::registerPropertyValueCallback(PropertyCallBackType&& callback) {
- if (mPropCallback) {
- LOG(ERROR) << __func__ << ": Cannot register multiple callbacks!";
- return;
- }
- mPropCallback = std::move(callback);
-}
+ private:
+ void dumpUserHal(int fd, std::string indent);
+};
-GeneratorHub* EmulatedVehicleServer::getGenerator() {
- return &mGeneratorHub;
-}
-
-VehiclePropValuePool* EmulatedVehicleServer::getValuePool() const {
- if (!mValuePool) {
- LOG(WARNING) << __func__ << ": Value pool not set!";
- }
- return mValuePool;
-}
-
-void EmulatedVehicleServer::setValuePool(VehiclePropValuePool* valuePool) {
- if (!valuePool) {
- LOG(WARNING) << __func__ << ": Setting value pool to nullptr!";
- }
- mValuePool = valuePool;
-}
-
-void EmulatedVehicleServer::onFakeValueGenerated(const VehiclePropValue& value) {
- constexpr bool updateStatus = true;
- LOG(DEBUG) << __func__ << ": " << toString(value);
- auto updatedPropValue = getValuePool()->obtain(value);
- if (updatedPropValue) {
- updatedPropValue->timestamp = value.timestamp;
- updatedPropValue->status = VehiclePropertyStatus::AVAILABLE;
- onPropertyValueFromCar(*updatedPropValue, updateStatus);
- }
-}
-
-std::vector<VehiclePropConfig> EmulatedVehicleServer::onGetAllPropertyConfig() const {
- std::vector<VehiclePropConfig> vehiclePropConfigs;
- constexpr size_t numOfVehiclePropConfigs =
- sizeof(kVehicleProperties) / sizeof(kVehicleProperties[0]);
- vehiclePropConfigs.reserve(numOfVehiclePropConfigs);
- for (auto& it : kVehicleProperties) {
- vehiclePropConfigs.emplace_back(it.config);
- }
- return vehiclePropConfigs;
-}
-
-StatusCode EmulatedVehicleServer::handleGenerateFakeDataRequest(const VehiclePropValue& request) {
- constexpr bool updateStatus = true;
-
- LOG(INFO) << __func__;
- const auto& v = request.value;
- if (!v.int32Values.size()) {
- LOG(ERROR) << __func__ << ": expected at least \"command\" field in int32Values";
- return StatusCode::INVALID_ARG;
- }
-
- FakeDataCommand command = static_cast<FakeDataCommand>(v.int32Values[0]);
-
- switch (command) {
- case FakeDataCommand::StartLinear: {
- LOG(INFO) << __func__ << ", FakeDataCommand::StartLinear";
- if (v.int32Values.size() < 2) {
- LOG(ERROR) << __func__ << ": expected property ID in int32Values";
- return StatusCode::INVALID_ARG;
- }
- if (!v.int64Values.size()) {
- LOG(ERROR) << __func__ << ": interval is not provided in int64Values";
- return StatusCode::INVALID_ARG;
- }
- if (v.floatValues.size() < 3) {
- LOG(ERROR) << __func__ << ": expected at least 3 elements in floatValues, got: "
- << v.floatValues.size();
- return StatusCode::INVALID_ARG;
- }
- int32_t cookie = v.int32Values[1];
- getGenerator()->registerGenerator(cookie,
- std::make_unique<LinearFakeValueGenerator>(request));
- break;
- }
- case FakeDataCommand::StartJson: {
- LOG(INFO) << __func__ << ", FakeDataCommand::StartJson";
- if (v.stringValue.empty()) {
- LOG(ERROR) << __func__ << ": path to JSON file is missing";
- return StatusCode::INVALID_ARG;
- }
- int32_t cookie = std::hash<std::string>()(v.stringValue);
- getGenerator()->registerGenerator(cookie,
- std::make_unique<JsonFakeValueGenerator>(request));
- break;
- }
- case FakeDataCommand::StopLinear: {
- LOG(INFO) << __func__ << ", FakeDataCommand::StopLinear";
- if (v.int32Values.size() < 2) {
- LOG(ERROR) << __func__ << ": expected property ID in int32Values";
- return StatusCode::INVALID_ARG;
- }
- int32_t cookie = v.int32Values[1];
- getGenerator()->unregisterGenerator(cookie);
- break;
- }
- case FakeDataCommand::StopJson: {
- LOG(INFO) << __func__ << ", FakeDataCommand::StopJson";
- if (v.stringValue.empty()) {
- LOG(ERROR) << __func__ << ": path to JSON file is missing";
- return StatusCode::INVALID_ARG;
- }
- int32_t cookie = std::hash<std::string>()(v.stringValue);
- getGenerator()->unregisterGenerator(cookie);
- break;
- }
- case FakeDataCommand::KeyPress: {
- LOG(INFO) << __func__ << ", FakeDataCommand::KeyPress";
- int32_t keyCode = request.value.int32Values[2];
- int32_t display = request.value.int32Values[3];
- // Send back to HAL
- onPropertyValueFromCar(
- *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_DOWN, keyCode, display),
- updateStatus);
- onPropertyValueFromCar(
- *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_UP, keyCode, display),
- updateStatus);
- break;
- }
- default: {
- LOG(ERROR) << __func__ << ": unexpected command: " << toInt(command);
- return StatusCode::INVALID_ARG;
- }
- }
- return StatusCode::OK;
-}
-
-VehicleHal::VehiclePropValuePtr EmulatedVehicleServer::createApPowerStateReq(
- VehicleApPowerStateReq state, int32_t param) {
- auto req = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 2);
- req->prop = toInt(VehicleProperty::AP_POWER_STATE_REQ);
- req->areaId = 0;
- req->timestamp = elapsedRealtimeNano();
- req->status = VehiclePropertyStatus::AVAILABLE;
- req->value.int32Values[0] = toInt(state);
- req->value.int32Values[1] = param;
- return req;
-}
-
-VehicleHal::VehiclePropValuePtr EmulatedVehicleServer::createHwInputKeyProp(
- VehicleHwKeyInputAction action, int32_t keyCode, int32_t targetDisplay) {
- auto keyEvent = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 3);
- keyEvent->prop = toInt(VehicleProperty::HW_KEY_INPUT);
- keyEvent->areaId = 0;
- keyEvent->timestamp = elapsedRealtimeNano();
- keyEvent->status = VehiclePropertyStatus::AVAILABLE;
- keyEvent->value.int32Values[0] = toInt(action);
- keyEvent->value.int32Values[1] = keyCode;
- keyEvent->value.int32Values[2] = targetDisplay;
- return keyEvent;
-}
-
-StatusCode EmulatedVehicleServer::onSetProperty(const VehiclePropValue& value, bool updateStatus) {
- // Some properties need to be treated non-trivially
- switch (value.prop) {
- case kGenerateFakeDataControllingProperty:
- return handleGenerateFakeDataRequest(value);
-
- // set the value from vehicle side, used in end to end test.
- case kSetIntPropertyFromVehicleForTest: {
- auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::INT32, 1);
- updatedPropValue->prop = value.value.int32Values[0];
- updatedPropValue->value.int32Values[0] = value.value.int32Values[1];
- updatedPropValue->timestamp = value.value.int64Values[0];
- updatedPropValue->areaId = value.areaId;
- onPropertyValueFromCar(*updatedPropValue, updateStatus);
- return StatusCode::OK;
- }
- case kSetFloatPropertyFromVehicleForTest: {
- auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::FLOAT, 1);
- updatedPropValue->prop = value.value.int32Values[0];
- updatedPropValue->value.floatValues[0] = value.value.floatValues[0];
- updatedPropValue->timestamp = value.value.int64Values[0];
- updatedPropValue->areaId = value.areaId;
- onPropertyValueFromCar(*updatedPropValue, updateStatus);
- return StatusCode::OK;
- }
- case kSetBooleanPropertyFromVehicleForTest: {
- auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::BOOLEAN, 1);
- updatedPropValue->prop = value.value.int32Values[1];
- updatedPropValue->value.int32Values[0] = value.value.int32Values[0];
- updatedPropValue->timestamp = value.value.int64Values[0];
- updatedPropValue->areaId = value.areaId;
- onPropertyValueFromCar(*updatedPropValue, updateStatus);
- return StatusCode::OK;
- }
-
- case AP_POWER_STATE_REPORT:
- switch (value.value.int32Values[0]) {
- case toInt(VehicleApPowerStateReport::DEEP_SLEEP_EXIT):
- case toInt(VehicleApPowerStateReport::SHUTDOWN_CANCELLED):
- case toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL):
- // CPMS is in WAIT_FOR_VHAL state, simply move to ON
- // Send back to HAL
- // ALWAYS update status for generated property value
- onPropertyValueFromCar(*createApPowerStateReq(VehicleApPowerStateReq::ON, 0),
- true /* updateStatus */);
- break;
- case toInt(VehicleApPowerStateReport::DEEP_SLEEP_ENTRY):
- case toInt(VehicleApPowerStateReport::SHUTDOWN_START):
- // CPMS is in WAIT_FOR_FINISH state, send the FINISHED command
- // Send back to HAL
- // ALWAYS update status for generated property value
- onPropertyValueFromCar(
- *createApPowerStateReq(VehicleApPowerStateReq::FINISHED, 0),
- true /* updateStatus */);
- break;
- case toInt(VehicleApPowerStateReport::ON):
- case toInt(VehicleApPowerStateReport::SHUTDOWN_POSTPONE):
- case toInt(VehicleApPowerStateReport::SHUTDOWN_PREPARE):
- // Do nothing
- break;
- default:
- // Unknown state
- break;
- }
- break;
- case INITIAL_USER_INFO:
- return onSetInitialUserInfo(value, updateStatus);
- default:
- break;
- }
-
- // In the real vhal, the value will be sent to Car ECU.
- // We just pretend it is done here and send back to HAL
- auto updatedPropValue = getValuePool()->obtain(value);
- updatedPropValue->timestamp = elapsedRealtimeNano();
-
- onPropertyValueFromCar(*updatedPropValue, updateStatus);
- return StatusCode::OK;
-}
-
-/**
- * INITIAL_USER_INFO is called by Android when it starts, and it's expecting a property change
- * indicating what the initial user should be.
- *
- * During normal circumstances, the emulator will reply right away, passing a response if
- * InitialUserInfoResponseAction::DEFAULT (so Android could use its own logic to decide which user
- * to boot).
- *
- * But during development / testing, the behavior can be changed using lshal dump, which must use
- * the areaId to indicate what should happen next.
- *
- * So, the behavior of set(INITIAL_USER_INFO) is:
- *
- * - if it has an areaId, store the property into mInitialUserResponseFromCmd (as it was called by
- * lshal).
- * - else if mInitialUserResponseFromCmd is not set, return a response with the same request id and
- * InitialUserInfoResponseAction::DEFAULT
- * - else the behavior is defined by the areaId on mInitialUserResponseFromCmd:
- * - if it's 1, reply with mInitialUserResponseFromCmd and the right request id
- * - if it's 2, reply with mInitialUserResponseFromCmd but a wrong request id (so Android can test
- * this error scenario)
- * - if it's 3, then don't send a property change (so Android can emulate a timeout)
- *
- */
-StatusCode EmulatedVehicleServer::onSetInitialUserInfo(const VehiclePropValue& value,
- bool updateStatus) {
- // TODO: LOG calls below might be more suited to be DEBUG, but those are not being logged
- // (even when explicitly calling setprop log.tag. As this class should be using ALOG instead of
- // LOG, it's not worth investigating why...
-
- if (value.value.int32Values.size() == 0) {
- LOG(ERROR) << "set(INITIAL_USER_INFO): no int32values, ignoring it: " << toString(value);
- return StatusCode::INVALID_ARG;
- }
-
- if (value.areaId != 0) {
- LOG(INFO) << "set(INITIAL_USER_INFO) called from lshal; storing it: " << toString(value);
- mInitialUserResponseFromCmd.reset(new VehiclePropValue(value));
- return StatusCode::OK;
- }
- LOG(INFO) << "set(INITIAL_USER_INFO) called from Android: " << toString(value);
-
- int32_t requestId = value.value.int32Values[0];
-
- // Create the update property and set common values
- auto updatedValue = createVehiclePropValue(VehiclePropertyType::MIXED, 0);
- updatedValue->prop = INITIAL_USER_INFO;
- updatedValue->timestamp = elapsedRealtimeNano();
-
- if (mInitialUserResponseFromCmd == nullptr) {
- updatedValue->value.int32Values.resize(2);
- updatedValue->value.int32Values[0] = requestId;
- updatedValue->value.int32Values[1] = (int32_t)InitialUserInfoResponseAction::DEFAULT;
- LOG(INFO) << "no lshal response; returning InitialUserInfoResponseAction::DEFAULT: "
- << toString(*updatedValue);
- onPropertyValueFromCar(*updatedValue, updateStatus);
- return StatusCode::OK;
- }
-
- // mInitialUserResponseFromCmd is used for just one request
- std::unique_ptr<VehiclePropValue> response = std::move(mInitialUserResponseFromCmd);
-
- // TODO(b/138709788): rather than populate the raw values directly, it should use the
- // libraries that convert a InitialUserInfoResponse into a VehiclePropValue)
-
- switch (response->areaId) {
- case 1:
- LOG(INFO) << "returning response with right request id";
- *updatedValue = *response;
- updatedValue->areaId = 0;
- updatedValue->value.int32Values[0] = requestId;
- break;
- case 2:
- LOG(INFO) << "returning response with wrong request id";
- *updatedValue = *response;
- updatedValue->areaId = 0;
- updatedValue->value.int32Values[0] = -requestId;
- break;
- case 3:
- LOG(INFO) << "not generating a property change event because of lshal prop: "
- << toString(*response);
- return StatusCode::OK;
- default:
- LOG(ERROR) << "invalid action on lshal response: " << toString(*response);
- return StatusCode::INTERNAL_ERROR;
- }
-
- LOG(INFO) << "updating property to: " << toString(*updatedValue);
- onPropertyValueFromCar(*updatedValue, updateStatus);
- return StatusCode::OK;
-}
-
-bool EmulatedVehicleServer::onDump(const hidl_handle& handle,
- const hidl_vec<hidl_string>& options) {
+bool EmulatedPassthroughConnector::onDump(const hidl_handle& handle,
+ const hidl_vec<hidl_string>& options) {
int fd = handle->data[0];
if (options.size() > 0) {
@@ -401,7 +71,7 @@
return true;
}
-void EmulatedVehicleServer::dumpUserHal(int fd, std::string indent) {
+void EmulatedPassthroughConnector::dumpUserHal(int fd, std::string indent) {
if (mInitialUserResponseFromCmd != nullptr) {
dprintf(fd, "%sInitial User Info: %s\n", indent.c_str(),
toString(*mInitialUserResponseFromCmd).c_str());
@@ -410,7 +80,7 @@
}
}
-EmulatedPassthroughConnectorPtr makeEmulatedPassthroughConnector() {
+PassthroughConnectorPtr makeEmulatedPassthroughConnector() {
return std::make_unique<EmulatedPassthroughConnector>();
}
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h
index 4850d32..57cbb8b 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h
@@ -18,9 +18,9 @@
#define android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleConnector_H_
#include <vhal_v2_0/VehicleConnector.h>
-#include <vhal_v2_0/VehicleHal.h>
-#include "GeneratorHub.h"
+#include "VehicleHalClient.h"
+#include "VehicleHalServer.h"
namespace android {
namespace hardware {
@@ -30,69 +30,10 @@
namespace impl {
-// Extension of the client/server interfaces for emulated vehicle
+using PassthroughConnector = IPassThroughConnector<VehicleHalClient, VehicleHalServer>;
+using PassthroughConnectorPtr = std::unique_ptr<PassthroughConnector>;
-class EmulatedVehicleClient : public IVehicleClient {
- public:
- // Type of callback function for handling the new property values
- using PropertyCallBackType = std::function<void(const VehiclePropValue&, bool updateStatus)>;
-
- // Method from IVehicleClient
- void onPropertyValue(const VehiclePropValue& value, bool updateStatus) override;
-
- void registerPropertyValueCallback(PropertyCallBackType&& callback);
-
- private:
- PropertyCallBackType mPropCallback;
-};
-
-class EmulatedVehicleServer : public IVehicleServer {
- public:
- // Methods from IVehicleServer
-
- std::vector<VehiclePropConfig> onGetAllPropertyConfig() const override;
-
- StatusCode onSetProperty(const VehiclePropValue& value, bool updateStatus) override;
-
- bool onDump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
-
- // Set the Property Value Pool used in this server
- void setValuePool(VehiclePropValuePool* valuePool);
-
- private:
- GeneratorHub* getGenerator();
-
- VehiclePropValuePool* getValuePool() const;
-
- void onFakeValueGenerated(const VehiclePropValue& value);
-
- StatusCode handleGenerateFakeDataRequest(const VehiclePropValue& request);
-
- VehicleHal::VehiclePropValuePtr createApPowerStateReq(VehicleApPowerStateReq req, int32_t param);
-
- VehicleHal::VehiclePropValuePtr createHwInputKeyProp(VehicleHwKeyInputAction action,
- int32_t keyCode, int32_t targetDisplay);
-
- // private data members
-
- GeneratorHub mGeneratorHub{
- std::bind(&EmulatedVehicleServer::onFakeValueGenerated, this, std::placeholders::_1)};
-
- VehiclePropValuePool* mValuePool{nullptr};
-
- // TODO(b/146207078): it might be clearer to move members below to an EmulatedUserHal class
- std::unique_ptr<VehiclePropValue> mInitialUserResponseFromCmd;
- StatusCode onSetInitialUserInfo(const VehiclePropValue& value, bool updateStatus);
- void dumpUserHal(int fd, std::string indent);
-};
-
-// Helper functions
-
-using EmulatedPassthroughConnector =
- IPassThroughConnector<EmulatedVehicleClient, EmulatedVehicleServer>;
-using EmulatedPassthroughConnectorPtr = std::unique_ptr<EmulatedPassthroughConnector>;
-
-EmulatedPassthroughConnectorPtr makeEmulatedPassthroughConnector();
+PassthroughConnectorPtr makeEmulatedPassthroughConnector();
} // namespace impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
index 692c7f7..6d5f23f 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
@@ -87,12 +87,11 @@
return sensorStore;
}
-EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore,
- EmulatedVehicleClient* client)
+EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client)
: mPropStore(propStore),
mHvacPowerProps(std::begin(kHvacPowerProperties), std::end(kHvacPowerProperties)),
- mRecurrentTimer(
- std::bind(&EmulatedVehicleHal::onContinuousPropertyTimer, this, std::placeholders::_1)),
+ mRecurrentTimer(std::bind(&EmulatedVehicleHal::onContinuousPropertyTimer, this,
+ std::placeholders::_1)),
mVehicleClient(client) {
initStaticConfig();
for (size_t i = 0; i < arraysize(kVehicleProperties); i++) {
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
index ebc405e..ebf1995 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
@@ -46,7 +46,7 @@
class EmulatedVehicleHal : public EmulatedVehicleHalIface {
public:
EmulatedVehicleHal(VehiclePropertyStore* propStore,
- EmulatedVehicleClient* client);
+ VehicleHalClient* client);
~EmulatedVehicleHal() = default;
// Methods from VehicleHal
@@ -85,7 +85,7 @@
VehiclePropertyStore* mPropStore;
std::unordered_set<int32_t> mHvacPowerProps;
RecurrentTimer mRecurrentTimer;
- EmulatedVehicleClient* mVehicleClient;
+ VehicleHalClient* mVehicleClient;
};
} // impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h
index d6ad77d..2dc502b 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h
@@ -19,6 +19,8 @@
#include <android/hardware/automotive/vehicle/2.0/types.h>
+#include <chrono>
+
namespace android {
namespace hardware {
namespace automotive {
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp
index 7bdc97c..96aaafe 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp
@@ -46,7 +46,8 @@
if (mGenCfg.currentValue > mGenCfg.initialValue + mGenCfg.dispersion) {
mGenCfg.currentValue = mGenCfg.initialValue - mGenCfg.dispersion;
}
- VehiclePropValue event = {.prop = mGenCfg.propId};
+ // TODO: (chenhaosjtuacm) remove "{}" if AGL compiler updated
+ VehiclePropValue event = {.timestamp = {}, .areaId = {}, .prop = mGenCfg.propId};
auto& value = event.value;
switch (getPropType(event.prop)) {
case VehiclePropertyType::INT32:
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.cpp
new file mode 100644
index 0000000..25ffc6d
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "VehicleHalClient.h"
+
+#include <android-base/logging.h>
+
+namespace android::hardware::automotive::vehicle::V2_0::impl {
+
+void VehicleHalClient::onPropertyValue(const VehiclePropValue& value, bool updateStatus) {
+ if (!mPropCallback) {
+ LOG(ERROR) << __func__ << ": PropertyCallBackType is not registered!";
+ return;
+ }
+ return mPropCallback(value, updateStatus);
+}
+
+void VehicleHalClient::registerPropertyValueCallback(PropertyCallBackType&& callback) {
+ if (mPropCallback) {
+ LOG(ERROR) << __func__ << ": Cannot register multiple callbacks!";
+ return;
+ }
+ mPropCallback = std::move(callback);
+}
+
+} // namespace android::hardware::automotive::vehicle::V2_0::impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.h
new file mode 100644
index 0000000..6559e2a
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalClient.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <vhal_v2_0/VehicleClient.h>
+
+namespace android::hardware::automotive::vehicle::V2_0::impl {
+
+// The common client operations that may be used by both native and
+// virtualized VHAL clients.
+class VehicleHalClient : public IVehicleClient {
+ public:
+ // Type of callback function for handling the new property values
+ using PropertyCallBackType = std::function<void(const VehiclePropValue&, bool updateStatus)>;
+
+ // Method from IVehicleClient
+ void onPropertyValue(const VehiclePropValue& value, bool updateStatus) override;
+
+ void registerPropertyValueCallback(PropertyCallBackType&& callback);
+
+ private:
+ PropertyCallBackType mPropCallback;
+};
+
+} // namespace android::hardware::automotive::vehicle::V2_0::impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp
new file mode 100644
index 0000000..a91ca8e
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp
@@ -0,0 +1,353 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "VehicleHalServer.h"
+
+#include <fstream>
+
+#include <android-base/logging.h>
+#include <utils/SystemClock.h>
+
+#include "DefaultConfig.h"
+#include "JsonFakeValueGenerator.h"
+#include "LinearFakeValueGenerator.h"
+#include "Obd2SensorStore.h"
+
+namespace android::hardware::automotive::vehicle::V2_0::impl {
+
+GeneratorHub* VehicleHalServer::getGenerator() {
+ return &mGeneratorHub;
+}
+
+VehiclePropValuePool* VehicleHalServer::getValuePool() const {
+ if (!mValuePool) {
+ LOG(WARNING) << __func__ << ": Value pool not set!";
+ }
+ return mValuePool;
+}
+
+void VehicleHalServer::setValuePool(VehiclePropValuePool* valuePool) {
+ if (!valuePool) {
+ LOG(WARNING) << __func__ << ": Setting value pool to nullptr!";
+ }
+ mValuePool = valuePool;
+}
+
+void VehicleHalServer::onFakeValueGenerated(const VehiclePropValue& value) {
+ constexpr bool updateStatus = true;
+ LOG(DEBUG) << __func__ << ": " << toString(value);
+ auto updatedPropValue = getValuePool()->obtain(value);
+ if (updatedPropValue) {
+ updatedPropValue->timestamp = value.timestamp;
+ updatedPropValue->status = VehiclePropertyStatus::AVAILABLE;
+ onPropertyValueFromCar(*updatedPropValue, updateStatus);
+ }
+}
+
+std::vector<VehiclePropConfig> VehicleHalServer::onGetAllPropertyConfig() const {
+ std::vector<VehiclePropConfig> vehiclePropConfigs;
+ constexpr size_t numOfVehiclePropConfigs =
+ sizeof(kVehicleProperties) / sizeof(kVehicleProperties[0]);
+ vehiclePropConfigs.reserve(numOfVehiclePropConfigs);
+ for (auto& it : kVehicleProperties) {
+ vehiclePropConfigs.emplace_back(it.config);
+ }
+ return vehiclePropConfigs;
+}
+
+StatusCode VehicleHalServer::handleGenerateFakeDataRequest(const VehiclePropValue& request) {
+ constexpr bool updateStatus = true;
+
+ LOG(INFO) << __func__;
+ const auto& v = request.value;
+ if (!v.int32Values.size()) {
+ LOG(ERROR) << __func__ << ": expected at least \"command\" field in int32Values";
+ return StatusCode::INVALID_ARG;
+ }
+
+ FakeDataCommand command = static_cast<FakeDataCommand>(v.int32Values[0]);
+
+ switch (command) {
+ case FakeDataCommand::StartLinear: {
+ LOG(INFO) << __func__ << ", FakeDataCommand::StartLinear";
+ if (v.int32Values.size() < 2) {
+ LOG(ERROR) << __func__ << ": expected property ID in int32Values";
+ return StatusCode::INVALID_ARG;
+ }
+ if (!v.int64Values.size()) {
+ LOG(ERROR) << __func__ << ": interval is not provided in int64Values";
+ return StatusCode::INVALID_ARG;
+ }
+ if (v.floatValues.size() < 3) {
+ LOG(ERROR) << __func__ << ": expected at least 3 elements in floatValues, got: "
+ << v.floatValues.size();
+ return StatusCode::INVALID_ARG;
+ }
+ int32_t cookie = v.int32Values[1];
+ getGenerator()->registerGenerator(cookie,
+ std::make_unique<LinearFakeValueGenerator>(request));
+ break;
+ }
+ case FakeDataCommand::StartJson: {
+ LOG(INFO) << __func__ << ", FakeDataCommand::StartJson";
+ if (v.stringValue.empty()) {
+ LOG(ERROR) << __func__ << ": path to JSON file is missing";
+ return StatusCode::INVALID_ARG;
+ }
+ int32_t cookie = std::hash<std::string>()(v.stringValue);
+ getGenerator()->registerGenerator(cookie,
+ std::make_unique<JsonFakeValueGenerator>(request));
+ break;
+ }
+ case FakeDataCommand::StopLinear: {
+ LOG(INFO) << __func__ << ", FakeDataCommand::StopLinear";
+ if (v.int32Values.size() < 2) {
+ LOG(ERROR) << __func__ << ": expected property ID in int32Values";
+ return StatusCode::INVALID_ARG;
+ }
+ int32_t cookie = v.int32Values[1];
+ getGenerator()->unregisterGenerator(cookie);
+ break;
+ }
+ case FakeDataCommand::StopJson: {
+ LOG(INFO) << __func__ << ", FakeDataCommand::StopJson";
+ if (v.stringValue.empty()) {
+ LOG(ERROR) << __func__ << ": path to JSON file is missing";
+ return StatusCode::INVALID_ARG;
+ }
+ int32_t cookie = std::hash<std::string>()(v.stringValue);
+ getGenerator()->unregisterGenerator(cookie);
+ break;
+ }
+ case FakeDataCommand::KeyPress: {
+ LOG(INFO) << __func__ << ", FakeDataCommand::KeyPress";
+ int32_t keyCode = request.value.int32Values[2];
+ int32_t display = request.value.int32Values[3];
+ // Send back to HAL
+ onPropertyValueFromCar(
+ *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_DOWN, keyCode, display),
+ updateStatus);
+ onPropertyValueFromCar(
+ *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_UP, keyCode, display),
+ updateStatus);
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << ": unexpected command: " << toInt(command);
+ return StatusCode::INVALID_ARG;
+ }
+ }
+ return StatusCode::OK;
+}
+
+VehicleHalServer::VehiclePropValuePtr VehicleHalServer::createApPowerStateReq(
+ VehicleApPowerStateReq state, int32_t param) {
+ auto req = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 2);
+ req->prop = toInt(VehicleProperty::AP_POWER_STATE_REQ);
+ req->areaId = 0;
+ req->timestamp = elapsedRealtimeNano();
+ req->status = VehiclePropertyStatus::AVAILABLE;
+ req->value.int32Values[0] = toInt(state);
+ req->value.int32Values[1] = param;
+ return req;
+}
+
+VehicleHalServer::VehiclePropValuePtr VehicleHalServer::createHwInputKeyProp(
+ VehicleHwKeyInputAction action, int32_t keyCode, int32_t targetDisplay) {
+ auto keyEvent = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 3);
+ keyEvent->prop = toInt(VehicleProperty::HW_KEY_INPUT);
+ keyEvent->areaId = 0;
+ keyEvent->timestamp = elapsedRealtimeNano();
+ keyEvent->status = VehiclePropertyStatus::AVAILABLE;
+ keyEvent->value.int32Values[0] = toInt(action);
+ keyEvent->value.int32Values[1] = keyCode;
+ keyEvent->value.int32Values[2] = targetDisplay;
+ return keyEvent;
+}
+
+StatusCode VehicleHalServer::onSetProperty(const VehiclePropValue& value, bool updateStatus) {
+ // Some properties need to be treated non-trivially
+ switch (value.prop) {
+ case kGenerateFakeDataControllingProperty:
+ return handleGenerateFakeDataRequest(value);
+
+ // set the value from vehicle side, used in end to end test.
+ case kSetIntPropertyFromVehicleForTest: {
+ auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::INT32, 1);
+ updatedPropValue->prop = value.value.int32Values[0];
+ updatedPropValue->value.int32Values[0] = value.value.int32Values[1];
+ updatedPropValue->timestamp = value.value.int64Values[0];
+ updatedPropValue->areaId = value.areaId;
+ onPropertyValueFromCar(*updatedPropValue, updateStatus);
+ return StatusCode::OK;
+ }
+ case kSetFloatPropertyFromVehicleForTest: {
+ auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::FLOAT, 1);
+ updatedPropValue->prop = value.value.int32Values[0];
+ updatedPropValue->value.floatValues[0] = value.value.floatValues[0];
+ updatedPropValue->timestamp = value.value.int64Values[0];
+ updatedPropValue->areaId = value.areaId;
+ onPropertyValueFromCar(*updatedPropValue, updateStatus);
+ return StatusCode::OK;
+ }
+ case kSetBooleanPropertyFromVehicleForTest: {
+ auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::BOOLEAN, 1);
+ updatedPropValue->prop = value.value.int32Values[1];
+ updatedPropValue->value.int32Values[0] = value.value.int32Values[0];
+ updatedPropValue->timestamp = value.value.int64Values[0];
+ updatedPropValue->areaId = value.areaId;
+ onPropertyValueFromCar(*updatedPropValue, updateStatus);
+ return StatusCode::OK;
+ }
+
+ case AP_POWER_STATE_REPORT:
+ switch (value.value.int32Values[0]) {
+ case toInt(VehicleApPowerStateReport::DEEP_SLEEP_EXIT):
+ case toInt(VehicleApPowerStateReport::SHUTDOWN_CANCELLED):
+ case toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL):
+ // CPMS is in WAIT_FOR_VHAL state, simply move to ON
+ // Send back to HAL
+ // ALWAYS update status for generated property value
+ onPropertyValueFromCar(*createApPowerStateReq(VehicleApPowerStateReq::ON, 0),
+ true /* updateStatus */);
+ break;
+ case toInt(VehicleApPowerStateReport::DEEP_SLEEP_ENTRY):
+ case toInt(VehicleApPowerStateReport::SHUTDOWN_START):
+ // CPMS is in WAIT_FOR_FINISH state, send the FINISHED command
+ // Send back to HAL
+ // ALWAYS update status for generated property value
+ onPropertyValueFromCar(
+ *createApPowerStateReq(VehicleApPowerStateReq::FINISHED, 0),
+ true /* updateStatus */);
+ break;
+ case toInt(VehicleApPowerStateReport::ON):
+ case toInt(VehicleApPowerStateReport::SHUTDOWN_POSTPONE):
+ case toInt(VehicleApPowerStateReport::SHUTDOWN_PREPARE):
+ // Do nothing
+ break;
+ default:
+ // Unknown state
+ break;
+ }
+ break;
+ case INITIAL_USER_INFO:
+ return onSetInitialUserInfo(value, updateStatus);
+ default:
+ break;
+ }
+
+ // In the real vhal, the value will be sent to Car ECU.
+ // We just pretend it is done here and send back to HAL
+ auto updatedPropValue = getValuePool()->obtain(value);
+ updatedPropValue->timestamp = elapsedRealtimeNano();
+
+ onPropertyValueFromCar(*updatedPropValue, updateStatus);
+ return StatusCode::OK;
+}
+
+/**
+ * INITIAL_USER_INFO is called by Android when it starts, and it's expecting a property change
+ * indicating what the initial user should be.
+ *
+ * During normal circumstances, the emulator will reply right away, passing a response if
+ * InitialUserInfoResponseAction::DEFAULT (so Android could use its own logic to decide which user
+ * to boot).
+ *
+ * But during development / testing, the behavior can be changed using lshal dump, which must use
+ * the areaId to indicate what should happen next.
+ *
+ * So, the behavior of set(INITIAL_USER_INFO) is:
+ *
+ * - if it has an areaId, store the property into mInitialUserResponseFromCmd (as it was called by
+ * lshal).
+ * - else if mInitialUserResponseFromCmd is not set, return a response with the same request id and
+ * InitialUserInfoResponseAction::DEFAULT
+ * - else the behavior is defined by the areaId on mInitialUserResponseFromCmd:
+ * - if it's 1, reply with mInitialUserResponseFromCmd and the right request id
+ * - if it's 2, reply with mInitialUserResponseFromCmd but a wrong request id (so Android can test
+ * this error scenario)
+ * - if it's 3, then don't send a property change (so Android can emulate a timeout)
+ *
+ */
+StatusCode VehicleHalServer::onSetInitialUserInfo(const VehiclePropValue& value,
+ bool updateStatus) {
+ // TODO: LOG calls below might be more suited to be DEBUG, but those are not being logged
+ // (even when explicitly calling setprop log.tag. As this class should be using ALOG instead of
+ // LOG, it's not worth investigating why...
+
+ if (value.value.int32Values.size() == 0) {
+ LOG(ERROR) << "set(INITIAL_USER_INFO): no int32values, ignoring it: " << toString(value);
+ return StatusCode::INVALID_ARG;
+ }
+
+ if (value.areaId != 0) {
+ LOG(INFO) << "set(INITIAL_USER_INFO) called from lshal; storing it: " << toString(value);
+ mInitialUserResponseFromCmd.reset(new VehiclePropValue(value));
+ return StatusCode::OK;
+ }
+ LOG(INFO) << "set(INITIAL_USER_INFO) called from Android: " << toString(value);
+
+ int32_t requestId = value.value.int32Values[0];
+
+ // Create the update property and set common values
+ auto updatedValue = createVehiclePropValue(VehiclePropertyType::MIXED, 0);
+ updatedValue->prop = INITIAL_USER_INFO;
+ updatedValue->timestamp = elapsedRealtimeNano();
+
+ if (mInitialUserResponseFromCmd == nullptr) {
+ updatedValue->value.int32Values.resize(2);
+ updatedValue->value.int32Values[0] = requestId;
+ updatedValue->value.int32Values[1] = (int32_t)InitialUserInfoResponseAction::DEFAULT;
+ LOG(INFO) << "no lshal response; returning InitialUserInfoResponseAction::DEFAULT: "
+ << toString(*updatedValue);
+ onPropertyValueFromCar(*updatedValue, updateStatus);
+ return StatusCode::OK;
+ }
+
+ // mInitialUserResponseFromCmd is used for just one request
+ std::unique_ptr<VehiclePropValue> response = std::move(mInitialUserResponseFromCmd);
+
+ // TODO(b/138709788): rather than populate the raw values directly, it should use the
+ // libraries that convert a InitialUserInfoResponse into a VehiclePropValue)
+
+ switch (response->areaId) {
+ case 1:
+ LOG(INFO) << "returning response with right request id";
+ *updatedValue = *response;
+ updatedValue->areaId = 0;
+ updatedValue->value.int32Values[0] = requestId;
+ break;
+ case 2:
+ LOG(INFO) << "returning response with wrong request id";
+ *updatedValue = *response;
+ updatedValue->areaId = 0;
+ updatedValue->value.int32Values[0] = -requestId;
+ break;
+ case 3:
+ LOG(INFO) << "not generating a property change event because of lshal prop: "
+ << toString(*response);
+ return StatusCode::OK;
+ default:
+ LOG(ERROR) << "invalid action on lshal response: " << toString(*response);
+ return StatusCode::INTERNAL_ERROR;
+ }
+
+ LOG(INFO) << "updating property to: " << toString(*updatedValue);
+ onPropertyValueFromCar(*updatedValue, updateStatus);
+ return StatusCode::OK;
+}
+
+} // namespace android::hardware::automotive::vehicle::V2_0::impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h
new file mode 100644
index 0000000..b1ae106
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <vhal_v2_0/VehicleObjectPool.h>
+#include <vhal_v2_0/VehicleServer.h>
+
+#include "GeneratorHub.h"
+
+namespace android::hardware::automotive::vehicle::V2_0::impl {
+
+// This contains the common server operations that will be used by
+// both native and virtualized VHAL server. Notice that in the virtualized
+// scenario, the server may be run on a different OS than Android.
+class VehicleHalServer : public IVehicleServer {
+ public:
+ // Methods from IVehicleServer
+
+ std::vector<VehiclePropConfig> onGetAllPropertyConfig() const override;
+
+ StatusCode onSetProperty(const VehiclePropValue& value, bool updateStatus) override;
+
+ // Set the Property Value Pool used in this server
+ void setValuePool(VehiclePropValuePool* valuePool);
+
+ private:
+ using VehiclePropValuePtr = recyclable_ptr<VehiclePropValue>;
+
+ GeneratorHub* getGenerator();
+
+ VehiclePropValuePool* getValuePool() const;
+
+ void onFakeValueGenerated(const VehiclePropValue& value);
+
+ StatusCode handleGenerateFakeDataRequest(const VehiclePropValue& request);
+
+ VehiclePropValuePtr createApPowerStateReq(VehicleApPowerStateReq req, int32_t param);
+
+ VehiclePropValuePtr createHwInputKeyProp(VehicleHwKeyInputAction action, int32_t keyCode,
+ int32_t targetDisplay);
+
+ StatusCode onSetInitialUserInfo(const VehiclePropValue& value, bool updateStatus);
+
+ // data members
+
+ protected:
+ // TODO(b/146207078): it might be clearer to move members below to an EmulatedUserHal class
+ std::unique_ptr<VehiclePropValue> mInitialUserResponseFromCmd;
+
+ private:
+ GeneratorHub mGeneratorHub{
+ std::bind(&VehicleHalServer::onFakeValueGenerated, this, std::placeholders::_1)};
+
+ VehiclePropValuePool* mValuePool{nullptr};
+};
+
+} // namespace android::hardware::automotive::vehicle::V2_0::impl
diff --git a/boot/1.1/default/boot_control/Android.bp b/boot/1.1/default/boot_control/Android.bp
new file mode 100644
index 0000000..b2e68df
--- /dev/null
+++ b/boot/1.1/default/boot_control/Android.bp
@@ -0,0 +1,61 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_defaults {
+ name: "libboot_control_defaults",
+ vendor: true,
+ recovery_available: true,
+ relative_install_path: "hw",
+
+ cflags: [
+ "-D_FILE_OFFSET_BITS=64",
+ "-Werror",
+ "-Wall",
+ "-Wextra",
+ ],
+
+ shared_libs: [
+ "android.hardware.boot@1.1",
+ "libbase",
+ "liblog",
+ ],
+ static_libs: [
+ "libbootloader_message_vendor",
+ "libfstab",
+ ],
+}
+
+cc_library_static {
+ name: "libboot_control",
+ defaults: ["libboot_control_defaults"],
+ export_include_dirs: ["include"],
+
+ srcs: ["libboot_control.cpp"],
+}
+
+cc_library_shared {
+ name: "bootctrl.default",
+ defaults: ["libboot_control_defaults"],
+
+ srcs: ["legacy_boot_control.cpp"],
+
+ static_libs: [
+ "libboot_control",
+ ],
+ shared_libs: [
+ "libhardware",
+ ],
+}
diff --git a/boot/1.1/default/boot_control/include/libboot_control/libboot_control.h b/boot/1.1/default/boot_control/include/libboot_control/libboot_control.h
new file mode 100644
index 0000000..5468658
--- /dev/null
+++ b/boot/1.1/default/boot_control/include/libboot_control/libboot_control.h
@@ -0,0 +1,89 @@
+//
+// 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 <string>
+
+#include <android/hardware/boot/1.1/IBootControl.h>
+
+namespace android {
+namespace bootable {
+
+// Helper library to implement the IBootControl HAL using the misc partition.
+class BootControl {
+ using MergeStatus = ::android::hardware::boot::V1_1::MergeStatus;
+
+ public:
+ bool Init();
+ unsigned int GetNumberSlots();
+ unsigned int GetCurrentSlot();
+ bool MarkBootSuccessful();
+ bool SetActiveBootSlot(unsigned int slot);
+ bool SetSlotAsUnbootable(unsigned int slot);
+ bool SetSlotBootable(unsigned int slot);
+ bool IsSlotBootable(unsigned int slot);
+ const char* GetSuffix(unsigned int slot);
+ bool IsSlotMarkedSuccessful(unsigned int slot);
+ bool SetSnapshotMergeStatus(MergeStatus status);
+ MergeStatus GetSnapshotMergeStatus();
+
+ bool IsValidSlot(unsigned int slot);
+
+ const std::string& misc_device() const {
+ return misc_device_;
+ }
+
+ private:
+ // Whether this object was initialized with data from the bootloader message
+ // that doesn't change until next reboot.
+ bool initialized_ = false;
+
+ // The path to the misc_device as reported in the fstab.
+ std::string misc_device_;
+
+ // The number of slots present on the device.
+ unsigned int num_slots_ = 0;
+
+ // The slot where we are running from.
+ unsigned int current_slot_ = 0;
+};
+
+// Helper functions to write the Virtual A/B merge status message. These are
+// separate because BootControl uses bootloader_control_ab in vendor space,
+// whereas the Virtual A/B merge status is in system space. A HAL might not
+// use bootloader_control_ab, but may want to use the AOSP method of maintaining
+// the merge status.
+
+// If the Virtual A/B message has not yet been initialized, then initialize it.
+// This should be called when the BootControl HAL first loads.
+//
+// If the Virtual A/B message in misc was already initialized, true is returned.
+// If initialization was attempted, but failed, false is returned, and the HAL
+// should fail to load.
+bool InitMiscVirtualAbMessageIfNeeded();
+
+// Save the current merge status as well as the current slot.
+bool SetMiscVirtualAbMergeStatus(unsigned int current_slot,
+ android::hardware::boot::V1_1::MergeStatus status);
+
+// Return the current merge status. If the saved status is SNAPSHOTTED but the
+// slot hasn't changed, the status returned will be NONE.
+bool GetMiscVirtualAbMergeStatus(unsigned int current_slot,
+ android::hardware::boot::V1_1::MergeStatus* status);
+
+} // namespace bootable
+} // namespace android
diff --git a/boot/1.1/default/boot_control/include/private/boot_control_definition.h b/boot/1.1/default/boot_control/include/private/boot_control_definition.h
new file mode 100644
index 0000000..8f02111
--- /dev/null
+++ b/boot/1.1/default/boot_control/include/private/boot_control_definition.h
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+
+
+/**
+ * The A/B-specific bootloader message structure (4-KiB).
+ *
+ * We separate A/B boot control metadata from the regular bootloader
+ * message struct and keep it here. Everything that's A/B-specific
+ * stays after struct bootloader_message, which belongs to the vendor
+ * space of /misc partition. Also, the A/B-specific contents should be
+ * managed by the A/B-bootloader or boot control HAL.
+ *
+ * The slot_suffix field is used for A/B implementations where the
+ * bootloader does not set the androidboot.ro.boot.slot_suffix kernel
+ * commandline parameter. This is used by fs_mgr to mount /system and
+ * other partitions with the slotselect flag set in fstab. A/B
+ * implementations are free to use all 32 bytes and may store private
+ * data past the first NUL-byte in this field. It is encouraged, but
+ * not mandatory, to use 'struct bootloader_control' described below.
+ *
+ * The update_channel field is used to store the Omaha update channel
+ * if update_engine is compiled with Omaha support.
+ */
+struct bootloader_message_ab {
+ struct bootloader_message message;
+ char slot_suffix[32];
+ char update_channel[128];
+
+ // Round up the entire struct to 4096-byte.
+ char reserved[1888];
+};
+
+/**
+ * Be cautious about the struct size change, in case we put anything post
+ * bootloader_message_ab struct (b/29159185).
+ */
+#if (__STDC_VERSION__ >= 201112L) || defined(__cplusplus)
+static_assert(sizeof(struct bootloader_message_ab) == 4096,
+ "struct bootloader_message_ab size changes");
+#endif
+
+#define BOOT_CTRL_MAGIC 0x42414342 /* Bootloader Control AB */
+#define BOOT_CTRL_VERSION 1
+
+struct slot_metadata {
+ // Slot priority with 15 meaning highest priority, 1 lowest
+ // priority and 0 the slot is unbootable.
+ uint8_t priority : 4;
+ // Number of times left attempting to boot this slot.
+ uint8_t tries_remaining : 3;
+ // 1 if this slot has booted successfully, 0 otherwise.
+ uint8_t successful_boot : 1;
+ // 1 if this slot is corrupted from a dm-verity corruption, 0
+ // otherwise.
+ uint8_t verity_corrupted : 1;
+ // Reserved for further use.
+ uint8_t reserved : 7;
+} __attribute__((packed));
+
+/* Bootloader Control AB
+ *
+ * This struct can be used to manage A/B metadata. It is designed to
+ * be put in the 'slot_suffix' field of the 'bootloader_message'
+ * structure described above. It is encouraged to use the
+ * 'bootloader_control' structure to store the A/B metadata, but not
+ * mandatory.
+ */
+struct bootloader_control {
+ // NUL terminated active slot suffix.
+ char slot_suffix[4];
+ // Bootloader Control AB magic number (see BOOT_CTRL_MAGIC).
+ uint32_t magic;
+ // Version of struct being used (see BOOT_CTRL_VERSION).
+ uint8_t version;
+ // Number of slots being managed.
+ uint8_t nb_slot : 3;
+ // Number of times left attempting to boot recovery.
+ uint8_t recovery_tries_remaining : 3;
+ // Status of any pending snapshot merge of dynamic partitions.
+ uint8_t merge_status : 3;
+ // Ensure 4-bytes alignment for slot_info field.
+ uint8_t reserved0[1];
+ // Per-slot information. Up to 4 slots.
+ struct slot_metadata slot_info[4];
+ // Reserved for further use.
+ uint8_t reserved1[8];
+ // CRC32 of all 28 bytes preceding this field (little endian
+ // format).
+ uint32_t crc32_le;
+} __attribute__((packed));
+
+#if (__STDC_VERSION__ >= 201112L) || defined(__cplusplus)
+static_assert(sizeof(struct bootloader_control) ==
+ sizeof(((struct bootloader_message_ab *)0)->slot_suffix),
+ "struct bootloader_control has wrong size");
+#endif
+
diff --git a/boot/1.1/default/boot_control/legacy_boot_control.cpp b/boot/1.1/default/boot_control/legacy_boot_control.cpp
new file mode 100644
index 0000000..73d3a58
--- /dev/null
+++ b/boot/1.1/default/boot_control/legacy_boot_control.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2015 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 <string>
+
+#include <hardware/boot_control.h>
+#include <hardware/hardware.h>
+
+#include <libboot_control/libboot_control.h>
+
+using android::bootable::BootControl;
+
+struct boot_control_private_t {
+ // The base struct needs to be first in the list.
+ boot_control_module_t base;
+
+ BootControl impl;
+};
+
+namespace {
+
+void BootControl_init(boot_control_module_t* module) {
+ auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+ impl.Init();
+}
+
+unsigned int BootControl_getNumberSlots(boot_control_module_t* module) {
+ auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+ return impl.GetNumberSlots();
+}
+
+unsigned int BootControl_getCurrentSlot(boot_control_module_t* module) {
+ auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+ return impl.GetCurrentSlot();
+}
+
+int BootControl_markBootSuccessful(boot_control_module_t* module) {
+ auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+ return impl.MarkBootSuccessful() ? 0 : -1;
+}
+
+int BootControl_setActiveBootSlot(boot_control_module_t* module, unsigned int slot) {
+ auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+ return impl.SetActiveBootSlot(slot) ? 0 : -1;
+}
+
+int BootControl_setSlotAsUnbootable(struct boot_control_module* module, unsigned int slot) {
+ auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+ return impl.SetSlotAsUnbootable(slot) ? 0 : -1;
+}
+
+int BootControl_isSlotBootable(struct boot_control_module* module, unsigned int slot) {
+ auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+ return impl.IsSlotBootable(slot) ? 0 : -1;
+}
+
+int BootControl_isSlotMarkedSuccessful(struct boot_control_module* module, unsigned int slot) {
+ auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+ return impl.IsSlotMarkedSuccessful(slot) ? 0 : -1;
+}
+
+const char* BootControl_getSuffix(boot_control_module_t* module, unsigned int slot) {
+ auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+ return impl.GetSuffix(slot);
+}
+
+static int BootControl_open(const hw_module_t* module __unused, const char* id __unused,
+ hw_device_t** device __unused) {
+ /* Nothing to do currently. */
+ return 0;
+}
+
+struct hw_module_methods_t BootControl_methods = {
+ .open = BootControl_open,
+};
+
+} // namespace
+
+boot_control_private_t HAL_MODULE_INFO_SYM = {
+ .base =
+ {
+ .common =
+ {
+ .tag = HARDWARE_MODULE_TAG,
+ .module_api_version = BOOT_CONTROL_MODULE_API_VERSION_0_1,
+ .hal_api_version = HARDWARE_HAL_API_VERSION,
+ .id = BOOT_CONTROL_HARDWARE_MODULE_ID,
+ .name = "AOSP reference bootctrl HAL",
+ .author = "The Android Open Source Project",
+ .methods = &BootControl_methods,
+ },
+ .init = BootControl_init,
+ .getNumberSlots = BootControl_getNumberSlots,
+ .getCurrentSlot = BootControl_getCurrentSlot,
+ .markBootSuccessful = BootControl_markBootSuccessful,
+ .setActiveBootSlot = BootControl_setActiveBootSlot,
+ .setSlotAsUnbootable = BootControl_setSlotAsUnbootable,
+ .isSlotBootable = BootControl_isSlotBootable,
+ .getSuffix = BootControl_getSuffix,
+ .isSlotMarkedSuccessful = BootControl_isSlotMarkedSuccessful,
+ },
+};
diff --git a/boot/1.1/default/boot_control/libboot_control.cpp b/boot/1.1/default/boot_control/libboot_control.cpp
new file mode 100644
index 0000000..2c6ccaf
--- /dev/null
+++ b/boot/1.1/default/boot_control/libboot_control.cpp
@@ -0,0 +1,425 @@
+/*
+ * Copyright (C) 2015 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 <libboot_control/libboot_control.h>
+
+#include <endian.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <string>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
+#include <bootloader_message/bootloader_message.h>
+
+#include "private/boot_control_definition.h"
+
+namespace android {
+namespace bootable {
+
+using ::android::hardware::boot::V1_1::MergeStatus;
+
+// The number of boot attempts that should be made from a new slot before
+// rolling back to the previous slot.
+constexpr unsigned int kDefaultBootAttempts = 7;
+static_assert(kDefaultBootAttempts < 8, "tries_remaining field only has 3 bits");
+
+constexpr unsigned int kMaxNumSlots =
+ sizeof(bootloader_control::slot_info) / sizeof(bootloader_control::slot_info[0]);
+constexpr const char* kSlotSuffixes[kMaxNumSlots] = { "_a", "_b", "_c", "_d" };
+constexpr off_t kBootloaderControlOffset = offsetof(bootloader_message_ab, slot_suffix);
+
+static uint32_t CRC32(const uint8_t* buf, size_t size) {
+ static uint32_t crc_table[256];
+
+ // Compute the CRC-32 table only once.
+ if (!crc_table[1]) {
+ for (uint32_t i = 0; i < 256; ++i) {
+ uint32_t crc = i;
+ for (uint32_t j = 0; j < 8; ++j) {
+ uint32_t mask = -(crc & 1);
+ crc = (crc >> 1) ^ (0xEDB88320 & mask);
+ }
+ crc_table[i] = crc;
+ }
+ }
+
+ uint32_t ret = -1;
+ for (size_t i = 0; i < size; ++i) {
+ ret = (ret >> 8) ^ crc_table[(ret ^ buf[i]) & 0xFF];
+ }
+
+ return ~ret;
+}
+
+// Return the little-endian representation of the CRC-32 of the first fields
+// in |boot_ctrl| up to the crc32_le field.
+uint32_t BootloaderControlLECRC(const bootloader_control* boot_ctrl) {
+ return htole32(
+ CRC32(reinterpret_cast<const uint8_t*>(boot_ctrl), offsetof(bootloader_control, crc32_le)));
+}
+
+bool LoadBootloaderControl(const std::string& misc_device, bootloader_control* buffer) {
+ android::base::unique_fd fd(open(misc_device.c_str(), O_RDONLY));
+ if (fd.get() == -1) {
+ PLOG(ERROR) << "failed to open " << misc_device;
+ return false;
+ }
+ if (lseek(fd, kBootloaderControlOffset, SEEK_SET) != kBootloaderControlOffset) {
+ PLOG(ERROR) << "failed to lseek " << misc_device;
+ return false;
+ }
+ if (!android::base::ReadFully(fd.get(), buffer, sizeof(bootloader_control))) {
+ PLOG(ERROR) << "failed to read " << misc_device;
+ return false;
+ }
+ return true;
+}
+
+bool UpdateAndSaveBootloaderControl(const std::string& misc_device, bootloader_control* buffer) {
+ buffer->crc32_le = BootloaderControlLECRC(buffer);
+ android::base::unique_fd fd(open(misc_device.c_str(), O_WRONLY | O_SYNC));
+ if (fd.get() == -1) {
+ PLOG(ERROR) << "failed to open " << misc_device;
+ return false;
+ }
+ if (lseek(fd.get(), kBootloaderControlOffset, SEEK_SET) != kBootloaderControlOffset) {
+ PLOG(ERROR) << "failed to lseek " << misc_device;
+ return false;
+ }
+ if (!android::base::WriteFully(fd.get(), buffer, sizeof(bootloader_control))) {
+ PLOG(ERROR) << "failed to write " << misc_device;
+ return false;
+ }
+ return true;
+}
+
+void InitDefaultBootloaderControl(BootControl* control, bootloader_control* boot_ctrl) {
+ memset(boot_ctrl, 0, sizeof(*boot_ctrl));
+
+ unsigned int current_slot = control->GetCurrentSlot();
+ if (current_slot < kMaxNumSlots) {
+ strlcpy(boot_ctrl->slot_suffix, kSlotSuffixes[current_slot], sizeof(boot_ctrl->slot_suffix));
+ }
+ boot_ctrl->magic = BOOT_CTRL_MAGIC;
+ boot_ctrl->version = BOOT_CTRL_VERSION;
+
+ // Figure out the number of slots by checking if the partitions exist,
+ // otherwise assume the maximum supported by the header.
+ boot_ctrl->nb_slot = kMaxNumSlots;
+ std::string base_path = control->misc_device();
+ size_t last_path_sep = base_path.rfind('/');
+ if (last_path_sep != std::string::npos) {
+ // We test the existence of the "boot" partition on each possible slot,
+ // which is a partition required by Android Bootloader Requirements.
+ base_path = base_path.substr(0, last_path_sep + 1) + "boot";
+ int last_existing_slot = -1;
+ int first_missing_slot = -1;
+ for (unsigned int slot = 0; slot < kMaxNumSlots; ++slot) {
+ std::string partition_path = base_path + kSlotSuffixes[slot];
+ struct stat part_stat;
+ int err = stat(partition_path.c_str(), &part_stat);
+ if (!err) {
+ last_existing_slot = slot;
+ LOG(INFO) << "Found slot: " << kSlotSuffixes[slot];
+ } else if (err < 0 && errno == ENOENT && first_missing_slot == -1) {
+ first_missing_slot = slot;
+ }
+ }
+ // We only declare that we found the actual number of slots if we found all
+ // the boot partitions up to the number of slots, and no boot partition
+ // after that. Not finding any of the boot partitions implies a problem so
+ // we just leave the number of slots in the maximum value.
+ if ((last_existing_slot != -1 && last_existing_slot + 1 == first_missing_slot) ||
+ (first_missing_slot == -1 && last_existing_slot + 1 == kMaxNumSlots)) {
+ boot_ctrl->nb_slot = last_existing_slot + 1;
+ LOG(INFO) << "Found a system with " << last_existing_slot + 1 << " slots.";
+ }
+ }
+
+ for (unsigned int slot = 0; slot < kMaxNumSlots; ++slot) {
+ slot_metadata entry = {};
+
+ if (slot < boot_ctrl->nb_slot) {
+ entry.priority = 7;
+ entry.tries_remaining = kDefaultBootAttempts;
+ entry.successful_boot = 0;
+ } else {
+ entry.priority = 0; // Unbootable
+ }
+
+ // When the boot_control stored on disk is invalid, we assume that the
+ // current slot is successful. The bootloader should repair this situation
+ // before booting and write a valid boot_control slot, so if we reach this
+ // stage it means that the misc partition was corrupted since boot.
+ if (current_slot == slot) {
+ entry.successful_boot = 1;
+ }
+
+ boot_ctrl->slot_info[slot] = entry;
+ }
+ boot_ctrl->recovery_tries_remaining = 0;
+
+ boot_ctrl->crc32_le = BootloaderControlLECRC(boot_ctrl);
+}
+
+// Return the index of the slot suffix passed or -1 if not a valid slot suffix.
+int SlotSuffixToIndex(const char* suffix) {
+ for (unsigned int slot = 0; slot < kMaxNumSlots; ++slot) {
+ if (!strcmp(kSlotSuffixes[slot], suffix)) return slot;
+ }
+ return -1;
+}
+
+// Initialize the boot_control_private struct with the information from
+// the bootloader_message buffer stored in |boot_ctrl|. Returns whether the
+// initialization succeeded.
+bool BootControl::Init() {
+ if (initialized_) return true;
+
+ // Initialize the current_slot from the read-only property. If the property
+ // was not set (from either the command line or the device tree), we can later
+ // initialize it from the bootloader_control struct.
+ std::string suffix_prop = android::base::GetProperty("ro.boot.slot_suffix", "");
+ if (suffix_prop.empty()) {
+ LOG(ERROR) << "Slot suffix property is not set";
+ return false;
+ }
+ current_slot_ = SlotSuffixToIndex(suffix_prop.c_str());
+
+ std::string err;
+ std::string device = get_bootloader_message_blk_device(&err);
+ if (device.empty()) {
+ LOG(ERROR) << "Could not find bootloader message block device: " << err;
+ return false;
+ }
+
+ bootloader_control boot_ctrl;
+ if (!LoadBootloaderControl(device.c_str(), &boot_ctrl)) {
+ LOG(ERROR) << "Failed to load bootloader control block";
+ return false;
+ }
+
+ // Note that since there isn't a module unload function this memory is leaked.
+ // We use `device` below sometimes, so it's not moved out of here.
+ misc_device_ = device;
+ initialized_ = true;
+
+ // Validate the loaded data, otherwise we will destroy it and re-initialize it
+ // with the current information.
+ uint32_t computed_crc32 = BootloaderControlLECRC(&boot_ctrl);
+ if (boot_ctrl.crc32_le != computed_crc32) {
+ LOG(WARNING) << "Invalid boot control found, expected CRC-32 0x" << std::hex << computed_crc32
+ << " but found 0x" << std::hex << boot_ctrl.crc32_le << ". Re-initializing.";
+ InitDefaultBootloaderControl(this, &boot_ctrl);
+ UpdateAndSaveBootloaderControl(device.c_str(), &boot_ctrl);
+ }
+
+ if (!InitMiscVirtualAbMessageIfNeeded()) {
+ return false;
+ }
+
+ num_slots_ = boot_ctrl.nb_slot;
+ return true;
+}
+
+unsigned int BootControl::GetNumberSlots() {
+ return num_slots_;
+}
+
+unsigned int BootControl::GetCurrentSlot() {
+ return current_slot_;
+}
+
+bool BootControl::MarkBootSuccessful() {
+ bootloader_control bootctrl;
+ if (!LoadBootloaderControl(misc_device_, &bootctrl)) return false;
+
+ bootctrl.slot_info[current_slot_].successful_boot = 1;
+ // tries_remaining == 0 means that the slot is not bootable anymore, make
+ // sure we mark the current slot as bootable if it succeeds in the last
+ // attempt.
+ bootctrl.slot_info[current_slot_].tries_remaining = 1;
+ return UpdateAndSaveBootloaderControl(misc_device_, &bootctrl);
+}
+
+bool BootControl::SetActiveBootSlot(unsigned int slot) {
+ if (slot >= kMaxNumSlots || slot >= num_slots_) {
+ // Invalid slot number.
+ return false;
+ }
+
+ bootloader_control bootctrl;
+ if (!LoadBootloaderControl(misc_device_, &bootctrl)) return false;
+
+ // Set every other slot with a lower priority than the new "active" slot.
+ const unsigned int kActivePriority = 15;
+ const unsigned int kActiveTries = 6;
+ for (unsigned int i = 0; i < num_slots_; ++i) {
+ if (i != slot) {
+ if (bootctrl.slot_info[i].priority >= kActivePriority)
+ bootctrl.slot_info[i].priority = kActivePriority - 1;
+ }
+ }
+
+ // Note that setting a slot as active doesn't change the successful bit.
+ // The successful bit will only be changed by setSlotAsUnbootable().
+ bootctrl.slot_info[slot].priority = kActivePriority;
+ bootctrl.slot_info[slot].tries_remaining = kActiveTries;
+
+ // Setting the current slot as active is a way to revert the operation that
+ // set *another* slot as active at the end of an updater. This is commonly
+ // used to cancel the pending update. We should only reset the verity_corrpted
+ // bit when attempting a new slot, otherwise the verity bit on the current
+ // slot would be flip.
+ if (slot != current_slot_) bootctrl.slot_info[slot].verity_corrupted = 0;
+
+ return UpdateAndSaveBootloaderControl(misc_device_, &bootctrl);
+}
+
+bool BootControl::SetSlotAsUnbootable(unsigned int slot) {
+ if (slot >= kMaxNumSlots || slot >= num_slots_) {
+ // Invalid slot number.
+ return false;
+ }
+
+ bootloader_control bootctrl;
+ if (!LoadBootloaderControl(misc_device_, &bootctrl)) return false;
+
+ // The only way to mark a slot as unbootable, regardless of the priority is to
+ // set the tries_remaining to 0.
+ bootctrl.slot_info[slot].successful_boot = 0;
+ bootctrl.slot_info[slot].tries_remaining = 0;
+ return UpdateAndSaveBootloaderControl(misc_device_, &bootctrl);
+}
+
+bool BootControl::IsSlotBootable(unsigned int slot) {
+ if (slot >= kMaxNumSlots || slot >= num_slots_) {
+ // Invalid slot number.
+ return false;
+ }
+
+ bootloader_control bootctrl;
+ if (!LoadBootloaderControl(misc_device_, &bootctrl)) return false;
+
+ return bootctrl.slot_info[slot].tries_remaining != 0;
+}
+
+bool BootControl::IsSlotMarkedSuccessful(unsigned int slot) {
+ if (slot >= kMaxNumSlots || slot >= num_slots_) {
+ // Invalid slot number.
+ return false;
+ }
+
+ bootloader_control bootctrl;
+ if (!LoadBootloaderControl(misc_device_, &bootctrl)) return false;
+
+ return bootctrl.slot_info[slot].successful_boot && bootctrl.slot_info[slot].tries_remaining;
+}
+
+bool BootControl::IsValidSlot(unsigned int slot) {
+ return slot < kMaxNumSlots && slot < num_slots_;
+}
+
+bool BootControl::SetSnapshotMergeStatus(MergeStatus status) {
+ return SetMiscVirtualAbMergeStatus(current_slot_, status);
+}
+
+MergeStatus BootControl::GetSnapshotMergeStatus() {
+ MergeStatus status;
+ if (!GetMiscVirtualAbMergeStatus(current_slot_, &status)) {
+ return MergeStatus::UNKNOWN;
+ }
+ return status;
+}
+
+const char* BootControl::GetSuffix(unsigned int slot) {
+ if (slot >= kMaxNumSlots || slot >= num_slots_) {
+ return nullptr;
+ }
+ return kSlotSuffixes[slot];
+}
+
+bool InitMiscVirtualAbMessageIfNeeded() {
+ std::string err;
+ misc_virtual_ab_message message;
+ if (!ReadMiscVirtualAbMessage(&message, &err)) {
+ LOG(ERROR) << "Could not read merge status: " << err;
+ return false;
+ }
+
+ if (message.version == MISC_VIRTUAL_AB_MESSAGE_VERSION &&
+ message.magic == MISC_VIRTUAL_AB_MAGIC_HEADER) {
+ // Already initialized.
+ return true;
+ }
+
+ message = {};
+ message.version = MISC_VIRTUAL_AB_MESSAGE_VERSION;
+ message.magic = MISC_VIRTUAL_AB_MAGIC_HEADER;
+ if (!WriteMiscVirtualAbMessage(message, &err)) {
+ LOG(ERROR) << "Could not write merge status: " << err;
+ return false;
+ }
+ return true;
+}
+
+bool SetMiscVirtualAbMergeStatus(unsigned int current_slot,
+ android::hardware::boot::V1_1::MergeStatus status) {
+ std::string err;
+ misc_virtual_ab_message message;
+
+ if (!ReadMiscVirtualAbMessage(&message, &err)) {
+ LOG(ERROR) << "Could not read merge status: " << err;
+ return false;
+ }
+
+ message.merge_status = static_cast<uint8_t>(status);
+ message.source_slot = current_slot;
+ if (!WriteMiscVirtualAbMessage(message, &err)) {
+ LOG(ERROR) << "Could not write merge status: " << err;
+ return false;
+ }
+ return true;
+}
+
+bool GetMiscVirtualAbMergeStatus(unsigned int current_slot,
+ android::hardware::boot::V1_1::MergeStatus* status) {
+ std::string err;
+ misc_virtual_ab_message message;
+
+ if (!ReadMiscVirtualAbMessage(&message, &err)) {
+ LOG(ERROR) << "Could not read merge status: " << err;
+ return false;
+ }
+
+ // If the slot reverted after having created a snapshot, then the snapshot will
+ // be thrown away at boot. Thus we don't count this as being in a snapshotted
+ // state.
+ *status = static_cast<MergeStatus>(message.merge_status);
+ if (*status == MergeStatus::SNAPSHOTTED && current_slot == message.source_slot) {
+ *status = MergeStatus::NONE;
+ }
+ return true;
+}
+
+} // namespace bootable
+} // namespace android
diff --git a/camera/common/1.0/default/Exif.cpp b/camera/common/1.0/default/Exif.cpp
index 4de05c5..413b6bb 100644
--- a/camera/common/1.0/default/Exif.cpp
+++ b/camera/common/1.0/default/Exif.cpp
@@ -632,13 +632,13 @@
}
bool ExifUtilsImpl::setImageHeight(uint32_t length) {
- SET_LONG(EXIF_IFD_0, EXIF_TAG_IMAGE_LENGTH, length);
+ SET_SHORT(EXIF_IFD_0, EXIF_TAG_IMAGE_LENGTH, length);
SET_LONG(EXIF_IFD_EXIF, EXIF_TAG_PIXEL_Y_DIMENSION, length);
return true;
}
bool ExifUtilsImpl::setImageWidth(uint32_t width) {
- SET_LONG(EXIF_IFD_0, EXIF_TAG_IMAGE_WIDTH, width);
+ SET_SHORT(EXIF_IFD_0, EXIF_TAG_IMAGE_WIDTH, width);
SET_LONG(EXIF_IFD_EXIF, EXIF_TAG_PIXEL_X_DIMENSION, width);
return true;
}
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 5c73aa2..c9d76da 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -69,65 +69,67 @@
#include <android/hidl/memory/1.0/IMemory.h>
using namespace ::android::hardware::camera::device;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
+using ::android::BufferItemConsumer;
+using ::android::BufferQueue;
+using ::android::GraphicBuffer;
+using ::android::IGraphicBufferConsumer;
+using ::android::IGraphicBufferProducer;
+using ::android::sp;
+using ::android::Surface;
+using ::android::wp;
using ::android::hardware::hidl_bitfield;
using ::android::hardware::hidl_handle;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
-using ::android::sp;
-using ::android::wp;
-using ::android::GraphicBuffer;
-using ::android::IGraphicBufferProducer;
-using ::android::IGraphicBufferConsumer;
-using ::android::BufferQueue;
-using ::android::BufferItemConsumer;
-using ::android::Surface;
-using ::android::hardware::graphics::common::V1_0::BufferUsage;
-using ::android::hardware::graphics::common::V1_0::Dataspace;
-using ::android::hardware::graphics::common::V1_0::PixelFormat;
-using ::android::hardware::camera::common::V1_0::Status;
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
using ::android::hardware::camera::common::V1_0::CameraDeviceStatus;
+using ::android::hardware::camera::common::V1_0::Status;
using ::android::hardware::camera::common::V1_0::TorchMode;
using ::android::hardware::camera::common::V1_0::TorchModeStatus;
using ::android::hardware::camera::common::V1_0::helper::CameraParameters;
using ::android::hardware::camera::common::V1_0::helper::Size;
-using ::android::hardware::camera::provider::V2_4::ICameraProvider;
-using ::android::hardware::camera::provider::V2_4::ICameraProviderCallback;
-using ::android::hardware::camera::device::V3_2::ICameraDevice;
-using ::android::hardware::camera::device::V3_2::BufferCache;
-using ::android::hardware::camera::device::V3_2::CaptureRequest;
-using ::android::hardware::camera::device::V3_2::CaptureResult;
-using ::android::hardware::camera::device::V3_2::ICameraDeviceSession;
-using ::android::hardware::camera::device::V3_2::NotifyMsg;
-using ::android::hardware::camera::device::V3_2::RequestTemplate;
-using ::android::hardware::camera::device::V3_2::StreamType;
-using ::android::hardware::camera::device::V3_2::StreamRotation;
-using ::android::hardware::camera::device::V3_2::StreamConfiguration;
-using ::android::hardware::camera::device::V3_2::StreamConfigurationMode;
-using ::android::hardware::camera::device::V3_2::CameraMetadata;
-using ::android::hardware::camera::device::V3_2::HalStreamConfiguration;
-using ::android::hardware::camera::device::V3_2::BufferStatus;
-using ::android::hardware::camera::device::V3_2::StreamBuffer;
-using ::android::hardware::camera::device::V3_2::MsgType;
-using ::android::hardware::camera::device::V3_2::ErrorMsg;
-using ::android::hardware::camera::device::V3_2::ErrorCode;
using ::android::hardware::camera::device::V1_0::CameraFacing;
-using ::android::hardware::camera::device::V1_0::NotifyCallbackMsg;
+using ::android::hardware::camera::device::V1_0::CameraFrameMetadata;
using ::android::hardware::camera::device::V1_0::CommandType;
using ::android::hardware::camera::device::V1_0::DataCallbackMsg;
-using ::android::hardware::camera::device::V1_0::CameraFrameMetadata;
-using ::android::hardware::camera::device::V1_0::ICameraDevicePreviewCallback;
using ::android::hardware::camera::device::V1_0::FrameCallbackFlag;
using ::android::hardware::camera::device::V1_0::HandleTimestampMessage;
-using ::android::hardware::camera::metadata::V3_4::CameraMetadataEnumAndroidSensorInfoColorFilterArrangement;
-using ::android::hardware::camera::metadata::V3_4::CameraMetadataTag;
+using ::android::hardware::camera::device::V1_0::ICameraDevicePreviewCallback;
+using ::android::hardware::camera::device::V1_0::NotifyCallbackMsg;
+using ::android::hardware::camera::device::V3_2::BufferCache;
+using ::android::hardware::camera::device::V3_2::BufferStatus;
+using ::android::hardware::camera::device::V3_2::CameraMetadata;
+using ::android::hardware::camera::device::V3_2::CaptureRequest;
+using ::android::hardware::camera::device::V3_2::CaptureResult;
+using ::android::hardware::camera::device::V3_2::ErrorCode;
+using ::android::hardware::camera::device::V3_2::ErrorMsg;
+using ::android::hardware::camera::device::V3_2::HalStreamConfiguration;
+using ::android::hardware::camera::device::V3_2::ICameraDevice;
+using ::android::hardware::camera::device::V3_2::ICameraDeviceSession;
+using ::android::hardware::camera::device::V3_2::MsgType;
+using ::android::hardware::camera::device::V3_2::NotifyMsg;
+using ::android::hardware::camera::device::V3_2::RequestTemplate;
+using ::android::hardware::camera::device::V3_2::StreamBuffer;
+using ::android::hardware::camera::device::V3_2::StreamConfiguration;
+using ::android::hardware::camera::device::V3_2::StreamConfigurationMode;
+using ::android::hardware::camera::device::V3_2::StreamRotation;
+using ::android::hardware::camera::device::V3_2::StreamType;
using ::android::hardware::camera::device::V3_4::PhysicalCameraMetadata;
-using ::android::hardware::MessageQueue;
-using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::camera::metadata::V3_4::
+ CameraMetadataEnumAndroidSensorInfoColorFilterArrangement;
+using ::android::hardware::camera::metadata::V3_4::CameraMetadataTag;
+using ::android::hardware::camera::provider::V2_4::ICameraProvider;
+using ::android::hardware::camera::provider::V2_4::ICameraProviderCallback;
+using ::android::hardware::camera::provider::V2_6::CameraIdAndStreamCombination;
+using ::android::hardware::graphics::common::V1_0::BufferUsage;
+using ::android::hardware::graphics::common::V1_0::Dataspace;
+using ::android::hardware::graphics::common::V1_0::PixelFormat;
using ::android::hidl::allocator::V1_0::IAllocator;
-using ::android::hidl::memory::V1_0::IMemory;
using ::android::hidl::memory::V1_0::IMapper;
+using ::android::hidl::memory::V1_0::IMemory;
using ResultMetadataQueue = MessageQueue<uint8_t, kSynchronizedReadWrite>;
using ::android::hidl::manager::V1_0::IServiceManager;
@@ -554,7 +556,12 @@
hidl_vec<hidl_string> getCameraDeviceNames(sp<ICameraProvider> provider);
- struct EmptyDeviceCb : public V3_5::ICameraDeviceCallback {
+ std::map<hidl_string, hidl_string> getCameraDeviceIdToNameMap(sp<ICameraProvider> provider);
+
+ hidl_vec<hidl_vec<hidl_string>> getConcurrentDeviceCombinations(
+ sp<::android::hardware::camera::provider::V2_6::ICameraProvider>&);
+
+ struct EmptyDeviceCb : public V3_5::ICameraDeviceCallback {
virtual Return<void> processCaptureResult(
const hidl_vec<CaptureResult>& /*results*/) override {
ALOGI("processCaptureResult callback");
@@ -591,8 +598,7 @@
ADD_FAILURE(); // Empty callback should not reach here
return Void();
}
-
- };
+ };
struct DeviceCb : public V3_5::ICameraDeviceCallback {
DeviceCb(CameraHidlTest *parent, int deviceVersion, const camera_metadata_t *staticMeta) :
@@ -808,6 +814,13 @@
static Status getAvailableOutputStreams(const camera_metadata_t *staticMeta,
std::vector<AvailableStream> &outputStreams,
const AvailableStream *threshold = nullptr);
+
+ static Status getMaxOutputSizeForFormat(const camera_metadata_t* staticMeta, PixelFormat format,
+ Size* size);
+
+ static Status getMandatoryConcurrentStreams(const camera_metadata_t* staticMeta,
+ std::vector<AvailableStream>* outputStreams);
+
static Status getJpegBufferSize(camera_metadata_t *staticMeta,
uint32_t* outBufSize);
static Status isConstrainedModeAvailable(camera_metadata_t *staticMeta);
@@ -1535,6 +1548,20 @@
return Void();
}
+std::map<hidl_string, hidl_string> CameraHidlTest::getCameraDeviceIdToNameMap(
+ sp<ICameraProvider> provider) {
+ hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(provider);
+ std::map<hidl_string, hidl_string> idToNameMap;
+ for (auto& name : cameraDeviceNames) {
+ std::string version, cameraId;
+ if (!matchDeviceName(name, mProviderType, &version, &cameraId)) {
+ ADD_FAILURE();
+ }
+ idToNameMap.insert(std::make_pair(hidl_string(cameraId), name));
+ }
+ return idToNameMap;
+}
+
hidl_vec<hidl_string> CameraHidlTest::getCameraDeviceNames(sp<ICameraProvider> provider) {
std::vector<std::string> cameraDeviceNames;
Return<void> ret;
@@ -1591,6 +1618,21 @@
return retList;
}
+hidl_vec<hidl_vec<hidl_string>> CameraHidlTest::getConcurrentDeviceCombinations(
+ sp<::android::hardware::camera::provider::V2_6::ICameraProvider>& provider2_6) {
+ hidl_vec<hidl_vec<hidl_string>> combinations;
+ Return<void> ret = provider2_6->getConcurrentStreamingCameraIds(
+ [&combinations](Status concurrentIdStatus,
+ const hidl_vec<hidl_vec<hidl_string>>& cameraDeviceIdCombinations) {
+ ASSERT_EQ(concurrentIdStatus, Status::OK);
+ combinations = cameraDeviceIdCombinations;
+ });
+ if (!ret.isOk()) {
+ ADD_FAILURE();
+ }
+ return combinations;
+}
+
// Test devices with first_api_level >= P does not advertise device@1.0
TEST_P(CameraHidlTest, noHal1AfterP) {
constexpr int32_t HAL1_PHASE_OUT_API_LEVEL = 28;
@@ -3078,6 +3120,157 @@
}
}
+// Verify that mandatory concurrent streams and outputs are supported.
+TEST_P(CameraHidlTest, configureConcurrentStreamsAvailableOutputs) {
+ struct CameraTestInfo {
+ camera_metadata_t* staticMeta = nullptr;
+ sp<ICameraDeviceSession> session;
+ sp<device::V3_3::ICameraDeviceSession> session3_3;
+ sp<device::V3_4::ICameraDeviceSession> session3_4;
+ sp<device::V3_5::ICameraDeviceSession> session3_5;
+ sp<device::V3_6::ICameraDeviceSession> session3_6;
+ sp<device::V3_2::ICameraDevice> cameraDevice;
+ sp<device::V3_5::ICameraDevice> cameraDevice3_5;
+ ::android::hardware::camera::device::V3_5::StreamConfiguration config3_5;
+ ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4;
+ ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2;
+ };
+ if (mProvider2_6 == nullptr) {
+ // This test is provider@2.6 specific
+ ALOGW("%s provider not 2_6, skipping", __func__);
+ return;
+ }
+
+ std::map<hidl_string, hidl_string> idToNameMap = getCameraDeviceIdToNameMap(mProvider2_6);
+ hidl_vec<hidl_vec<hidl_string>> concurrentDeviceCombinations =
+ getConcurrentDeviceCombinations(mProvider2_6);
+ std::vector<AvailableStream> outputStreams;
+ for (const auto& cameraDeviceIds : concurrentDeviceCombinations) {
+ std::vector<CameraIdAndStreamCombination> cameraIdsAndStreamCombinations;
+ std::vector<CameraTestInfo> cameraTestInfos;
+ size_t i = 0;
+ for (const auto& id : cameraDeviceIds) {
+ CameraTestInfo cti;
+ Return<void> ret;
+ auto it = idToNameMap.find(id);
+ ASSERT_TRUE(idToNameMap.end() != it);
+ hidl_string name = it->second;
+ int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+ if (deviceVersion == CAMERA_DEVICE_API_VERSION_1_0) {
+ continue;
+ } else if (deviceVersion <= 0) {
+ ALOGE("%s: Unsupported device version %d", __func__, deviceVersion);
+ ADD_FAILURE();
+ return;
+ }
+ openEmptyDeviceSession(name, mProvider2_6, &cti.session /*out*/,
+ &cti.staticMeta /*out*/, &cti.cameraDevice /*out*/);
+ castSession(cti.session, deviceVersion, &cti.session3_3, &cti.session3_4,
+ &cti.session3_5, &cti.session3_6);
+ castDevice(cti.cameraDevice, deviceVersion, &cti.cameraDevice3_5);
+
+ outputStreams.clear();
+ ASSERT_EQ(Status::OK, getMandatoryConcurrentStreams(cti.staticMeta, &outputStreams));
+ ASSERT_NE(0u, outputStreams.size());
+
+ uint32_t jpegBufferSize = 0;
+ ASSERT_EQ(Status::OK, getJpegBufferSize(cti.staticMeta, &jpegBufferSize));
+ ASSERT_NE(0u, jpegBufferSize);
+
+ int32_t streamId = 0;
+ ::android::hardware::hidl_vec<V3_2::Stream> streams3_2(outputStreams.size());
+ size_t j = 0;
+ for (const auto& it : outputStreams) {
+ V3_2::Stream stream3_2;
+ V3_2::DataspaceFlags dataspaceFlag = 0;
+ switch (static_cast<PixelFormat>(it.format)) {
+ case PixelFormat::BLOB:
+ dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::V0_JFIF);
+ break;
+ case PixelFormat::Y16:
+ dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::DEPTH);
+ break;
+ default:
+ dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::UNKNOWN);
+ }
+ stream3_2 = {streamId++,
+ StreamType::OUTPUT,
+ static_cast<uint32_t>(it.width),
+ static_cast<uint32_t>(it.height),
+ static_cast<PixelFormat>(it.format),
+ GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
+ dataspaceFlag,
+ StreamRotation::ROTATION_0};
+ streams3_2[j] = stream3_2;
+ j++;
+ }
+
+ // Add the created stream configs to cameraIdsAndStreamCombinations
+ createStreamConfiguration(streams3_2, StreamConfigurationMode::NORMAL_MODE,
+ &cti.config3_2, &cti.config3_4, &cti.config3_5,
+ jpegBufferSize);
+
+ cti.config3_5.streamConfigCounter = outputStreams.size();
+ CameraIdAndStreamCombination cameraIdAndStreamCombination;
+ cameraIdAndStreamCombination.cameraId = id;
+ cameraIdAndStreamCombination.streamConfiguration = cti.config3_4;
+ cameraIdsAndStreamCombinations.push_back(cameraIdAndStreamCombination);
+ i++;
+ cameraTestInfos.push_back(cti);
+ }
+ // Now verify that concurrent streams are supported
+ auto cb = [](Status s, bool supported) {
+ ASSERT_EQ(Status::OK, s);
+ ASSERT_EQ(supported, true);
+ };
+
+ auto ret = mProvider2_6->isConcurrentStreamCombinationSupported(
+ cameraIdsAndStreamCombinations, cb);
+
+ // Test the stream can actually be configured
+ for (const auto& cti : cameraTestInfos) {
+ if (cti.session3_5 != nullptr) {
+ bool expectStreamCombQuery = (isLogicalMultiCamera(cti.staticMeta) == Status::OK);
+ verifyStreamCombination(cti.cameraDevice3_5, cti.config3_4,
+ /*expectedStatus*/ true, expectStreamCombQuery);
+ ret = cti.session3_5->configureStreams_3_5(
+ cti.config3_5,
+ [&cti](Status s, device::V3_4::HalStreamConfiguration halConfig) {
+ ASSERT_EQ(Status::OK, s);
+ ASSERT_EQ(cti.config3_5.v3_4.streams.size(), halConfig.streams.size());
+ });
+ } else if (cti.session3_4 != nullptr) {
+ ret = cti.session3_4->configureStreams_3_4(
+ cti.config3_4,
+ [&cti](Status s, device::V3_4::HalStreamConfiguration halConfig) {
+ ASSERT_EQ(Status::OK, s);
+ ASSERT_EQ(cti.config3_4.streams.size(), halConfig.streams.size());
+ });
+ } else if (cti.session3_3 != nullptr) {
+ ret = cti.session3_3->configureStreams_3_3(
+ cti.config3_2,
+ [&cti](Status s, device::V3_3::HalStreamConfiguration halConfig) {
+ ASSERT_EQ(Status::OK, s);
+ ASSERT_EQ(cti.config3_2.streams.size(), halConfig.streams.size());
+ });
+ } else {
+ ret = cti.session->configureStreams(
+ cti.config3_2, [&cti](Status s, HalStreamConfiguration halConfig) {
+ ASSERT_EQ(Status::OK, s);
+ ASSERT_EQ(cti.config3_2.streams.size(), halConfig.streams.size());
+ });
+ }
+ ASSERT_TRUE(ret.isOk());
+ }
+
+ for (const auto& cti : cameraTestInfos) {
+ free_camera_metadata(cti.staticMeta);
+ ret = cti.session->close();
+ ASSERT_TRUE(ret.isOk());
+ }
+ }
+}
+
// Check for correct handling of invalid/incorrect configuration parameters.
TEST_P(CameraHidlTest, configureStreamsInvalidOutputs) {
hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
@@ -5158,6 +5351,65 @@
return Status::OK;
}
+static Size getMinSize(Size a, Size b) {
+ if (a.width * a.height < b.width * b.height) {
+ return a;
+ }
+ return b;
+}
+
+// TODO: Add more combinations
+Status CameraHidlTest::getMandatoryConcurrentStreams(const camera_metadata_t* staticMeta,
+ std::vector<AvailableStream>* outputStreams) {
+ if (nullptr == staticMeta) {
+ return Status::ILLEGAL_ARGUMENT;
+ }
+ Size yuvMaxSize(1280, 720);
+ Size jpegMaxSize(1920, 1440);
+ Size maxAvailableYuvSize;
+ Size maxAvailableJpegSize;
+ getMaxOutputSizeForFormat(staticMeta, PixelFormat::YCBCR_420_888, &maxAvailableYuvSize);
+ getMaxOutputSizeForFormat(staticMeta, PixelFormat::BLOB, &maxAvailableJpegSize);
+ Size yuvChosenSize = getMinSize(yuvMaxSize, maxAvailableYuvSize);
+ Size jpegChosenSize = getMinSize(jpegMaxSize, maxAvailableJpegSize);
+
+ AvailableStream yuvStream = {.width = yuvChosenSize.width,
+ .height = yuvChosenSize.height,
+ .format = static_cast<int32_t>(PixelFormat::YCBCR_420_888)};
+
+ AvailableStream jpegStream = {.width = jpegChosenSize.width,
+ .height = jpegChosenSize.height,
+ .format = static_cast<int32_t>(PixelFormat::BLOB)};
+ outputStreams->push_back(yuvStream);
+ outputStreams->push_back(jpegStream);
+
+ return Status::OK;
+}
+
+Status CameraHidlTest::getMaxOutputSizeForFormat(const camera_metadata_t* staticMeta,
+ PixelFormat format, Size* size) {
+ std::vector<AvailableStream> outputStreams;
+ if (size == nullptr || getAvailableOutputStreams(staticMeta, outputStreams) != Status::OK) {
+ return Status::ILLEGAL_ARGUMENT;
+ }
+ Size maxSize;
+ bool found = false;
+ for (auto& outputStream : outputStreams) {
+ if (static_cast<int32_t>(format) == outputStream.format &&
+ (outputStream.width * outputStream.height > maxSize.width * maxSize.height)) {
+ maxSize.width = outputStream.width;
+ maxSize.height = outputStream.height;
+ found = true;
+ }
+ }
+ if (!found) {
+ ALOGE("%s :chosen format %d not found", __FUNCTION__, static_cast<int32_t>(format));
+ return Status::ILLEGAL_ARGUMENT;
+ }
+ *size = maxSize;
+ return Status::OK;
+}
+
void CameraHidlTest::fillOutputStreams(camera_metadata_ro_entry_t* entry,
std::vector<AvailableStream>& outputStreams, const AvailableStream* threshold,
const int32_t availableConfigOutputTag) {
diff --git a/confirmationui/1.0/vts/functional/Android.bp b/confirmationui/1.0/vts/functional/Android.bp
index fd088cd..c8b522c 100644
--- a/confirmationui/1.0/vts/functional/Android.bp
+++ b/confirmationui/1.0/vts/functional/Android.bp
@@ -27,5 +27,5 @@
"libcn-cbor",
"android.hardware.confirmationui-support-lib",
],
- test_suites: ["general-tests"],
+ test_suites: ["general-tests", "vts-core"],
}
diff --git a/confirmationui/1.0/vts/functional/VtsHalConfirmationUIV1_0TargetTest.cpp b/confirmationui/1.0/vts/functional/VtsHalConfirmationUIV1_0TargetTest.cpp
index fb01ad0..d953ab0 100644
--- a/confirmationui/1.0/vts/functional/VtsHalConfirmationUIV1_0TargetTest.cpp
+++ b/confirmationui/1.0/vts/functional/VtsHalConfirmationUIV1_0TargetTest.cpp
@@ -26,8 +26,12 @@
#include <android/hardware/confirmationui/1.0/types.h>
#include <android/hardware/confirmationui/support/confirmationui_utils.h>
+#include <gtest/gtest.h>
+
#include <VtsHalHidlTargetCallbackBase.h>
-#include <VtsHalHidlTargetTestBase.h>
+
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
#include <openssl/hmac.h>
#include <openssl/sha.h>
@@ -199,43 +203,18 @@
}
};
-class ConfirmationUIHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
- public:
- // get the test environment singleton
- static ConfirmationUIHidlEnvironment* Instance() {
- static ConfirmationUIHidlEnvironment* instance = new ConfirmationUIHidlEnvironment;
- return instance;
- }
-
- void registerTestServices() override { registerTestService<IConfirmationUI>(); }
-
- private:
- ConfirmationUIHidlEnvironment(){};
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(ConfirmationUIHidlEnvironment);
-};
-
-class ConfirmationUIHidlTest : public ::testing::VtsHalHidlTargetTestBase {
- public:
- void TearDown() override { confirmator().abort(); }
-
- static void SetUpTestCase() {
- string service_name =
- ConfirmationUIHidlEnvironment::Instance()->getServiceName<IConfirmationUI>();
- confirmator_ = IConfirmationUI::getService(service_name);
+class ConfirmationUIHidlTest : public ::testing::TestWithParam<std::string> {
+ public:
+ void TearDown() override { confirmator_->abort(); }
+ void SetUp() override {
+ confirmator_ = IConfirmationUI::getService(GetParam());
ASSERT_NE(nullptr, confirmator_.get());
}
- static void TearDownTestCase() { confirmator_.clear(); }
-
- static IConfirmationUI& confirmator() { return *confirmator_; }
-
- private:
- static sp<IConfirmationUI> confirmator_;
+ protected:
+ sp<IConfirmationUI> confirmator_;
};
-sp<IConfirmationUI> ConfirmationUIHidlTest::confirmator_;
-
#define ASSERT_HAL_CALL(expected, call) \
{ \
auto result = call; \
@@ -250,17 +229,17 @@
typedef std::unique_ptr<cn_cbor, CnCborDeleter> CnCborPtr;
// Simulates the User taping Ok
-TEST_F(ConfirmationUIHidlTest, UserOkTest) {
+TEST_P(ConfirmationUIHidlTest, UserOkTest) {
static constexpr char test_prompt[] = "Me first, gimme gimme!";
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
hidl_string prompt_text(test_prompt);
hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_HAL_CALL(ResponseCode::OK,
- confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+ confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
- ASSERT_HAL_CALL(ResponseCode::OK, confirmator().deliverSecureInputEvent(
- makeTestToken(TestModeCommands::OK_EVENT)));
+ ASSERT_HAL_CALL(ResponseCode::OK, confirmator_->deliverSecureInputEvent(
+ makeTestToken(TestModeCommands::OK_EVENT)));
auto result = conf_cb->WaitForCallback();
ASSERT_EQ(ResponseCode::OK, result.args->error_);
@@ -294,40 +273,40 @@
}
// Initiates a confirmation prompt with a message that is too long
-TEST_F(ConfirmationUIHidlTest, MessageTooLongTest) {
+TEST_P(ConfirmationUIHidlTest, MessageTooLongTest) {
static constexpr uint8_t test_extra[static_cast<uint32_t>(MessageSize::MAX)] = {};
static constexpr char test_prompt[] = "D\'oh!";
sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
hidl_string prompt_text(test_prompt);
hidl_vec<uint8_t> extra(test_extra, test_extra + sizeof(test_extra));
ASSERT_HAL_CALL(ResponseCode::UIErrorMessageTooLong,
- confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+ confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
}
// If the message gets very long some HAL implementations might fail even before the message
// reaches the trusted app implementation. But the HAL must still diagnose the correct error.
-TEST_F(ConfirmationUIHidlTest, MessageWayTooLongTest) {
+TEST_P(ConfirmationUIHidlTest, MessageWayTooLongTest) {
static constexpr uint8_t test_extra[static_cast<uint32_t>(MessageSize::MAX) * 10] = {};
static constexpr char test_prompt[] = "D\'oh!";
sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
hidl_string prompt_text(test_prompt);
hidl_vec<uint8_t> extra(test_extra, test_extra + sizeof(test_extra));
ASSERT_HAL_CALL(ResponseCode::UIErrorMessageTooLong,
- confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+ confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
}
// Simulates the User tapping the Cancel
-TEST_F(ConfirmationUIHidlTest, UserCancelTest) {
+TEST_P(ConfirmationUIHidlTest, UserCancelTest) {
static constexpr char test_prompt[] = "Me first, gimme gimme!";
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
hidl_string prompt_text(test_prompt);
hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_HAL_CALL(ResponseCode::OK,
- confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+ confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
- ASSERT_HAL_CALL(ResponseCode::OK, confirmator().deliverSecureInputEvent(
- makeTestToken(TestModeCommands::CANCEL_EVENT)));
+ ASSERT_HAL_CALL(ResponseCode::OK, confirmator_->deliverSecureInputEvent(
+ makeTestToken(TestModeCommands::CANCEL_EVENT)));
auto result = conf_cb->WaitForCallback();
ASSERT_EQ(ResponseCode::Canceled, result.args->error_);
@@ -337,16 +316,16 @@
}
// Simulates the framework cancelling an ongoing prompt
-TEST_F(ConfirmationUIHidlTest, AbortTest) {
+TEST_P(ConfirmationUIHidlTest, AbortTest) {
static constexpr char test_prompt[] = "Me first, gimme gimme!";
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
hidl_string prompt_text(test_prompt);
hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_HAL_CALL(ResponseCode::OK,
- confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+ confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
- confirmator().abort();
+ confirmator_->abort();
auto result = conf_cb->WaitForCallback();
ASSERT_EQ(ResponseCode::Aborted, result.args->error_);
@@ -356,7 +335,7 @@
// Tests if the confirmation dialog can successfully render 100 'W' characters as required by
// the design guidelines.
-TEST_F(ConfirmationUIHidlTest, PortableMessageTest1) {
+TEST_P(ConfirmationUIHidlTest, PortableMessageTest1) {
static constexpr char test_prompt[] =
"WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW"
"WWWWWWWWWWWWWW";
@@ -365,9 +344,9 @@
hidl_string prompt_text(test_prompt);
hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_HAL_CALL(ResponseCode::OK,
- confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+ confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
- confirmator().abort();
+ confirmator_->abort();
auto result = conf_cb->WaitForCallback();
ASSERT_EQ(ResponseCode::Aborted, result.args->error_);
@@ -377,7 +356,7 @@
// Tests if the confirmation dialog can successfully render 100 'W' characters as required by
// the design guidelines in magnified mode.
-TEST_F(ConfirmationUIHidlTest, PortableMessageTest1Magnified) {
+TEST_P(ConfirmationUIHidlTest, PortableMessageTest1Magnified) {
static constexpr char test_prompt[] =
"WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW"
"WWWWWWWWWWWWWW";
@@ -386,10 +365,10 @@
hidl_string prompt_text(test_prompt);
hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_HAL_CALL(ResponseCode::OK,
- confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en",
+ confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en",
{UIOption::AccessibilityMagnified}));
- confirmator().abort();
+ confirmator_->abort();
auto result = conf_cb->WaitForCallback();
ASSERT_EQ(ResponseCode::Aborted, result.args->error_);
@@ -399,7 +378,7 @@
// Tests if the confirmation dialog can successfully render 8 groups of 12 'W' characters as
// required by the design guidelines.
-TEST_F(ConfirmationUIHidlTest, PortableMessageTest2) {
+TEST_P(ConfirmationUIHidlTest, PortableMessageTest2) {
static constexpr char test_prompt[] =
"WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW "
"WWWWWWWWWWWW WWWWWWWWWWWW";
@@ -408,9 +387,9 @@
hidl_string prompt_text(test_prompt);
hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_HAL_CALL(ResponseCode::OK,
- confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+ confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
- confirmator().abort();
+ confirmator_->abort();
auto result = conf_cb->WaitForCallback();
ASSERT_EQ(ResponseCode::Aborted, result.args->error_);
@@ -420,7 +399,7 @@
// Tests if the confirmation dialog can successfully render 8 groups of 12 'W' characters as
// required by the design guidelines in magnified mode.
-TEST_F(ConfirmationUIHidlTest, PortableMessageTest2Magnified) {
+TEST_P(ConfirmationUIHidlTest, PortableMessageTest2Magnified) {
static constexpr char test_prompt[] =
"WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW "
"WWWWWWWWWWWW WWWWWWWWWWWW";
@@ -429,10 +408,10 @@
hidl_string prompt_text(test_prompt);
hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_HAL_CALL(ResponseCode::OK,
- confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en",
+ confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en",
{UIOption::AccessibilityMagnified}));
- confirmator().abort();
+ confirmator_->abort();
auto result = conf_cb->WaitForCallback();
ASSERT_EQ(ResponseCode::Aborted, result.args->error_);
@@ -442,19 +421,19 @@
// Passing malformed UTF-8 to the confirmation UI
// This test passes a string that ends in the middle of a multibyte character
-TEST_F(ConfirmationUIHidlTest, MalformedUTF8Test1) {
+TEST_P(ConfirmationUIHidlTest, MalformedUTF8Test1) {
static constexpr char test_prompt[] = {char(0xc0), 0};
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
hidl_string prompt_text(test_prompt);
hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_HAL_CALL(ResponseCode::UIErrorMalformedUTF8Encoding,
- confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+ confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
}
// Passing malformed UTF-8 to the confirmation UI
// This test passes a string with a 5-byte character.
-TEST_F(ConfirmationUIHidlTest, MalformedUTF8Test2) {
+TEST_P(ConfirmationUIHidlTest, MalformedUTF8Test2) {
static constexpr char test_prompt[] = {char(0xf8), char(0x82), char(0x82),
char(0x82), char(0x82), 0};
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
@@ -462,19 +441,19 @@
hidl_string prompt_text(test_prompt);
hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_HAL_CALL(ResponseCode::UIErrorMalformedUTF8Encoding,
- confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+ confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
}
// Passing malformed UTF-8 to the confirmation UI
// This test passes a string with a 2-byte character followed by a stray non UTF-8 character.
-TEST_F(ConfirmationUIHidlTest, MalformedUTF8Test3) {
+TEST_P(ConfirmationUIHidlTest, MalformedUTF8Test3) {
static constexpr char test_prompt[] = {char(0xc0), char(0x82), char(0x83), 0};
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
hidl_string prompt_text(test_prompt);
hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_HAL_CALL(ResponseCode::UIErrorMalformedUTF8Encoding,
- confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+ confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
}
// Test the implementation of HMAC SHA 256 against a golden blob.
@@ -494,16 +473,13 @@
ASSERT_EQ(expected, result.value());
}
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, ConfirmationUIHidlTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(IConfirmationUI::descriptor)),
+ android::hardware::PrintInstanceNameToString);
+
} // namespace test
} // namespace V1_0
} // namespace confirmationui
} // namespace hardware
} // namespace android
-
-int main(int argc, char** argv) {
- ::testing::InitGoogleTest(&argc, argv);
- std::vector<std::string> positional_args;
- int status = RUN_ALL_TESTS();
- ALOGI("Test result = %d", status);
- return status;
-}
diff --git a/contexthub/1.0/default/android.hardware.contexthub@1.0-service.rc b/contexthub/1.0/default/android.hardware.contexthub@1.0-service.rc
index b659be8..fc2893f 100644
--- a/contexthub/1.0/default/android.hardware.contexthub@1.0-service.rc
+++ b/contexthub/1.0/default/android.hardware.contexthub@1.0-service.rc
@@ -1,5 +1,5 @@
service vendor.contexthub-hal-1-0 /vendor/bin/hw/android.hardware.contexthub@1.0-service
interface android.hardware.contexthub@1.0::IContexthub default
class hal
- user system
- group system
+ user context_hub
+ group context_hub
diff --git a/contexthub/1.1/default/android.hardware.contexthub@1.1-service.rc b/contexthub/1.1/default/android.hardware.contexthub@1.1-service.rc
index 9db00f9..b00b1bd 100644
--- a/contexthub/1.1/default/android.hardware.contexthub@1.1-service.rc
+++ b/contexthub/1.1/default/android.hardware.contexthub@1.1-service.rc
@@ -2,5 +2,5 @@
interface android.hardware.contexthub@1.0::IContexthub default
interface android.hardware.contexthub@1.1::IContexthub default
class hal
- user system
- group system
+ user context_hub
+ group context_hub
diff --git a/drm/1.3/vts/functional/Android.bp b/drm/1.3/vts/functional/Android.bp
index 4be1575..ac1f912 100644
--- a/drm/1.3/vts/functional/Android.bp
+++ b/drm/1.3/vts/functional/Android.bp
@@ -30,12 +30,12 @@
"android.hardware.drm@1.3",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
+ "libcrypto",
"libhidlmemory",
"libnativehelper",
],
static_libs: [
"android.hardware.drm@1.0-helper",
- "libcrypto_static",
"libdrmvtshelper",
],
export_include_dirs: [
@@ -63,12 +63,12 @@
"android.hardware.drm@1.3",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
+ "libcrypto",
"libhidlmemory",
"libnativehelper",
],
static_libs: [
"android.hardware.drm@1.0-helper",
- "libcrypto_static",
"libdrmvtshelper",
],
test_suites: [
diff --git a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
index 8c9393b..83a8d94 100644
--- a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
@@ -626,21 +626,28 @@
ErrorStatus result;
hidl_handle syncFenceHandle;
sp<IFencedExecutionCallback> fencedCallback;
- Return<void> ret = preparedModel->executeFenced(
- request, {}, testConfig.measureTiming, {}, loopTimeoutDuration, {},
- [&result, &syncFenceHandle, &fencedCallback](
- ErrorStatus error, const hidl_handle& handle,
- const sp<IFencedExecutionCallback>& callback) {
- result = error;
- syncFenceHandle = handle;
- fencedCallback = callback;
- });
+ auto callbackFunc = [&result, &syncFenceHandle, &fencedCallback](
+ ErrorStatus error, const hidl_handle& handle,
+ const sp<IFencedExecutionCallback>& callback) {
+ result = error;
+ syncFenceHandle = handle;
+ fencedCallback = callback;
+ };
+ Return<void> ret =
+ preparedModel->executeFenced(request, {}, testConfig.measureTiming, {},
+ loopTimeoutDuration, {}, callbackFunc);
ASSERT_TRUE(ret.isOk());
if (result != ErrorStatus::NONE) {
ASSERT_EQ(syncFenceHandle.getNativeHandle(), nullptr);
ASSERT_EQ(fencedCallback, nullptr);
- executionStatus = ErrorStatus::GENERAL_FAILURE;
+ executionStatus = result;
} else if (syncFenceHandle.getNativeHandle()) {
+ // If a sync fence is returned, try start another run waiting for the sync fence.
+ ret = preparedModel->executeFenced(request, {syncFenceHandle},
+ testConfig.measureTiming, {},
+ loopTimeoutDuration, {}, callbackFunc);
+ ASSERT_TRUE(ret.isOk());
+ ASSERT_EQ(result, ErrorStatus::NONE);
waitForSyncFence(syncFenceHandle.getNativeHandle()->data[0]);
}
if (result == ErrorStatus::NONE) {
@@ -656,9 +663,7 @@
}
}
- // The driver is allowed to reject executeFenced, and if they do, we should skip.
- if ((testConfig.outputType != OutputType::FULLY_SPECIFIED ||
- testConfig.executor == Executor::FENCED) &&
+ if (testConfig.outputType != OutputType::FULLY_SPECIFIED &&
executionStatus == ErrorStatus::GENERAL_FAILURE) {
if (skipped != nullptr) {
*skipped = true;
@@ -691,12 +696,22 @@
outputShapes.size() == testModel.main.outputIndexes.size());
break;
case OutputType::UNSPECIFIED:
+ if (testConfig.executor == Executor::FENCED) {
+ // For Executor::FENCED, the output shape must be fully specified.
+ ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionStatus);
+ return;
+ }
// If the model output operands are not fully specified, outputShapes must have
// the same number of elements as the number of outputs.
ASSERT_EQ(ErrorStatus::NONE, executionStatus);
ASSERT_EQ(outputShapes.size(), testModel.main.outputIndexes.size());
break;
case OutputType::INSUFFICIENT:
+ if (testConfig.executor == Executor::FENCED) {
+ // For Executor::FENCED, the output shape must be fully specified.
+ ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionStatus);
+ return;
+ }
ASSERT_EQ(ErrorStatus::OUTPUT_INSUFFICIENT_SIZE, executionStatus);
ASSERT_EQ(outputShapes.size(), testModel.main.outputIndexes.size());
ASSERT_FALSE(outputShapes[0].isSufficient);
@@ -739,12 +754,12 @@
case TestKind::DYNAMIC_SHAPE: {
outputTypesList = {OutputType::UNSPECIFIED, OutputType::INSUFFICIENT};
measureTimingList = {MeasureTiming::NO, MeasureTiming::YES};
- executorList = {Executor::ASYNC, Executor::SYNC, Executor::BURST};
+ executorList = {Executor::ASYNC, Executor::SYNC, Executor::BURST, Executor::FENCED};
} break;
case TestKind::MEMORY_DOMAIN: {
outputTypesList = {OutputType::FULLY_SPECIFIED};
measureTimingList = {MeasureTiming::NO};
- executorList = {Executor::ASYNC, Executor::SYNC};
+ executorList = {Executor::ASYNC, Executor::SYNC, Executor::FENCED};
memoryType = MemoryType::DEVICE;
} break;
case TestKind::FENCED_COMPUTE: {
@@ -921,8 +936,13 @@
INSTANTIATE_GENERATED_TEST(MemoryDomainTest,
[](const TestModel& testModel) { return !testModel.expectFailure; });
-INSTANTIATE_GENERATED_TEST(FencedComputeTest,
- [](const TestModel& testModel) { return !testModel.expectFailure; });
+INSTANTIATE_GENERATED_TEST(FencedComputeTest, [](const TestModel& testModel) {
+ return !testModel.expectFailure &&
+ std::all_of(testModel.main.outputIndexes.begin(), testModel.main.outputIndexes.end(),
+ [&testModel](uint32_t index) {
+ return testModel.main.operands[index].data.size() > 0;
+ });
+});
INSTANTIATE_GENERATED_TEST(QuantizationCouplingTest, [](const TestModel& testModel) {
return testModel.hasQuant8CoupledOperands() && testModel.main.operations.size() == 1;
diff --git a/sensors/1.0/default/android.hardware.sensors@1.0-service.rc b/sensors/1.0/default/android.hardware.sensors@1.0-service.rc
index b41730b..1af6d0b 100644
--- a/sensors/1.0/default/android.hardware.sensors@1.0-service.rc
+++ b/sensors/1.0/default/android.hardware.sensors@1.0-service.rc
@@ -2,6 +2,6 @@
interface android.hardware.sensors@1.0::ISensors default
class hal
user system
- group system wakelock uhid
+ group system wakelock uhid context_hub
capabilities BLOCK_SUSPEND
rlimit rtprio 10 10
diff --git a/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.cpp b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.cpp
index 1e5e886..aca6961 100644
--- a/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.cpp
+++ b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.cpp
@@ -25,6 +25,13 @@
using ::android::hardware::sensors::V1_0::Result;
using ::android::hardware::sensors::V1_0::SensorInfo;
+void SensorsHidlEnvironmentV1_0::HidlTearDown() {
+ mStopThread = true;
+ if (mPollThread.joinable()) {
+ mPollThread.detach();
+ }
+}
+
bool SensorsHidlEnvironmentV1_0::resetHal() {
// wait upto 100ms * 10 = 1s for hidl service.
constexpr auto RETRY_DELAY = std::chrono::milliseconds(100);
@@ -103,18 +110,23 @@
ALOGD("polling thread start");
while (!stop) {
- env->sensors->poll(
- 64, [&](auto result, const auto& events, const auto& dynamicSensorsAdded) {
- if (result != Result::OK ||
- (events.size() == 0 && dynamicSensorsAdded.size() == 0) || stop) {
- stop = true;
- return;
- }
+ if (!env->sensors
+ ->poll(64,
+ [&](auto result, const auto& events, const auto& dynamicSensorsAdded) {
+ if (result != Result::OK ||
+ (events.size() == 0 && dynamicSensorsAdded.size() == 0) ||
+ stop) {
+ stop = true;
+ return;
+ }
- for (const auto& e : events) {
- env->addEvent(e);
- }
- });
+ for (const auto& e : events) {
+ env->addEvent(e);
+ }
+ })
+ .isOk()) {
+ break;
+ }
}
ALOGD("polling thread end");
}
\ No newline at end of file
diff --git a/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h
index 485ed1e..168777d 100644
--- a/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h
+++ b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h
@@ -32,6 +32,8 @@
class SensorsHidlEnvironmentV1_0
: public SensorsHidlEnvironmentBase<::android::hardware::sensors::V1_0::Event> {
public:
+ void HidlTearDown() override;
+
using Event = ::android::hardware::sensors::V1_0::Event;
SensorsHidlEnvironmentV1_0(const std::string& service_name)
: SensorsHidlEnvironmentBase(service_name) {}
diff --git a/sensors/2.0/multihal/Android.bp b/sensors/2.0/multihal/Android.bp
index 24c475c..7213b44 100644
--- a/sensors/2.0/multihal/Android.bp
+++ b/sensors/2.0/multihal/Android.bp
@@ -13,14 +13,21 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-cc_defaults {
- name: "android.hardware.sensors@2.0-multihal-defaults",
- header_libs: [
- "android.hardware.sensors@2.0-multihal.header",
+cc_binary {
+ name: "android.hardware.sensors@2.0-service.multihal",
+ defaults: [
+ "hidl_defaults",
],
+ vendor: true,
+ relative_install_path: "hw",
+ srcs: [
+ "service.cpp",
+ ],
+ init_rc: ["android.hardware.sensors@2.0-service-multihal.rc"],
+ vintf_fragments: ["android.hardware.sensors@2.0-multihal.xml"],
shared_libs: [
- "android.hardware.sensors@1.0",
"android.hardware.sensors@2.0",
+ "android.hardware.sensors@2.0-ScopedWakelock",
"libbase",
"libcutils",
"libfmq",
@@ -29,66 +36,5 @@
"libpower",
"libutils",
],
- cflags: ["-DLOG_TAG=\"SensorsMultiHal\""],
-}
-
-cc_binary {
- name: "android.hardware.sensors@2.0-service.multihal",
- defaults: [
- "hidl_defaults",
- "android.hardware.sensors@2.0-multihal-defaults",
- ],
- vendor: true,
- relative_install_path: "hw",
- srcs: [
- "service.cpp",
- "HalProxy.cpp",
- ],
- init_rc: ["android.hardware.sensors@2.0-service-multihal.rc"],
- vintf_fragments: ["android.hardware.sensors@2.0-multihal.xml"],
- shared_libs: ["android.hardware.sensors@2.0-ScopedWakelock"],
-}
-
-cc_library_headers {
- name: "android.hardware.sensors@2.0-multihal.header",
- vendor_available: true,
- export_include_dirs: ["include"],
-}
-
-cc_library_shared {
- name: "android.hardware.sensors@2.0-ScopedWakelock",
- defaults: [
- "hidl_defaults",
- "android.hardware.sensors@2.0-multihal-defaults",
- ],
- srcs: [
- "ScopedWakelock.cpp",
- ],
- vendor_available: true,
- export_header_lib_headers: [
- "android.hardware.sensors@2.0-multihal.header",
- ],
-}
-
-// The below targets should only be used for testing.
-cc_test_library {
- name: "android.hardware.sensors@2.0-HalProxy",
- defaults: [
- "hidl_defaults",
- "android.hardware.sensors@2.0-multihal-defaults",
- ],
- vendor_available: true,
- srcs: [
- "HalProxy.cpp",
- ],
- export_header_lib_headers: [
- "android.hardware.sensors@2.0-multihal.header",
- ],
- export_shared_lib_headers: [
- "android.hardware.sensors@2.0-ScopedWakelock",
- ],
- shared_libs: [
- "libutils",
- "android.hardware.sensors@2.0-ScopedWakelock",
- ],
+ static_libs: ["android.hardware.sensors@2.X-multihal"],
}
diff --git a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
index 8895350..a0d436f 100644
--- a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
+++ b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
@@ -16,6 +16,261 @@
#include "VtsHalSensorsV2_XTargetTest.h"
+// Test if sensor hal can do UI speed accelerometer streaming properly
+TEST_P(SensorsHidlTest, AccelerometerStreamingOperationSlow) {
+ testStreamingOperation(SensorTypeVersion::ACCELEROMETER, std::chrono::milliseconds(200),
+ std::chrono::seconds(5), mAccelNormChecker);
+}
+
+// Test if sensor hal can do normal speed accelerometer streaming properly
+TEST_P(SensorsHidlTest, AccelerometerStreamingOperationNormal) {
+ testStreamingOperation(SensorTypeVersion::ACCELEROMETER, std::chrono::milliseconds(20),
+ std::chrono::seconds(5), mAccelNormChecker);
+}
+
+// Test if sensor hal can do game speed accelerometer streaming properly
+TEST_P(SensorsHidlTest, AccelerometerStreamingOperationFast) {
+ testStreamingOperation(SensorTypeVersion::ACCELEROMETER, std::chrono::milliseconds(5),
+ std::chrono::seconds(5), mAccelNormChecker);
+}
+
+// Test if sensor hal can do UI speed gyroscope streaming properly
+TEST_P(SensorsHidlTest, GyroscopeStreamingOperationSlow) {
+ testStreamingOperation(SensorTypeVersion::GYROSCOPE, std::chrono::milliseconds(200),
+ std::chrono::seconds(5), mGyroNormChecker);
+}
+
+// Test if sensor hal can do normal speed gyroscope streaming properly
+TEST_P(SensorsHidlTest, GyroscopeStreamingOperationNormal) {
+ testStreamingOperation(SensorTypeVersion::GYROSCOPE, std::chrono::milliseconds(20),
+ std::chrono::seconds(5), mGyroNormChecker);
+}
+
+// Test if sensor hal can do game speed gyroscope streaming properly
+TEST_P(SensorsHidlTest, GyroscopeStreamingOperationFast) {
+ testStreamingOperation(SensorTypeVersion::GYROSCOPE, std::chrono::milliseconds(5),
+ std::chrono::seconds(5), mGyroNormChecker);
+}
+
+// Test if sensor hal can do UI speed magnetometer streaming properly
+TEST_P(SensorsHidlTest, MagnetometerStreamingOperationSlow) {
+ testStreamingOperation(SensorTypeVersion::MAGNETIC_FIELD, std::chrono::milliseconds(200),
+ std::chrono::seconds(5), NullChecker<EventType>());
+}
+
+// Test if sensor hal can do normal speed magnetometer streaming properly
+TEST_P(SensorsHidlTest, MagnetometerStreamingOperationNormal) {
+ testStreamingOperation(SensorTypeVersion::MAGNETIC_FIELD, std::chrono::milliseconds(20),
+ std::chrono::seconds(5), NullChecker<EventType>());
+}
+
+// Test if sensor hal can do game speed magnetometer streaming properly
+TEST_P(SensorsHidlTest, MagnetometerStreamingOperationFast) {
+ testStreamingOperation(SensorTypeVersion::MAGNETIC_FIELD, std::chrono::milliseconds(5),
+ std::chrono::seconds(5), NullChecker<EventType>());
+}
+
+// Test if sensor hal can do accelerometer sampling rate switch properly when sensor is active
+TEST_P(SensorsHidlTest, AccelerometerSamplingPeriodHotSwitchOperation) {
+ testSamplingRateHotSwitchOperation(SensorTypeVersion::ACCELEROMETER);
+ testSamplingRateHotSwitchOperation(SensorTypeVersion::ACCELEROMETER, false /*fastToSlow*/);
+}
+
+// Test if sensor hal can do gyroscope sampling rate switch properly when sensor is active
+TEST_P(SensorsHidlTest, GyroscopeSamplingPeriodHotSwitchOperation) {
+ testSamplingRateHotSwitchOperation(SensorTypeVersion::GYROSCOPE);
+ testSamplingRateHotSwitchOperation(SensorTypeVersion::GYROSCOPE, false /*fastToSlow*/);
+}
+
+// Test if sensor hal can do magnetometer sampling rate switch properly when sensor is active
+TEST_P(SensorsHidlTest, MagnetometerSamplingPeriodHotSwitchOperation) {
+ testSamplingRateHotSwitchOperation(SensorTypeVersion::MAGNETIC_FIELD);
+ testSamplingRateHotSwitchOperation(SensorTypeVersion::MAGNETIC_FIELD, false /*fastToSlow*/);
+}
+
+// Test if sensor hal can do accelerometer batching properly
+TEST_P(SensorsHidlTest, AccelerometerBatchingOperation) {
+ testBatchingOperation(SensorTypeVersion::ACCELEROMETER);
+}
+
+// Test if sensor hal can do gyroscope batching properly
+TEST_P(SensorsHidlTest, GyroscopeBatchingOperation) {
+ testBatchingOperation(SensorTypeVersion::GYROSCOPE);
+}
+
+// Test if sensor hal can do magnetometer batching properly
+TEST_P(SensorsHidlTest, MagnetometerBatchingOperation) {
+ testBatchingOperation(SensorTypeVersion::MAGNETIC_FIELD);
+}
+
+// Test sensor event direct report with ashmem for accel sensor at normal rate
+TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationNormal) {
+ testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::ASHMEM,
+ RateLevel::NORMAL, mAccelNormChecker);
+}
+
+// Test sensor event direct report with ashmem for accel sensor at fast rate
+TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationFast) {
+ testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::ASHMEM,
+ RateLevel::FAST, mAccelNormChecker);
+}
+
+// Test sensor event direct report with ashmem for accel sensor at very fast rate
+TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationVeryFast) {
+ testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::ASHMEM,
+ RateLevel::VERY_FAST, mAccelNormChecker);
+}
+
+// Test sensor event direct report with ashmem for gyro sensor at normal rate
+TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationNormal) {
+ testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::ASHMEM,
+ RateLevel::NORMAL, mGyroNormChecker);
+}
+
+// Test sensor event direct report with ashmem for gyro sensor at fast rate
+TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationFast) {
+ testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::FAST,
+ mGyroNormChecker);
+}
+
+// Test sensor event direct report with ashmem for gyro sensor at very fast rate
+TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationVeryFast) {
+ testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::ASHMEM,
+ RateLevel::VERY_FAST, mGyroNormChecker);
+}
+
+// Test sensor event direct report with ashmem for mag sensor at normal rate
+TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationNormal) {
+ testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::ASHMEM,
+ RateLevel::NORMAL, NullChecker<EventType>());
+}
+
+// Test sensor event direct report with ashmem for mag sensor at fast rate
+TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationFast) {
+ testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::ASHMEM,
+ RateLevel::FAST, NullChecker<EventType>());
+}
+
+// Test sensor event direct report with ashmem for mag sensor at very fast rate
+TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationVeryFast) {
+ testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::ASHMEM,
+ RateLevel::VERY_FAST, NullChecker<EventType>());
+}
+
+// Test sensor event direct report with gralloc for accel sensor at normal rate
+TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationNormal) {
+ testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::GRALLOC,
+ RateLevel::NORMAL, mAccelNormChecker);
+}
+
+// Test sensor event direct report with gralloc for accel sensor at fast rate
+TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationFast) {
+ testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::GRALLOC,
+ RateLevel::FAST, mAccelNormChecker);
+}
+
+// Test sensor event direct report with gralloc for accel sensor at very fast rate
+TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationVeryFast) {
+ testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::GRALLOC,
+ RateLevel::VERY_FAST, mAccelNormChecker);
+}
+
+// Test sensor event direct report with gralloc for gyro sensor at normal rate
+TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationNormal) {
+ testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::GRALLOC,
+ RateLevel::NORMAL, mGyroNormChecker);
+}
+
+// Test sensor event direct report with gralloc for gyro sensor at fast rate
+TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationFast) {
+ testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::FAST,
+ mGyroNormChecker);
+}
+
+// Test sensor event direct report with gralloc for gyro sensor at very fast rate
+TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationVeryFast) {
+ testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::GRALLOC,
+ RateLevel::VERY_FAST, mGyroNormChecker);
+}
+
+// Test sensor event direct report with gralloc for mag sensor at normal rate
+TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationNormal) {
+ testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::GRALLOC,
+ RateLevel::NORMAL, NullChecker<EventType>());
+}
+
+// Test sensor event direct report with gralloc for mag sensor at fast rate
+TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationFast) {
+ testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::GRALLOC,
+ RateLevel::FAST, NullChecker<EventType>());
+}
+
+// Test sensor event direct report with gralloc for mag sensor at very fast rate
+TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationVeryFast) {
+ testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::GRALLOC,
+ RateLevel::VERY_FAST, NullChecker<EventType>());
+}
+
+TEST_P(SensorsHidlTest, ConfigureDirectChannelWithInvalidHandle) {
+ SensorInfoType sensor;
+ SharedMemType memType;
+ RateLevel rate;
+ if (!getDirectChannelSensor(&sensor, &memType, &rate)) {
+ return;
+ }
+
+ // Verify that an invalid channel handle produces a BAD_VALUE result
+ configDirectReport(sensor.sensorHandle, -1, rate, [](Result result, int32_t /* reportToken */) {
+ ASSERT_EQ(result, Result::BAD_VALUE);
+ });
+}
+
+TEST_P(SensorsHidlTest, CleanupDirectConnectionOnInitialize) {
+ constexpr size_t kNumEvents = 1;
+ constexpr size_t kMemSize = kNumEvents * kEventSize;
+
+ SensorInfoType sensor;
+ SharedMemType memType;
+ RateLevel rate;
+
+ if (!getDirectChannelSensor(&sensor, &memType, &rate)) {
+ return;
+ }
+
+ std::shared_ptr<SensorsTestSharedMemory<SensorTypeVersion, EventType>> mem(
+ SensorsTestSharedMemory<SensorTypeVersion, EventType>::create(memType, kMemSize));
+ ASSERT_NE(mem, nullptr);
+
+ int32_t directChannelHandle = 0;
+ registerDirectChannel(mem->getSharedMemInfo(), [&](Result result, int32_t channelHandle) {
+ ASSERT_EQ(result, Result::OK);
+ directChannelHandle = channelHandle;
+ });
+
+ // Configure the channel and expect success
+ configDirectReport(
+ sensor.sensorHandle, directChannelHandle, rate,
+ [](Result result, int32_t /* reportToken */) { ASSERT_EQ(result, Result::OK); });
+
+ // Call initialize() via the environment setup to cause the HAL to re-initialize
+ // Clear the active direct connections so they are not stopped during TearDown
+ auto handles = mDirectChannelHandles;
+ mDirectChannelHandles.clear();
+ getEnvironment()->HidlTearDown();
+ getEnvironment()->HidlSetUp();
+ if (HasFatalFailure()) {
+ return; // Exit early if resetting the environment failed
+ }
+
+ // Attempt to configure the direct channel and expect it to fail
+ configDirectReport(
+ sensor.sensorHandle, directChannelHandle, rate,
+ [](Result result, int32_t /* reportToken */) { ASSERT_EQ(result, Result::BAD_VALUE); });
+
+ // Restore original handles, though they should already be deactivated
+ mDirectChannelHandles = handles;
+}
+
TEST_P(SensorsHidlTest, SensorListDoesntContainInvalidType) {
getSensors()->getSensorsList([&](const auto& list) {
const size_t count = list.size();
@@ -26,6 +281,21 @@
});
}
+TEST_P(SensorsHidlTest, FlushNonexistentSensor) {
+ SensorInfoType sensor;
+ std::vector<SensorInfoType> sensors = getNonOneShotSensors();
+ if (sensors.size() == 0) {
+ sensors = getOneShotSensors();
+ if (sensors.size() == 0) {
+ return;
+ }
+ }
+ sensor = sensors.front();
+ sensor.sensorHandle = getInvalidSensorHandle();
+ runSingleFlushTest(std::vector<SensorInfoType>{sensor}, false /* activateSensor */,
+ 0 /* expectedFlushCount */, Result::BAD_VALUE);
+}
+
INSTANTIATE_TEST_SUITE_P(PerInstance, SensorsHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(
android::hardware::sensors::V2_0::ISensors::descriptor)),
diff --git a/sensors/common/default/2.X/multihal/Android.bp b/sensors/common/default/2.X/multihal/Android.bp
new file mode 100644
index 0000000..2b4b3bf
--- /dev/null
+++ b/sensors/common/default/2.X/multihal/Android.bp
@@ -0,0 +1,84 @@
+//
+// 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_defaults {
+ name: "android.hardware.sensors@2.X-multihal-defaults",
+ header_libs: [
+ "android.hardware.sensors@2.0-multihal.header",
+ ],
+ shared_libs: [
+ "android.hardware.sensors@1.0",
+ "android.hardware.sensors@2.0",
+ "libbase",
+ "libcutils",
+ "libfmq",
+ "libhidlbase",
+ "liblog",
+ "libpower",
+ "libutils",
+ ],
+ cflags: ["-DLOG_TAG=\"SensorsMultiHal\""],
+}
+
+cc_library_headers {
+ name: "android.hardware.sensors@2.0-multihal.header",
+ vendor_available: true,
+ export_include_dirs: ["include"],
+}
+
+cc_library_static {
+ name: "android.hardware.sensors@2.X-multihal",
+ defaults: [
+ "hidl_defaults",
+ "android.hardware.sensors@2.X-multihal-defaults",
+ ],
+ srcs: [
+ "HalProxy.cpp",
+ ],
+ vendor_available: true,
+ export_header_lib_headers: [
+ "android.hardware.sensors@2.0-multihal.header",
+ ],
+}
+
+cc_library_shared {
+ name: "android.hardware.sensors@2.0-ScopedWakelock",
+ defaults: [
+ "hidl_defaults",
+ "android.hardware.sensors@2.X-multihal-defaults",
+ ],
+ srcs: [
+ "ScopedWakelock.cpp",
+ ],
+ vendor_available: true,
+ export_header_lib_headers: [
+ "android.hardware.sensors@2.0-multihal.header",
+ ],
+}
+
+cc_test_library {
+ name: "android.hardware.sensors@2.0-ScopedWakelock.testlib",
+ defaults: [
+ "hidl_defaults",
+ "android.hardware.sensors@2.X-multihal-defaults",
+ ],
+ srcs: [
+ "ScopedWakelock.cpp",
+ ],
+ vendor_available: true,
+ export_header_lib_headers: [
+ "android.hardware.sensors@2.0-multihal.header",
+ ],
+}
diff --git a/sensors/2.0/multihal/HalProxy.cpp b/sensors/common/default/2.X/multihal/HalProxy.cpp
similarity index 100%
rename from sensors/2.0/multihal/HalProxy.cpp
rename to sensors/common/default/2.X/multihal/HalProxy.cpp
diff --git a/sensors/2.0/multihal/ScopedWakelock.cpp b/sensors/common/default/2.X/multihal/ScopedWakelock.cpp
similarity index 100%
rename from sensors/2.0/multihal/ScopedWakelock.cpp
rename to sensors/common/default/2.X/multihal/ScopedWakelock.cpp
diff --git a/sensors/2.0/multihal/include/HalProxy.h b/sensors/common/default/2.X/multihal/include/HalProxy.h
similarity index 100%
rename from sensors/2.0/multihal/include/HalProxy.h
rename to sensors/common/default/2.X/multihal/include/HalProxy.h
diff --git a/sensors/2.0/multihal/include/ScopedWakelock.h b/sensors/common/default/2.X/multihal/include/ScopedWakelock.h
similarity index 100%
rename from sensors/2.0/multihal/include/ScopedWakelock.h
rename to sensors/common/default/2.X/multihal/include/ScopedWakelock.h
diff --git a/sensors/2.0/multihal/include/SubHal.h b/sensors/common/default/2.X/multihal/include/SubHal.h
similarity index 100%
rename from sensors/2.0/multihal/include/SubHal.h
rename to sensors/common/default/2.X/multihal/include/SubHal.h
diff --git a/sensors/2.0/multihal/tests/Android.bp b/sensors/common/default/2.X/multihal/tests/Android.bp
similarity index 74%
rename from sensors/2.0/multihal/tests/Android.bp
rename to sensors/common/default/2.X/multihal/tests/Android.bp
index a9feaf7..afb63cc 100644
--- a/sensors/2.0/multihal/tests/Android.bp
+++ b/sensors/common/default/2.X/multihal/tests/Android.bp
@@ -14,7 +14,7 @@
// limitations under the License.
cc_defaults {
- name: "android.hardware.sensors@2.0-fakesubhal-defaults",
+ name: "android.hardware.sensors@2.X-fakesubhal-defaults",
srcs: [
"fake_subhal/*.cpp",
],
@@ -35,7 +35,7 @@
"libutils",
],
static_libs: [
- "android.hardware.sensors@2.0-HalProxy",
+ "android.hardware.sensors@2.X-multihal",
],
cflags: [
"-DLOG_TAG=\"FakeSubHal\"",
@@ -43,9 +43,9 @@
}
cc_library {
- name: "android.hardware.sensors@2.0-fakesubhal-config1",
+ name: "android.hardware.sensors@2.X-fakesubhal-config1",
vendor: true,
- defaults: ["android.hardware.sensors@2.0-fakesubhal-defaults"],
+ defaults: ["android.hardware.sensors@2.X-fakesubhal-defaults"],
cflags: [
"-DSUPPORT_CONTINUOUS_SENSORS",
"-DSUB_HAL_NAME=\"FakeSubHal-Continuous\"",
@@ -53,9 +53,9 @@
}
cc_library {
- name: "android.hardware.sensors@2.0-fakesubhal-config2",
+ name: "android.hardware.sensors@2.X-fakesubhal-config2",
vendor: true,
- defaults: ["android.hardware.sensors@2.0-fakesubhal-defaults"],
+ defaults: ["android.hardware.sensors@2.X-fakesubhal-defaults"],
cflags: [
"-DSUPPORT_ON_CHANGE_SENSORS",
"-DSUB_HAL_NAME=\"FakeSubHal-OnChange\"",
@@ -63,9 +63,9 @@
}
cc_test_library {
- name: "android.hardware.sensors@2.0-fakesubhal-unittest",
+ name: "android.hardware.sensors@2.X-fakesubhal-unittest",
vendor_available: true,
- defaults: ["android.hardware.sensors@2.0-fakesubhal-defaults"],
+ defaults: ["android.hardware.sensors@2.X-fakesubhal-defaults"],
cflags: [
"-DSUPPORT_ON_CHANGE_SENSORS",
"-DSUPPORT_CONTINUOUS_SENSORS",
@@ -74,17 +74,17 @@
}
cc_test {
- name: "android.hardware.sensors@2.0-halproxy-unit-tests",
+ name: "android.hardware.sensors@2.X-halproxy-unit-tests",
srcs: ["HalProxy_test.cpp"],
vendor: true,
static_libs: [
- "android.hardware.sensors@2.0-HalProxy",
- "android.hardware.sensors@2.0-fakesubhal-unittest",
+ "android.hardware.sensors@2.0-ScopedWakelock.testlib",
+ "android.hardware.sensors@2.X-multihal",
+ "android.hardware.sensors@2.X-fakesubhal-unittest",
],
shared_libs: [
"android.hardware.sensors@1.0",
"android.hardware.sensors@2.0",
- "android.hardware.sensors@2.0-ScopedWakelock",
"libbase",
"libcutils",
"libfmq",
diff --git a/sensors/2.0/multihal/tests/HalProxy_test.cpp b/sensors/common/default/2.X/multihal/tests/HalProxy_test.cpp
similarity index 95%
rename from sensors/2.0/multihal/tests/HalProxy_test.cpp
rename to sensors/common/default/2.X/multihal/tests/HalProxy_test.cpp
index 1fd35d1..4633a75 100644
--- a/sensors/2.0/multihal/tests/HalProxy_test.cpp
+++ b/sensors/common/default/2.X/multihal/tests/HalProxy_test.cpp
@@ -724,6 +724,45 @@
EXPECT_EQ(eventOut.sensorHandle, (subhal2Index << 24) | sensorHandleToPost);
}
+TEST(HalProxyTest, FillAndDrainPendingQueueTest) {
+ constexpr size_t kQueueSize = 5;
+ // TODO: Make this constant linked to same limit in HalProxy.h
+ constexpr size_t kMaxPendingQueueSize = 100000;
+ AllSensorsSubHal subhal;
+ std::vector<ISensorsSubHal*> subHals{&subhal};
+
+ std::unique_ptr<EventMessageQueue> eventQueue = makeEventFMQ(kQueueSize);
+ std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(kQueueSize);
+ ::android::sp<ISensorsCallback> callback = new SensorsCallback();
+ EventFlag* eventQueueFlag;
+ EventFlag::createEventFlag(eventQueue->getEventFlagWord(), &eventQueueFlag);
+ HalProxy proxy(subHals);
+ proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
+
+ // Fill pending queue
+ std::vector<Event> events = makeMultipleAccelerometerEvents(kQueueSize);
+ subhal.postEvents(events, false);
+ events = makeMultipleAccelerometerEvents(kMaxPendingQueueSize);
+ subhal.postEvents(events, false);
+
+ // Drain pending queue
+ for (int i = 0; i < kMaxPendingQueueSize + kQueueSize; i += kQueueSize) {
+ ASSERT_TRUE(readEventsOutOfQueue(kQueueSize, eventQueue, eventQueueFlag));
+ }
+
+ // Put one event on pending queue
+ events = makeMultipleAccelerometerEvents(kQueueSize);
+ subhal.postEvents(events, false);
+ events = {makeAccelerometerEvent()};
+ subhal.postEvents(events, false);
+
+ // Read out to make room for one event on pending queue to write to FMQ
+ ASSERT_TRUE(readEventsOutOfQueue(kQueueSize, eventQueue, eventQueueFlag));
+
+ // Should be able to read that last event off queue
+ EXPECT_TRUE(readEventsOutOfQueue(1, eventQueue, eventQueueFlag));
+}
+
// Helper implementations follow
void testSensorsListFromProxyAndSubHal(const std::vector<SensorInfo>& proxySensorsList,
const std::vector<SensorInfo>& subHalSensorsList) {
diff --git a/sensors/2.0/multihal/tests/fake_subhal/README b/sensors/common/default/2.X/multihal/tests/fake_subhal/README
similarity index 100%
rename from sensors/2.0/multihal/tests/fake_subhal/README
rename to sensors/common/default/2.X/multihal/tests/fake_subhal/README
diff --git a/sensors/2.0/multihal/tests/fake_subhal/Sensor.cpp b/sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.cpp
similarity index 100%
rename from sensors/2.0/multihal/tests/fake_subhal/Sensor.cpp
rename to sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.cpp
diff --git a/sensors/2.0/multihal/tests/fake_subhal/Sensor.h b/sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.h
similarity index 100%
rename from sensors/2.0/multihal/tests/fake_subhal/Sensor.h
rename to sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.h
diff --git a/sensors/2.0/multihal/tests/fake_subhal/SensorsSubHal.cpp b/sensors/common/default/2.X/multihal/tests/fake_subhal/SensorsSubHal.cpp
similarity index 100%
rename from sensors/2.0/multihal/tests/fake_subhal/SensorsSubHal.cpp
rename to sensors/common/default/2.X/multihal/tests/fake_subhal/SensorsSubHal.cpp
diff --git a/sensors/2.0/multihal/tests/fake_subhal/SensorsSubHal.h b/sensors/common/default/2.X/multihal/tests/fake_subhal/SensorsSubHal.h
similarity index 100%
rename from sensors/2.0/multihal/tests/fake_subhal/SensorsSubHal.h
rename to sensors/common/default/2.X/multihal/tests/fake_subhal/SensorsSubHal.h
diff --git a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
index 53ed259..745ab2d 100644
--- a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
+++ b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
@@ -469,201 +469,6 @@
ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::NORMAL));
}
-// Test if sensor hal can do UI speed accelerometer streaming properly
-TEST_P(SensorsHidlTest, AccelerometerStreamingOperationSlow) {
- testStreamingOperation(SensorTypeVersion::ACCELEROMETER, std::chrono::milliseconds(200),
- std::chrono::seconds(5), mAccelNormChecker);
-}
-
-// Test if sensor hal can do normal speed accelerometer streaming properly
-TEST_P(SensorsHidlTest, AccelerometerStreamingOperationNormal) {
- testStreamingOperation(SensorTypeVersion::ACCELEROMETER, std::chrono::milliseconds(20),
- std::chrono::seconds(5), mAccelNormChecker);
-}
-
-// Test if sensor hal can do game speed accelerometer streaming properly
-TEST_P(SensorsHidlTest, AccelerometerStreamingOperationFast) {
- testStreamingOperation(SensorTypeVersion::ACCELEROMETER, std::chrono::milliseconds(5),
- std::chrono::seconds(5), mAccelNormChecker);
-}
-
-// Test if sensor hal can do UI speed gyroscope streaming properly
-TEST_P(SensorsHidlTest, GyroscopeStreamingOperationSlow) {
- testStreamingOperation(SensorTypeVersion::GYROSCOPE, std::chrono::milliseconds(200),
- std::chrono::seconds(5), mGyroNormChecker);
-}
-
-// Test if sensor hal can do normal speed gyroscope streaming properly
-TEST_P(SensorsHidlTest, GyroscopeStreamingOperationNormal) {
- testStreamingOperation(SensorTypeVersion::GYROSCOPE, std::chrono::milliseconds(20),
- std::chrono::seconds(5), mGyroNormChecker);
-}
-
-// Test if sensor hal can do game speed gyroscope streaming properly
-TEST_P(SensorsHidlTest, GyroscopeStreamingOperationFast) {
- testStreamingOperation(SensorTypeVersion::GYROSCOPE, std::chrono::milliseconds(5),
- std::chrono::seconds(5), mGyroNormChecker);
-}
-
-// Test if sensor hal can do UI speed magnetometer streaming properly
-TEST_P(SensorsHidlTest, MagnetometerStreamingOperationSlow) {
- testStreamingOperation(SensorTypeVersion::MAGNETIC_FIELD, std::chrono::milliseconds(200),
- std::chrono::seconds(5), NullChecker<EventType>());
-}
-
-// Test if sensor hal can do normal speed magnetometer streaming properly
-TEST_P(SensorsHidlTest, MagnetometerStreamingOperationNormal) {
- testStreamingOperation(SensorTypeVersion::MAGNETIC_FIELD, std::chrono::milliseconds(20),
- std::chrono::seconds(5), NullChecker<EventType>());
-}
-
-// Test if sensor hal can do game speed magnetometer streaming properly
-TEST_P(SensorsHidlTest, MagnetometerStreamingOperationFast) {
- testStreamingOperation(SensorTypeVersion::MAGNETIC_FIELD, std::chrono::milliseconds(5),
- std::chrono::seconds(5), NullChecker<EventType>());
-}
-
-// Test if sensor hal can do accelerometer sampling rate switch properly when sensor is active
-TEST_P(SensorsHidlTest, AccelerometerSamplingPeriodHotSwitchOperation) {
- testSamplingRateHotSwitchOperation(SensorTypeVersion::ACCELEROMETER);
- testSamplingRateHotSwitchOperation(SensorTypeVersion::ACCELEROMETER, false /*fastToSlow*/);
-}
-
-// Test if sensor hal can do gyroscope sampling rate switch properly when sensor is active
-TEST_P(SensorsHidlTest, GyroscopeSamplingPeriodHotSwitchOperation) {
- testSamplingRateHotSwitchOperation(SensorTypeVersion::GYROSCOPE);
- testSamplingRateHotSwitchOperation(SensorTypeVersion::GYROSCOPE, false /*fastToSlow*/);
-}
-
-// Test if sensor hal can do magnetometer sampling rate switch properly when sensor is active
-TEST_P(SensorsHidlTest, MagnetometerSamplingPeriodHotSwitchOperation) {
- testSamplingRateHotSwitchOperation(SensorTypeVersion::MAGNETIC_FIELD);
- testSamplingRateHotSwitchOperation(SensorTypeVersion::MAGNETIC_FIELD, false /*fastToSlow*/);
-}
-
-// Test if sensor hal can do accelerometer batching properly
-TEST_P(SensorsHidlTest, AccelerometerBatchingOperation) {
- testBatchingOperation(SensorTypeVersion::ACCELEROMETER);
-}
-
-// Test if sensor hal can do gyroscope batching properly
-TEST_P(SensorsHidlTest, GyroscopeBatchingOperation) {
- testBatchingOperation(SensorTypeVersion::GYROSCOPE);
-}
-
-// Test if sensor hal can do magnetometer batching properly
-TEST_P(SensorsHidlTest, MagnetometerBatchingOperation) {
- testBatchingOperation(SensorTypeVersion::MAGNETIC_FIELD);
-}
-
-// Test sensor event direct report with ashmem for accel sensor at normal rate
-TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationNormal) {
- testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::ASHMEM,
- RateLevel::NORMAL, mAccelNormChecker);
-}
-
-// Test sensor event direct report with ashmem for accel sensor at fast rate
-TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationFast) {
- testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::ASHMEM,
- RateLevel::FAST, mAccelNormChecker);
-}
-
-// Test sensor event direct report with ashmem for accel sensor at very fast rate
-TEST_P(SensorsHidlTest, AccelerometerAshmemDirectReportOperationVeryFast) {
- testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::ASHMEM,
- RateLevel::VERY_FAST, mAccelNormChecker);
-}
-
-// Test sensor event direct report with ashmem for gyro sensor at normal rate
-TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationNormal) {
- testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::ASHMEM,
- RateLevel::NORMAL, mGyroNormChecker);
-}
-
-// Test sensor event direct report with ashmem for gyro sensor at fast rate
-TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationFast) {
- testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::FAST,
- mGyroNormChecker);
-}
-
-// Test sensor event direct report with ashmem for gyro sensor at very fast rate
-TEST_P(SensorsHidlTest, GyroscopeAshmemDirectReportOperationVeryFast) {
- testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::ASHMEM,
- RateLevel::VERY_FAST, mGyroNormChecker);
-}
-
-// Test sensor event direct report with ashmem for mag sensor at normal rate
-TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationNormal) {
- testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::ASHMEM,
- RateLevel::NORMAL, NullChecker<EventType>());
-}
-
-// Test sensor event direct report with ashmem for mag sensor at fast rate
-TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationFast) {
- testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::ASHMEM,
- RateLevel::FAST, NullChecker<EventType>());
-}
-
-// Test sensor event direct report with ashmem for mag sensor at very fast rate
-TEST_P(SensorsHidlTest, MagnetometerAshmemDirectReportOperationVeryFast) {
- testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::ASHMEM,
- RateLevel::VERY_FAST, NullChecker<EventType>());
-}
-
-// Test sensor event direct report with gralloc for accel sensor at normal rate
-TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationNormal) {
- testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::GRALLOC,
- RateLevel::NORMAL, mAccelNormChecker);
-}
-
-// Test sensor event direct report with gralloc for accel sensor at fast rate
-TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationFast) {
- testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::GRALLOC,
- RateLevel::FAST, mAccelNormChecker);
-}
-
-// Test sensor event direct report with gralloc for accel sensor at very fast rate
-TEST_P(SensorsHidlTest, AccelerometerGrallocDirectReportOperationVeryFast) {
- testDirectReportOperation(SensorTypeVersion::ACCELEROMETER, SharedMemType::GRALLOC,
- RateLevel::VERY_FAST, mAccelNormChecker);
-}
-
-// Test sensor event direct report with gralloc for gyro sensor at normal rate
-TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationNormal) {
- testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::GRALLOC,
- RateLevel::NORMAL, mGyroNormChecker);
-}
-
-// Test sensor event direct report with gralloc for gyro sensor at fast rate
-TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationFast) {
- testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::FAST,
- mGyroNormChecker);
-}
-
-// Test sensor event direct report with gralloc for gyro sensor at very fast rate
-TEST_P(SensorsHidlTest, GyroscopeGrallocDirectReportOperationVeryFast) {
- testDirectReportOperation(SensorTypeVersion::GYROSCOPE, SharedMemType::GRALLOC,
- RateLevel::VERY_FAST, mGyroNormChecker);
-}
-
-// Test sensor event direct report with gralloc for mag sensor at normal rate
-TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationNormal) {
- testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::GRALLOC,
- RateLevel::NORMAL, NullChecker<EventType>());
-}
-
-// Test sensor event direct report with gralloc for mag sensor at fast rate
-TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationFast) {
- testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::GRALLOC,
- RateLevel::FAST, NullChecker<EventType>());
-}
-
-// Test sensor event direct report with gralloc for mag sensor at very fast rate
-TEST_P(SensorsHidlTest, MagnetometerGrallocDirectReportOperationVeryFast) {
- testDirectReportOperation(SensorTypeVersion::MAGNETIC_FIELD, SharedMemType::GRALLOC,
- RateLevel::VERY_FAST, NullChecker<EventType>());
-}
-
void SensorsHidlTest::activateAllSensors(bool enable) {
for (const SensorInfoType& sensorInfo : getSensorsList()) {
if (isValidType(sensorInfo.type)) {
@@ -829,21 +634,6 @@
Result::BAD_VALUE);
}
-TEST_P(SensorsHidlTest, FlushNonexistentSensor) {
- SensorInfoType sensor;
- std::vector<SensorInfoType> sensors = getNonOneShotSensors();
- if (sensors.size() == 0) {
- sensors = getOneShotSensors();
- if (sensors.size() == 0) {
- return;
- }
- }
- sensor = sensors.front();
- sensor.sensorHandle = getInvalidSensorHandle();
- runSingleFlushTest(std::vector<SensorInfoType>{sensor}, false /* activateSensor */,
- 0 /* expectedFlushCount */, Result::BAD_VALUE);
-}
-
TEST_P(SensorsHidlTest, Batch) {
if (getSensorsList().size() == 0) {
return;
@@ -1124,63 +914,3 @@
}
return found;
}
-
-TEST_P(SensorsHidlTest, ConfigureDirectChannelWithInvalidHandle) {
- SensorInfoType sensor;
- SharedMemType memType;
- RateLevel rate;
- if (!getDirectChannelSensor(&sensor, &memType, &rate)) {
- return;
- }
-
- // Verify that an invalid channel handle produces a BAD_VALUE result
- configDirectReport(sensor.sensorHandle, -1, rate, [](Result result, int32_t /* reportToken */) {
- ASSERT_EQ(result, Result::BAD_VALUE);
- });
-}
-
-TEST_P(SensorsHidlTest, CleanupDirectConnectionOnInitialize) {
- constexpr size_t kNumEvents = 1;
- constexpr size_t kMemSize = kNumEvents * kEventSize;
-
- SensorInfoType sensor;
- SharedMemType memType;
- RateLevel rate;
-
- if (!getDirectChannelSensor(&sensor, &memType, &rate)) {
- return;
- }
-
- std::shared_ptr<SensorsTestSharedMemory<SensorTypeVersion, EventType>> mem(
- SensorsTestSharedMemory<SensorTypeVersion, EventType>::create(memType, kMemSize));
- ASSERT_NE(mem, nullptr);
-
- int32_t directChannelHandle = 0;
- registerDirectChannel(mem->getSharedMemInfo(), [&](Result result, int32_t channelHandle) {
- ASSERT_EQ(result, Result::OK);
- directChannelHandle = channelHandle;
- });
-
- // Configure the channel and expect success
- configDirectReport(
- sensor.sensorHandle, directChannelHandle, rate,
- [](Result result, int32_t /* reportToken */) { ASSERT_EQ(result, Result::OK); });
-
- // Call initialize() via the environment setup to cause the HAL to re-initialize
- // Clear the active direct connections so they are not stopped during TearDown
- auto handles = mDirectChannelHandles;
- mDirectChannelHandles.clear();
- getEnvironment()->HidlTearDown();
- getEnvironment()->HidlSetUp();
- if (HasFatalFailure()) {
- return; // Exit early if resetting the environment failed
- }
-
- // Attempt to configure the direct channel and expect it to fail
- configDirectReport(
- sensor.sensorHandle, directChannelHandle, rate,
- [](Result result, int32_t /* reportToken */) { ASSERT_EQ(result, Result::BAD_VALUE); });
-
- // Restore original handles, though they should already be deactivated
- mDirectChannelHandles = handles;
-}
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h
index 781427d..19dfbe5 100644
--- a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h
@@ -46,12 +46,7 @@
std::this_thread::sleep_for(std::chrono::seconds(3));
}
- virtual void HidlTearDown() {
- mStopThread = true;
- if (mPollThread.joinable()) {
- mPollThread.join();
- }
- }
+ virtual void HidlTearDown() = 0;
// Get and clear all events collected so far (like "cat" shell command).
// If output is nullptr, it clears all collected events.
diff --git a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
index 06a8bf5..6489c1d 100644
--- a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
+++ b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl
@@ -202,6 +202,12 @@
* once enabled and assigned an effect to play. This may not be supported
* and this support is reflected in getCapabilities (CAP_ALWAYS_ON_CONTROL).
*
+ * The always-on source ID is conveyed directly to clients through
+ * device/board configuration files ensuring that no ID is assigned to
+ * multiple clients. No client should use this API unless explicitly
+ * assigned an always-on source ID. Clients must develop their own way to
+ * get IDs from vendor in a stable way.
+ *
* @param id The device-specific always-on source ID to enable.
* @param effect The type of haptic event to trigger.
* @param strength The intensity of haptic event to trigger.
@@ -212,6 +218,12 @@
* Disable an always-on haptic source. This may not be supported and this
* support is reflected in getCapabilities (CAP_ALWAYS_ON_CONTROL).
*
+ * The always-on source ID is conveyed directly to clients through
+ * device/board configuration files ensuring that no ID is assigned to
+ * multiple clients. No client should use this API unless explicitly
+ * assigned an always-on source ID. Clients must develop their own way to
+ * get IDs from vendor in a stable way.
+ *
* @param id The device-specific always-on source ID to disable.
*/
void alwaysOnDisable(in int id);
diff --git a/wifi/supplicant/1.3/vts/functional/supplicant_hidl_test_utils_1_3.cpp b/wifi/supplicant/1.3/vts/functional/supplicant_hidl_test_utils_1_3.cpp
index 7ea5462..dbf2b91 100644
--- a/wifi/supplicant/1.3/vts/functional/supplicant_hidl_test_utils_1_3.cpp
+++ b/wifi/supplicant/1.3/vts/functional/supplicant_hidl_test_utils_1_3.cpp
@@ -21,6 +21,8 @@
#include "supplicant_hidl_test_utils_1_3.h"
using ::android::sp;
+using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
+using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
using ::android::hardware::wifi::supplicant::V1_3::ISupplicant;
using ::android::hardware::wifi::supplicant::V1_3::ISupplicantStaIface;
using ::android::hardware::wifi::supplicant::V1_3::ISupplicantStaNetwork;
@@ -43,3 +45,15 @@
return ISupplicant::castFrom(
getSupplicant(supplicant_instance_name, isP2pOn));
}
+
+bool isFilsSupported(sp<ISupplicantStaIface> sta_iface) {
+ uint32_t keyMgmtMask = 0;
+ sta_iface->getKeyMgmtCapabilities_1_3(
+ [&](const SupplicantStatus& status, uint32_t keyMgmtMaskInternal) {
+ EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+ keyMgmtMask = keyMgmtMaskInternal;
+ });
+
+ return (keyMgmtMask & (ISupplicantStaNetwork::KeyMgmtMask::FILS_SHA256 |
+ ISupplicantStaNetwork::KeyMgmtMask::FILS_SHA384));
+}
diff --git a/wifi/supplicant/1.3/vts/functional/supplicant_hidl_test_utils_1_3.h b/wifi/supplicant/1.3/vts/functional/supplicant_hidl_test_utils_1_3.h
index f8dca13..69fc598 100644
--- a/wifi/supplicant/1.3/vts/functional/supplicant_hidl_test_utils_1_3.h
+++ b/wifi/supplicant/1.3/vts/functional/supplicant_hidl_test_utils_1_3.h
@@ -31,4 +31,7 @@
supplicant);
android::sp<android::hardware::wifi::supplicant::V1_3::ISupplicant>
getSupplicant_1_3(const std::string& supplicant_instance_name, bool isP2pOn);
+bool isFilsSupported(
+ android::sp<android::hardware::wifi::supplicant::V1_3::ISupplicantStaIface>
+ sta_iface);
#endif /* SUPPLICANT_HIDL_TEST_UTILS_1_3_H */
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 f7019d2..3754520 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
@@ -517,7 +517,10 @@
* FilsHlpAddRequest
*/
TEST_P(SupplicantStaIfaceHidlTest, FilsHlpAddRequest) {
- uint32_t keyMgmtMask = 0;
+ if (!isFilsSupported(sta_iface_)) {
+ GTEST_SKIP()
+ << "Skipping test since driver/supplicant doesn't support FILS";
+ }
uint8_t destMacAddr[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
std::vector<uint8_t> pktBuffer = {
0x08, 0x00, 0x45, 0x10, 0x01, 0x3a, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
@@ -548,22 +551,9 @@
0x63, 0x70, 0x2d, 0x52, 0x37, 0x0a, 0x01, 0x03, 0x06, 0x0f, 0x1a, 0x1c,
0x33, 0x3a, 0x3b, 0x2b, 0xff, 0x00};
- sta_iface_->getKeyMgmtCapabilities_1_3(
- [&](const SupplicantStatus& status, uint32_t keyMgmtMaskInternal) {
- EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
- keyMgmtMask = keyMgmtMaskInternal;
- });
-
- SupplicantStatusCode expectedStatusCode =
- (keyMgmtMask & (ISupplicantStaNetwork::KeyMgmtMask::FILS_SHA256 |
- ISupplicantStaNetwork::KeyMgmtMask::FILS_SHA384))
- ? SupplicantStatusCode::SUCCESS
- : SupplicantStatusCode::FAILURE_UNKNOWN;
-
sta_iface_->filsHlpAddRequest(
- destMacAddr, pktBuffer,
- [expectedStatusCode](const SupplicantStatus& status) {
- EXPECT_EQ(expectedStatusCode, status.code);
+ destMacAddr, pktBuffer, [](const SupplicantStatus& status) {
+ EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
});
}
@@ -571,23 +561,14 @@
* FilsHlpFlushRequest
*/
TEST_P(SupplicantStaIfaceHidlTest, FilsHlpFlushRequest) {
- uint32_t keyMgmtMask = 0;
- sta_iface_->getKeyMgmtCapabilities_1_3(
- [&](const SupplicantStatus& status, uint32_t keyMgmtMaskInternal) {
- EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
- keyMgmtMask = keyMgmtMaskInternal;
- });
+ if (!isFilsSupported(sta_iface_)) {
+ GTEST_SKIP()
+ << "Skipping test since driver/supplicant doesn't support FILS";
+ }
- SupplicantStatusCode expectedStatusCode =
- (keyMgmtMask & (ISupplicantStaNetwork::KeyMgmtMask::FILS_SHA256 |
- ISupplicantStaNetwork::KeyMgmtMask::FILS_SHA384))
- ? SupplicantStatusCode::SUCCESS
- : SupplicantStatusCode::FAILURE_UNKNOWN;
-
- sta_iface_->filsHlpFlushRequest(
- [expectedStatusCode](const SupplicantStatus& status) {
- EXPECT_EQ(expectedStatusCode, status.code);
- });
+ sta_iface_->filsHlpFlushRequest([](const SupplicantStatus& status) {
+ EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+ });
}
INSTANTIATE_TEST_CASE_P(
PerInstance, SupplicantStaIfaceHidlTest,
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 6be24bc..9c40de1 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
@@ -290,23 +290,14 @@
* SetEapErp
*/
TEST_P(SupplicantStaNetworkHidlTest, SetEapErp) {
- uint32_t keyMgmtMask = 0;
- sta_iface_->getKeyMgmtCapabilities_1_3(
- [&](const SupplicantStatus &status, uint32_t keyMgmtMaskInternal) {
- EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
- keyMgmtMask = keyMgmtMaskInternal;
- });
+ if (!isFilsSupported(sta_iface_)) {
+ GTEST_SKIP()
+ << "Skipping test since driver/supplicant doesn't support FILS";
+ }
- SupplicantStatusCode expectedStatusCode =
- (keyMgmtMask & (ISupplicantStaNetwork::KeyMgmtMask::FILS_SHA256 |
- ISupplicantStaNetwork::KeyMgmtMask::FILS_SHA384))
- ? SupplicantStatusCode::SUCCESS
- : SupplicantStatusCode::FAILURE_UNKNOWN;
-
- sta_network_->setEapErp(
- true, [expectedStatusCode](const SupplicantStatus &status) {
- EXPECT_EQ(expectedStatusCode, status.code);
- });
+ sta_network_->setEapErp(true, [](const SupplicantStatus &status) {
+ EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+ });
}
INSTANTIATE_TEST_CASE_P(
PerInstance, SupplicantStaNetworkHidlTest,