From b3d4348b769c0f0c22b09a774eb35e660256d220 Mon Sep 17 00:00:00 2001 From: Veerendranath Jakkam Date: Thu, 11 Jun 2020 20:12:48 +0530 Subject: [PATCH 01/27] wifi: Update wifi_wait_for_driver_ready return status handling Now wifi_wait_for_driver_ready can return WIFI_ERROR_UNKNOWN also thus update return status handling. Bug: 157090295 Test: Basic function test, SSR test Change-Id: Iea459bc2801418b1b21d15ce1ca3da9be64a4fe3 --- wifi/1.4/default/wifi_legacy_hal.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wifi/1.4/default/wifi_legacy_hal.cpp b/wifi/1.4/default/wifi_legacy_hal.cpp index 29123bfe47..75f22ec3ea 100644 --- a/wifi/1.4/default/wifi_legacy_hal.cpp +++ b/wifi/1.4/default/wifi_legacy_hal.cpp @@ -367,8 +367,8 @@ wifi_error WifiLegacyHal::start() { } LOG(DEBUG) << "Waiting for the driver ready"; wifi_error status = global_func_table_.wifi_wait_for_driver_ready(); - if (status == WIFI_ERROR_TIMED_OUT) { - LOG(ERROR) << "Timed out awaiting driver ready"; + if (status == WIFI_ERROR_TIMED_OUT || status == WIFI_ERROR_UNKNOWN) { + LOG(ERROR) << "Failed or timed out awaiting driver ready"; return status; } property_set(kDriverPropName, "ok"); From ca7a8c9559ecc330160c52eb26874300ff8fd215 Mon Sep 17 00:00:00 2001 From: TF Huang Date: Wed, 1 Jul 2020 10:43:31 +0800 Subject: [PATCH 02/27] wlan: add supported interfaces in rc file Service vendor.wifi_hal_legacy should add all supported interface into relevant .rc files. Bug: 160377428 Test: Wifi presubmit tests Change-Id: I68e8d3e7ddb1470a92c5ccd30f6d4d5f90ad9e37 Merged-In: I68e8d3e7ddb1470a92c5ccd30f6d4d5f90ad9e37 --- wifi/1.4/default/android.hardware.wifi@1.0-service-lazy.rc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/wifi/1.4/default/android.hardware.wifi@1.0-service-lazy.rc b/wifi/1.4/default/android.hardware.wifi@1.0-service-lazy.rc index cf917b5458..061689dbe5 100644 --- a/wifi/1.4/default/android.hardware.wifi@1.0-service-lazy.rc +++ b/wifi/1.4/default/android.hardware.wifi@1.0-service-lazy.rc @@ -1,5 +1,9 @@ service vendor.wifi_hal_legacy /vendor/bin/hw/android.hardware.wifi@1.0-service-lazy interface android.hardware.wifi@1.0::IWifi default + interface android.hardware.wifi@1.1::IWifi default + interface android.hardware.wifi@1.2::IWifi default + interface android.hardware.wifi@1.3::IWifi default + interface android.hardware.wifi@1.4::IWifi default oneshot disabled class hal From 3e9d442fa1e713d78174a4df72c0ada213dc1a77 Mon Sep 17 00:00:00 2001 From: felipeal Date: Fri, 17 Jul 2020 18:24:35 -0700 Subject: [PATCH 03/27] Fixed EmulatedUserHal so it supports SwitchUserMessageType::VEHICLE_REQUEST Test: adb shell lshal debug android.hardware.automotive.vehicle@2.0::IVehicle/default --set 299896584 a 1 i -42 i 4 i 11 Fixes: 161574356 Change-Id: Iaf5d8e35f556c72350cdb9b6665adb31fca26871 --- .../2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp index 6a6b12f485..f5cc7b2d77 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp @@ -102,6 +102,15 @@ android::base::Result> EmulatedUserHal::onSetS } if (value.areaId != 0) { + if (value.value.int32Values.size() >= 2 && + static_cast(value.value.int32Values[1]) == + SwitchUserMessageType::VEHICLE_REQUEST) { + // User HAL can also request a user switch, so we need to check it first + ALOGD("set(SWITCH_USER) called from lshal to emulate a vehicle request: %s", + toString(value).c_str()); + return std::unique_ptr(new VehiclePropValue(value)); + } + // Otherwise, we store it ALOGD("set(SWITCH_USER) called from lshal; storing it: %s", toString(value).c_str()); mSwitchUserResponseFromCmd.reset(new VehiclePropValue(value)); return {}; From 5b46a339d02db834a927c45ac3c4bd88006cdc04 Mon Sep 17 00:00:00 2001 From: felipeal Date: Thu, 9 Jul 2020 15:22:22 -0700 Subject: [PATCH 04/27] Fixed EmulatedUserHal merge issues. Some changes were not properly auto-merged, and it's quite impossible to cherry-pick them automatically (using git), so this CL is manually fixing it. Test: adb shell lshal debug android.hardware.automotive.vehic le@2.0::IVehicle/default --user-hal Bug: 150413515 Change-Id: Ibb8bef2c1ae8df32369dff5c5e5de76480b3a66f Merged-In: I5c8b99b8027b5ec10ace323d872cd85f9a0d4177 --- .../default/impl/vhal_v2_0/DefaultConfig.h | 16 ++ .../impl/vhal_v2_0/EmulatedUserHal.cpp | 138 ++++++++++++++++++ .../default/impl/vhal_v2_0/EmulatedUserHal.h | 38 ++++- .../impl/vhal_v2_0/EmulatedVehicleHal.cpp | 28 +++- .../impl/vhal_v2_0/EmulatedVehicleHal.h | 6 +- .../impl/vhal_v2_0/VehicleHalServer.cpp | 5 + .../default/impl/vhal_v2_0/VehicleHalServer.h | 2 + 7 files changed, 228 insertions(+), 5 deletions(-) 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 b8a606adab..16c33b9d19 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 @@ -1036,6 +1036,22 @@ const ConfigDeclaration kVehicleProperties[]{ .changeMode = VehiclePropertyChangeMode::ON_CHANGE, }, }, + { + .config = + { + .prop = toInt(VehicleProperty::CREATE_USER), + .access = VehiclePropertyAccess::READ_WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + }, + }, + { + .config = + { + .prop = toInt(VehicleProperty::REMOVE_USER), + .access = VehiclePropertyAccess::READ_WRITE, + .changeMode = VehiclePropertyChangeMode::ON_CHANGE, + }, + }, { .config = { diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp index 6a6b12f485..ea38cb3941 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp @@ -30,11 +30,18 @@ namespace impl { constexpr int INITIAL_USER_INFO = static_cast(VehicleProperty::INITIAL_USER_INFO); constexpr int SWITCH_USER = static_cast(VehicleProperty::SWITCH_USER); +constexpr int CREATE_USER = static_cast(VehicleProperty::CREATE_USER); +constexpr int REMOVE_USER = static_cast(VehicleProperty::REMOVE_USER); +constexpr int USER_IDENTIFICATION_ASSOCIATION = + static_cast(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION); bool EmulatedUserHal::isSupported(int32_t prop) { switch (prop) { case INITIAL_USER_INFO: case SWITCH_USER: + case CREATE_USER: + case REMOVE_USER: + case USER_IDENTIFICATION_ASSOCIATION: return true; default: return false; @@ -50,12 +57,58 @@ android::base::Result> EmulatedUserHal::onSetP return onSetInitialUserInfoResponse(value); case SWITCH_USER: return onSetSwitchUserResponse(value); + case CREATE_USER: + return onSetCreateUserResponse(value); + case REMOVE_USER: + ALOGI("REMOVE_USER is FYI only, nothing to do..."); + return {}; + case USER_IDENTIFICATION_ASSOCIATION: + return onSetUserIdentificationAssociation(value); default: return android::base::Error(static_cast(StatusCode::INVALID_ARG)) << "Unsupported property: " << toString(value); } } +android::base::Result> EmulatedUserHal::onGetProperty( + const VehiclePropValue& value) { + ALOGV("onGetProperty(%s)", toString(value).c_str()); + switch (value.prop) { + case INITIAL_USER_INFO: + case SWITCH_USER: + case CREATE_USER: + case REMOVE_USER: + ALOGE("onGetProperty(): %d is only supported on SET", value.prop); + return android::base::Error(static_cast(StatusCode::INVALID_ARG)) + << "only supported on SET"; + case USER_IDENTIFICATION_ASSOCIATION: + return onGetUserIdentificationAssociation(value); + default: + ALOGE("onGetProperty(): %d is not supported", value.prop); + return android::base::Error(static_cast(StatusCode::INVALID_ARG)) + << "not supported by User HAL"; + } +} + +android::base::Result> +EmulatedUserHal::onGetUserIdentificationAssociation(const VehiclePropValue& value) { + if (mSetUserIdentificationAssociationResponseFromCmd != nullptr) { + ALOGI("get(USER_IDENTIFICATION_ASSOCIATION): returning %s", + toString(*mSetUserIdentificationAssociationResponseFromCmd).c_str()); + auto newValue = std::unique_ptr( + new VehiclePropValue(*mSetUserIdentificationAssociationResponseFromCmd)); + // Must use the same requestId + if (value.value.int32Values.size() > 0) { + newValue->value.int32Values[0] = value.value.int32Values[0]; + } else { + ALOGE("get(USER_IDENTIFICATION_ASSOCIATION): no requestId on %s", + toString(value).c_str()); + } + return newValue; + } + return defaultUserIdentificationAssociation(value); +} + android::base::Result> EmulatedUserHal::onSetInitialUserInfoResponse(const VehiclePropValue& value) { if (value.value.int32Values.size() == 0) { @@ -144,6 +197,79 @@ android::base::Result> EmulatedUserHal::onSetS return updatedValue; } +android::base::Result> EmulatedUserHal::onSetCreateUserResponse( + const VehiclePropValue& value) { + if (value.value.int32Values.size() == 0) { + ALOGE("set(CREATE_USER): no int32values, ignoring it: %s", toString(value).c_str()); + return android::base::Error(static_cast(StatusCode::INVALID_ARG)) + << "no int32values on " << toString(value); + } + + if (value.areaId != 0) { + ALOGD("set(CREATE_USER) called from lshal; storing it: %s", toString(value).c_str()); + mCreateUserResponseFromCmd.reset(new VehiclePropValue(value)); + return {}; + } + ALOGD("set(CREATE_USER) called from Android: %s", toString(value).c_str()); + + int32_t requestId = value.value.int32Values[0]; + if (mCreateUserResponseFromCmd != nullptr) { + ALOGI("replying CREATE_USER with lshal value: %s", + toString(*mCreateUserResponseFromCmd).c_str()); + return sendUserHalResponse(std::move(mCreateUserResponseFromCmd), requestId); + } + + // Returns default response + auto updatedValue = std::unique_ptr(new VehiclePropValue); + updatedValue->prop = CREATE_USER; + updatedValue->timestamp = elapsedRealtimeNano(); + updatedValue->value.int32Values.resize(2); + updatedValue->value.int32Values[0] = requestId; + updatedValue->value.int32Values[1] = (int32_t)CreateUserStatus::SUCCESS; + + ALOGI("no lshal response; replying with SUCCESS: %s", toString(*updatedValue).c_str()); + + return updatedValue; +} + +android::base::Result> +EmulatedUserHal::onSetUserIdentificationAssociation(const VehiclePropValue& value) { + if (value.value.int32Values.size() == 0) { + ALOGE("set(USER_IDENTIFICATION_ASSOCIATION): no int32values, ignoring it: %s", + toString(value).c_str()); + return android::base::Error(static_cast(StatusCode::INVALID_ARG)) + << "no int32values on " << toString(value); + } + + if (value.areaId != 0) { + ALOGD("set(USER_IDENTIFICATION_ASSOCIATION) called from lshal; storing it: %s", + toString(value).c_str()); + mSetUserIdentificationAssociationResponseFromCmd.reset(new VehiclePropValue(value)); + return {}; + } + ALOGD("set(USER_IDENTIFICATION_ASSOCIATION) called from Android: %s", toString(value).c_str()); + + int32_t requestId = value.value.int32Values[0]; + if (mSetUserIdentificationAssociationResponseFromCmd != nullptr) { + ALOGI("replying USER_IDENTIFICATION_ASSOCIATION with lshal value: %s", + toString(*mSetUserIdentificationAssociationResponseFromCmd).c_str()); + // Not moving response so it can be used on GET requests + auto copy = std::unique_ptr( + new VehiclePropValue(*mSetUserIdentificationAssociationResponseFromCmd)); + return sendUserHalResponse(std::move(copy), requestId); + } + + // Returns default response + return defaultUserIdentificationAssociation(value); +} + +android::base::Result> +EmulatedUserHal::defaultUserIdentificationAssociation(const VehiclePropValue& request) { + // TODO(b/159498909): return a response with NOT_ASSOCIATED_ANY_USER for all requested types + ALOGE("no lshal response for %s; replying with NOT_AVAILABLE", toString(request).c_str()); + return android::base::Error(static_cast(StatusCode::NOT_AVAILABLE)) << "not set by lshal"; +} + android::base::Result> EmulatedUserHal::sendUserHalResponse( std::unique_ptr response, int32_t requestId) { switch (response->areaId) { @@ -189,6 +315,18 @@ void EmulatedUserHal::dump(int fd, std::string indent) { } else { dprintf(fd, "%sNo SwitchUser response\n", indent.c_str()); } + if (mCreateUserResponseFromCmd != nullptr) { + dprintf(fd, "%sCreateUser response: %s\n", indent.c_str(), + toString(*mCreateUserResponseFromCmd).c_str()); + } else { + dprintf(fd, "%sNo CreateUser response\n", indent.c_str()); + } + if (mSetUserIdentificationAssociationResponseFromCmd != nullptr) { + dprintf(fd, "%sSetUserIdentificationAssociation response: %s\n", indent.c_str(), + toString(*mSetUserIdentificationAssociationResponseFromCmd).c_str()); + } else { + dprintf(fd, "%sNo SetUserIdentificationAssociation response\n", indent.c_str()); + } } } // namespace impl diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.h index b25efcb4d7..db2f117e3e 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.h +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.h @@ -46,13 +46,21 @@ class EmulatedUserHal { bool isSupported(int32_t prop); /** - * Lets the emulator handle the property. + * Lets the emulator set the property. * * @return updated property and StatusCode */ android::base::Result> onSetProperty( const VehiclePropValue& value); + /** + * Gets the property value from the emulator. + * + * @return property value and StatusCode + */ + android::base::Result> onGetProperty( + const VehiclePropValue& value); + /** * Shows the User HAL emulation help. */ @@ -97,11 +105,39 @@ class EmulatedUserHal { android::base::Result> onSetSwitchUserResponse( const VehiclePropValue& value); + /** + * Used to emulate CREATE_USER - see onSetInitialUserInfoResponse() for usage. + */ + android::base::Result> onSetCreateUserResponse( + const VehiclePropValue& value); + + /** + * Used to emulate set USER_IDENTIFICATION_ASSOCIATION - see onSetInitialUserInfoResponse() for + * usage. + */ + android::base::Result> onSetUserIdentificationAssociation( + const VehiclePropValue& value); + + /** + * Used to emulate get USER_IDENTIFICATION_ASSOCIATION - see onSetInitialUserInfoResponse() for + * usage. + */ + android::base::Result> onGetUserIdentificationAssociation( + const VehiclePropValue& value); + + /** + * Creates a default USER_IDENTIFICATION_ASSOCIATION when it was not set by lshal. + */ + android::base::Result> defaultUserIdentificationAssociation( + const VehiclePropValue& request); + android::base::Result> sendUserHalResponse( std::unique_ptr response, int32_t requestId); std::unique_ptr mInitialUserResponseFromCmd; std::unique_ptr mSwitchUserResponseFromCmd; + std::unique_ptr mCreateUserResponseFromCmd; + std::unique_ptr mSetUserIdentificationAssociationResponseFromCmd; }; } // 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 a08d8e7516..1d516005a9 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,14 @@ static std::unique_ptr fillDefaultObd2Frame(size_t numVendorInt return sensorStore; } -EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client) +EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client, + EmulatedUserHal* emulatedUserHal) : mPropStore(propStore), mHvacPowerProps(std::begin(kHvacPowerProperties), std::end(kHvacPowerProperties)), mRecurrentTimer(std::bind(&EmulatedVehicleHal::onContinuousPropertyTimer, this, std::placeholders::_1)), - mVehicleClient(client) { + mVehicleClient(client), + mEmulatedUserHal(emulatedUserHal) { initStaticConfig(); for (size_t i = 0; i < arraysize(kVehicleProperties); i++) { mPropStore->registerProperty(kVehicleProperties[i].config); @@ -105,6 +107,8 @@ EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore, VehicleH VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::get( const VehiclePropValue& requestedPropValue, StatusCode* outStatus) { auto propId = requestedPropValue.prop; + ALOGV("get(%d)", propId); + auto& pool = *getValuePool(); VehiclePropValuePtr v = nullptr; @@ -118,6 +122,26 @@ VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::get( *outStatus = fillObd2DtcInfo(v.get()); break; default: + if (mEmulatedUserHal != nullptr && mEmulatedUserHal->isSupported(propId)) { + ALOGI("get(): getting value for prop %d from User HAL", propId); + const auto& ret = mEmulatedUserHal->onGetProperty(requestedPropValue); + if (!ret.ok()) { + ALOGE("get(): User HAL returned error: %s", ret.error().message().c_str()); + *outStatus = StatusCode(ret.error().code()); + } else { + auto value = ret.value().get(); + if (value != nullptr) { + ALOGI("get(): User HAL returned value: %s", toString(*value).c_str()); + v = getValuePool()->obtain(*value); + *outStatus = StatusCode::OK; + } else { + ALOGE("get(): User HAL returned null value"); + *outStatus = StatusCode::INTERNAL_ERROR; + } + } + break; + } + auto internalPropValue = mPropStore->readValueOrNull(requestedPropValue); if (internalPropValue != nullptr) { v = getValuePool()->obtain(*internalPropValue); 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 ebf19951b3..30f6bfa759 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 @@ -30,6 +30,7 @@ #include "vhal_v2_0/VehiclePropertyStore.h" #include "DefaultConfig.h" +#include "EmulatedUserHal.h" #include "EmulatedVehicleConnector.h" #include "GeneratorHub.h" #include "VehicleEmulator.h" @@ -45,8 +46,8 @@ namespace impl { /** Implementation of VehicleHal that connected to emulator instead of real vehicle network. */ class EmulatedVehicleHal : public EmulatedVehicleHalIface { public: - EmulatedVehicleHal(VehiclePropertyStore* propStore, - VehicleHalClient* client); + EmulatedVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client, + EmulatedUserHal* emulatedUserHal = nullptr); ~EmulatedVehicleHal() = default; // Methods from VehicleHal @@ -86,6 +87,7 @@ private: std::unordered_set mHvacPowerProps; RecurrentTimer mRecurrentTimer; VehicleHalClient* mVehicleClient; + EmulatedUserHal* mEmulatedUserHal; }; } // 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 index ad5096e58f..36f25345ae 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp @@ -41,6 +41,10 @@ VehiclePropValuePool* VehicleHalServer::getValuePool() const { return mValuePool; } +EmulatedUserHal* VehicleHalServer::getEmulatedUserHal() { + return &mEmulatedUserHal; +} + void VehicleHalServer::setValuePool(VehiclePropValuePool* valuePool) { if (!valuePool) { LOG(WARNING) << __func__ << ": Setting value pool to nullptr!"; @@ -197,6 +201,7 @@ StatusCode VehicleHalServer::onSetProperty(const VehiclePropValue& value, bool u } return StatusCode::OK; } + LOG(DEBUG) << "onSetProperty(" << value.prop << ")"; // Some properties need to be treated non-trivially switch (value.prop) { 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 index 2841fbee3c..fca78bc822 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.h @@ -38,6 +38,8 @@ class VehicleHalServer : public IVehicleServer { // Set the Property Value Pool used in this server void setValuePool(VehiclePropValuePool* valuePool); + EmulatedUserHal* getEmulatedUserHal(); + private: using VehiclePropValuePtr = recyclable_ptr; From 6b75eeb045aaea5477f9615f2fa9bdf2945be923 Mon Sep 17 00:00:00 2001 From: Sunil Ravi Date: Tue, 21 Jul 2020 22:15:01 -0700 Subject: [PATCH 05/27] wifi: Fix for DPP VTS test failures on 5GHz only devices Pass one 2.4GHz channel (1) and one 5GHz channel(40) in URI channel-list, so that devices which support only one band can initiate Authentication. Bug: 161331637 Test: VtsHalWifiSupplicantV1_2TargetTest Test: VtsHalWifiSupplicantV1_3TargetTest Change-Id: Ic2677c5f2c2bebe632f823f0472da0a5ae404c0d --- .../vts/functional/supplicant_sta_iface_hidl_test.cpp | 9 ++++++--- .../vts/functional/supplicant_sta_iface_hidl_test.cpp | 6 ++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp index f38dda4caf..7377f780f2 100644 --- a/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp +++ b/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp @@ -302,7 +302,8 @@ TEST_P(SupplicantStaIfaceHidlTest, AddDppPeerUriAndRomveUri) { } hidl_string uri = - "DPP:C:81/1;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj" + "DPP:C:81/1,117/" + "40;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj" "0DAQcDIgAD0edY4X3N//HhMFYsZfMbQJTiNFtNIWF/cIwMB/gzqOM=;;"; uint32_t peer_id = 0; @@ -347,7 +348,8 @@ TEST_P(SupplicantStaIfaceHidlTest, StartDppEnrolleeInitiator) { } hidl_string uri = - "DPP:C:81/1;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj" + "DPP:C:81/1,117/" + "40;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj" "0DAQcDIgAD0edY4X3N//HhMFYsZfMbQJTiNFtNIWF/cIwMB/gzqOM=;;"; uint32_t peer_id = 0; @@ -413,7 +415,8 @@ TEST_P(SupplicantStaIfaceHidlTest, StartDppConfiguratorInitiator) { } hidl_string uri = - "DPP:C:81/1;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj" + "DPP:C:81/1,117/" + "40;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj" "0DAQcDIgAD0edY4X3N//HhMFYsZfMbQJTiNFtNIWF/cIwMB/gzqOM=;;"; uint32_t peer_id = 0; 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 40202980bc..12bd122b14 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 @@ -419,7 +419,8 @@ TEST_P(SupplicantStaIfaceHidlTest, StartDppEnrolleeInitiator) { } hidl_string uri = - "DPP:C:81/1;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj" + "DPP:C:81/1,117/" + "40;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj" "0DAQcDIgAD0edY4X3N//HhMFYsZfMbQJTiNFtNIWF/cIwMB/gzqOM=;;"; uint32_t peer_id = 0; @@ -470,7 +471,8 @@ TEST_P(SupplicantStaIfaceHidlTest, StartDppConfiguratorInitiator) { } hidl_string uri = - "DPP:C:81/1;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj" + "DPP:C:81/1,117/" + "40;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj" "0DAQcDIgAD0edY4X3N//HhMFYsZfMbQJTiNFtNIWF/cIwMB/gzqOM=;;"; uint32_t peer_id = 0; From a46114dfb9d7a7f986855776a4a17577f135e6c7 Mon Sep 17 00:00:00 2001 From: xshu Date: Wed, 22 Jul 2020 17:53:37 -0700 Subject: [PATCH 06/27] Ringbuffer stops logging after wifi toggle Forces ringbuffer updates before writing zipped files to bugreport. Also properly resets the ringbuffer callback when it's deregistered. Bug: 161307741 Test: make vts -j64 && vts-tradefed run commandAndExit vts --module VtsHalWifiV1_0Target Test: manual verification with triggering a bugreport Test: manual verification with wifi toggles Change-Id: I74deffda917054e20cfcf4f0dd90d778626c89d3 Merged-In: I74deffda917054e20cfcf4f0dd90d778626c89d3 (cherry picked from commit 0a0fe51a6aa50a4ade84ad26207fef45ed2c9c3e) --- wifi/1.4/default/wifi_chip.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/wifi/1.4/default/wifi_chip.cpp b/wifi/1.4/default/wifi_chip.cpp index 8747e61992..8cba464757 100644 --- a/wifi/1.4/default/wifi_chip.cpp +++ b/wifi/1.4/default/wifi_chip.cpp @@ -624,6 +624,15 @@ Return WifiChip::getCapabilities_1_3(getCapabilities_cb hidl_status_cb) { Return WifiChip::debug(const hidl_handle& handle, const hidl_vec&) { if (handle != nullptr && handle->numFds >= 1) { + { + std::unique_lock lk(lock_t); + for (const auto& item : ringbuffer_map_) { + forceDumpToDebugRingBufferInternal(item.first); + } + // unique_lock unlocked here + } + usleep(100 * 1000); // sleep for 100 milliseconds to wait for + // ringbuffer updates. int fd = handle->data[0]; if (!writeRingbufferFilesInternal()) { LOG(ERROR) << "Error writing files to flash"; @@ -1120,6 +1129,9 @@ WifiStatus WifiChip::stopLoggingToDebugRingBufferInternal() { legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->deregisterRingBufferCallbackHandler( getFirstActiveWlanIfaceName()); + if (legacy_status == legacy_hal::WIFI_SUCCESS) { + debug_ring_buffer_cb_registered_ = false; + } return createWifiStatusFromLegacyError(legacy_status); } @@ -1335,7 +1347,7 @@ WifiStatus WifiChip::registerDebugRingBufferCallback() { LOG(ERROR) << "Ringname " << name << " not found"; return; } - // unlock + // unique_lock unlocked here } }; legacy_hal::wifi_error legacy_status = @@ -1637,7 +1649,7 @@ bool WifiChip::writeRingbufferFilesInternal() { } } } - // unlock + // unique_lock unlocked here } return true; } From b33e2abbfe38756239badc03a83eb421ff5da0e7 Mon Sep 17 00:00:00 2001 From: Lakshman Annadorai Date: Mon, 27 Jul 2020 10:42:32 -0700 Subject: [PATCH 07/27] Add a native UserHalHelper library. This library contains helper functions to convert the User HAL reponse structs to VehiclePropValues and request VehiclePropValues to HAL structs. Test: Tested with unit tests. Bug: 150409377 Change-Id: I978b39e2f3ee58eb3b154f507c714ca1ba2d1e3b --- automotive/vehicle/2.0/utils/Android.bp | 41 ++ .../vehicle/2.0/utils/UserHalHelper.cpp | 366 ++++++++++ automotive/vehicle/2.0/utils/UserHalHelper.h | 62 ++ .../2.0/utils/tests/UserHalHelper_test.cpp | 666 ++++++++++++++++++ 4 files changed, 1135 insertions(+) create mode 100644 automotive/vehicle/2.0/utils/Android.bp create mode 100644 automotive/vehicle/2.0/utils/UserHalHelper.cpp create mode 100644 automotive/vehicle/2.0/utils/UserHalHelper.h create mode 100644 automotive/vehicle/2.0/utils/tests/UserHalHelper_test.cpp diff --git a/automotive/vehicle/2.0/utils/Android.bp b/automotive/vehicle/2.0/utils/Android.bp new file mode 100644 index 0000000000..e354634165 --- /dev/null +++ b/automotive/vehicle/2.0/utils/Android.bp @@ -0,0 +1,41 @@ +// 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. + +// User HAL helper library. +cc_library_static { + name: "android.hardware.automotive.vehicle@2.0-user-hal-helper-lib", + defaults: ["vhal_v2_0_defaults"], + vendor: true, + host_supported: true, + srcs: [ + "UserHalHelper.cpp", + ], + export_include_dirs: [ + ".", + ], +} + +cc_test { + name: "android.hardware.automotive.vehicle@2.0-utils-unit-tests", + defaults: ["vhal_v2_0_defaults"], + vendor: true, + srcs: [ + "tests/UserHalHelper_test.cpp", + ], + static_libs: [ + "android.hardware.automotive.vehicle@2.0-user-hal-helper-lib", + "libgmock", + ], + test_suites: ["general-tests"], +} diff --git a/automotive/vehicle/2.0/utils/UserHalHelper.cpp b/automotive/vehicle/2.0/utils/UserHalHelper.cpp new file mode 100644 index 0000000000..33b39482da --- /dev/null +++ b/automotive/vehicle/2.0/utils/UserHalHelper.cpp @@ -0,0 +1,366 @@ +/* + * 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. + */ +#define LOG_TAG "UserHalHelper" + +#include "UserHalHelper.h" + +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace V2_0 { + +namespace user_hal_helper { +namespace { + +using android::base::Error; +using android::base::Result; + +static constexpr const char* kSeparator = "||"; +static const size_t kNumFieldsPerUserInfo = 2; +static const size_t kNumFieldsPerSetAssociation = 2; + +template +Result verifyAndCast(int32_t value) { + T castValue = static_cast(value); + const auto iter = hidl_enum_range(); + if (castValue < *iter.begin() || castValue > *std::prev(iter.end())) { + return Error() << "Value " << value << " not in range [" << toString(*iter.begin()) << ", " + << toString(*std::prev(iter.end())) << "]"; + } + for (const auto& v : hidl_enum_range()) { + if (castValue == v) { + return castValue; + } + } + return Error() << "Value " << value << " not in enum values"; +} + +Result verifyPropValue(const VehiclePropValue& propValue, VehicleProperty vehicleProperty, + size_t minInt32Values) { + auto prop = verifyAndCast(propValue.prop); + if (!prop.ok()) { + return Error() << "Invalid vehicle property: " << prop.error(); + } + if (*prop != vehicleProperty) { + return Error() << "Mismatching " << toString(vehicleProperty) << " request, received " + << toString(*prop) << " property"; + } + if (propValue.value.int32Values.size() < minInt32Values) { + return Error() << "Int32Values must have at least " << minInt32Values + << " values, received " << propValue.value.int32Values.size(); + } + return {}; +} + +Result parseUserInfo(const hidl_vec& int32Values, size_t startPos, + UserInfo* userInfo) { + if (int32Values.size() < startPos + kNumFieldsPerUserInfo) { + return Error() << "Int32Values must have at least " << startPos + 2 << " values, received " + << int32Values.size(); + } + userInfo->userId = int32Values[startPos]; + auto userFlags = verifyAndCast(int32Values[startPos + 1]); + if (!userFlags.ok()) { + return Error() << "Invalid user flags: " << userFlags.error(); + } + userInfo->flags = *userFlags; + return {}; +} + +Result parseUsersInfo(const hidl_vec& int32Values, size_t startPos, + UsersInfo* usersInfo) { + if (int32Values.size() < startPos + 3) { + return Error() << "Int32Values must have at least " << startPos + 3 << " values, received " + << int32Values.size(); + } + auto ret = parseUserInfo(int32Values, startPos, &usersInfo->currentUser); + if (!ret.ok()) { + return ret; + } + usersInfo->numberUsers = int32Values[startPos + 2]; + usersInfo->existingUsers.resize(usersInfo->numberUsers); + for (size_t i = 0; i < static_cast(usersInfo->numberUsers); ++i) { + ret = parseUserInfo(int32Values, startPos + 3 + (kNumFieldsPerUserInfo * i), + &usersInfo->existingUsers[i]); + if (!ret.ok()) { + return Error() << "Failed to parse existing user '" << i << "' info: " << ret.error(); + } + } + return {}; +} + +Result parseUserAssociationTypes( + const hidl_vec& int32Values, size_t startPos, size_t numberAssociationTypes, + hidl_vec* associationTypes) { + size_t minInt32Values = startPos + numberAssociationTypes; + if (int32Values.size() < minInt32Values) { + return Error() << "Int32Values must have at least " << minInt32Values + << " values, received " << int32Values.size(); + } + associationTypes->resize(numberAssociationTypes); + for (size_t i = 0; i < static_cast(numberAssociationTypes); ++i) { + size_t pos = startPos + i; + auto type = verifyAndCast(int32Values[pos]); + if (!type.ok()) { + return Error() << "Invalid association type in query '" << i << "': " << type.error(); + } + (*associationTypes)[i] = *type; + } + return {}; +} + +Result parseUserAssociations(const hidl_vec& int32Values, size_t startPos, + size_t numberAssociations, + hidl_vec* associations) { + size_t minInt32Values = startPos + (numberAssociations * kNumFieldsPerSetAssociation); + if (int32Values.size() < minInt32Values) { + return Error() << "Int32Values must have at least " << minInt32Values + << " values, received " << int32Values.size(); + } + associations->resize(numberAssociations); + for (size_t i = 0; i < static_cast(numberAssociations); ++i) { + size_t pos = startPos + (kNumFieldsPerSetAssociation * i); + auto type = verifyAndCast(int32Values[pos]); + if (!type.ok()) { + return Error() << "Invalid association type in request '" << i << "': " << type.error(); + } + (*associations)[i].type = *type; + auto value = verifyAndCast(int32Values[pos + 1]); + if (!value.ok()) { + return Error() << "Invalid association set value in request '" << i + << "': " << value.error(); + } + (*associations)[i].value = *value; + } + return {}; +} + +} // namespace + +Result toInitialUserInfoRequest(const VehiclePropValue& propValue) { + auto ret = verifyPropValue(propValue, VehicleProperty::INITIAL_USER_INFO, 2); + if (!ret.ok()) { + return ret.error(); + } + InitialUserInfoRequest request; + request.requestId = propValue.value.int32Values[0]; + auto requestType = verifyAndCast(propValue.value.int32Values[1]); + if (!requestType.ok()) { + return Error() << "Invalid InitialUserInfoRequestType: " << requestType.error(); + } + request.requestType = *requestType; + ret = parseUsersInfo(propValue.value.int32Values, 2, &request.usersInfo); + if (!ret.ok()) { + return Error() << "Failed to parse users info: " << ret.error(); + } + return request; +} + +Result toSwitchUserRequest(const VehiclePropValue& propValue) { + auto ret = verifyPropValue(propValue, VehicleProperty::SWITCH_USER, 2); + if (!ret.ok()) { + return ret.error(); + } + SwitchUserRequest request; + auto messageType = verifyAndCast(propValue.value.int32Values[1]); + if (!messageType.ok()) { + return Error() << "Invalid SwitchUserMessageType: " << messageType.error(); + } + if (*messageType != SwitchUserMessageType::LEGACY_ANDROID_SWITCH && + *messageType != SwitchUserMessageType::ANDROID_SWITCH && + *messageType != SwitchUserMessageType::ANDROID_POST_SWITCH) { + return Error() << "Invalid " << toString(*messageType) << " from Android System"; + } + request.requestId = propValue.value.int32Values[0]; + request.messageType = *messageType; + ret = parseUserInfo(propValue.value.int32Values, 2, &request.targetUser); + if (!ret.ok()) { + return Error() << "Failed to parse target user info: " << ret.error(); + } + ret = parseUsersInfo(propValue.value.int32Values, 4, &request.usersInfo); + if (!ret.ok()) { + return Error() << "Failed to parse users info: " << ret.error(); + } + return request; +} + +Result toCreateUserRequest(const VehiclePropValue& propValue) { + auto ret = verifyPropValue(propValue, VehicleProperty::CREATE_USER, 1); + if (!ret.ok()) { + return ret.error(); + } + CreateUserRequest request; + request.requestId = propValue.value.int32Values[0]; + ret = parseUserInfo(propValue.value.int32Values, 1, &request.newUserInfo); + if (!ret.ok()) { + return Error() << "Failed to parse new user info: " << ret.error(); + } + request.newUserName = propValue.value.stringValue; + ret = parseUsersInfo(propValue.value.int32Values, 3, &request.usersInfo); + if (!ret.ok()) { + return Error() << "Failed to parse users info: " << ret.error(); + } + return request; +} + +Result toRemoveUserRequest(const VehiclePropValue& propValue) { + auto ret = verifyPropValue(propValue, VehicleProperty::REMOVE_USER, 1); + if (!ret.ok()) { + return ret.error(); + } + RemoveUserRequest request; + request.requestId = propValue.value.int32Values[0]; + ret = parseUserInfo(propValue.value.int32Values, 1, &request.removedUserInfo); + if (!ret.ok()) { + return Error() << "Failed to parse removed user info: " << ret.error(); + } + ret = parseUsersInfo(propValue.value.int32Values, 3, &request.usersInfo); + if (!ret.ok()) { + return Error() << "Failed to parse users info: " << ret.error(); + } + return request; +} + +Result toUserIdentificationGetRequest( + const VehiclePropValue& propValue) { + auto ret = verifyPropValue(propValue, VehicleProperty::USER_IDENTIFICATION_ASSOCIATION, 4); + if (!ret.ok()) { + return ret.error(); + } + UserIdentificationGetRequest request; + request.requestId = propValue.value.int32Values[0]; + ret = parseUserInfo(propValue.value.int32Values, 1, &request.userInfo); + if (!ret.ok()) { + return Error() << "Failed to parse user info: " << ret.error(); + } + request.numberAssociationTypes = propValue.value.int32Values[3]; + ret = parseUserAssociationTypes(propValue.value.int32Values, 4, request.numberAssociationTypes, + &request.associationTypes); + if (!ret.ok()) { + return Error() << "Failed to parse UserIdentificationAssociationType: " << ret.error(); + } + return request; +} + +Result toUserIdentificationSetRequest( + const VehiclePropValue& propValue) { + auto ret = verifyPropValue(propValue, VehicleProperty::USER_IDENTIFICATION_ASSOCIATION, 4); + if (!ret.ok()) { + return ret.error(); + } + UserIdentificationSetRequest request; + request.requestId = propValue.value.int32Values[0]; + ret = parseUserInfo(propValue.value.int32Values, 1, &request.userInfo); + if (!ret.ok()) { + return Error() << "Failed to parse user info: " << ret.error(); + } + request.numberAssociations = propValue.value.int32Values[3]; + ret = parseUserAssociations(propValue.value.int32Values, 4, request.numberAssociations, + &request.associations); + if (!ret.ok()) { + return Error() << "Failed to parse UserIdentificationSetAssociation: " << ret.error(); + } + return request; +} + +std::unique_ptr toVehiclePropValue(const SwitchUserRequest& request) { + if (request.messageType != SwitchUserMessageType::VEHICLE_REQUEST) { + ALOGE("Invalid %s message type %s from HAL", toString(VehicleProperty::SWITCH_USER).c_str(), + toString(request.messageType).c_str()); + return nullptr; + } + auto propValue = std::unique_ptr(new VehiclePropValue()); + propValue->prop = static_cast(VehicleProperty::SWITCH_USER); + propValue->timestamp = elapsedRealtimeNano(); + propValue->value.int32Values.resize(3); + propValue->value.int32Values[0] = static_cast(request.requestId); + propValue->value.int32Values[1] = static_cast(request.messageType); + propValue->value.int32Values[2] = static_cast(request.targetUser.userId); + return propValue; +} + +std::unique_ptr toVehiclePropValue(const InitialUserInfoResponse& response) { + auto propValue = std::unique_ptr(new VehiclePropValue()); + propValue->prop = static_cast(VehicleProperty::INITIAL_USER_INFO); + propValue->timestamp = elapsedRealtimeNano(); + propValue->value.int32Values.resize(4); + propValue->value.int32Values[0] = static_cast(response.requestId); + propValue->value.int32Values[1] = static_cast(response.action); + propValue->value.int32Values[2] = static_cast(response.userToSwitchOrCreate.userId); + propValue->value.int32Values[3] = static_cast(response.userToSwitchOrCreate.flags); + propValue->value.stringValue = std::string(response.userLocales) + std::string(kSeparator) + + std::string(response.userNameToCreate); + return propValue; +} + +std::unique_ptr toVehiclePropValue(const SwitchUserResponse& response) { + auto propValue = std::unique_ptr(new VehiclePropValue()); + propValue->prop = static_cast(VehicleProperty::SWITCH_USER); + propValue->timestamp = elapsedRealtimeNano(); + propValue->value.int32Values.resize(3); + propValue->value.int32Values[0] = static_cast(response.requestId); + propValue->value.int32Values[1] = static_cast(response.messageType); + propValue->value.int32Values[2] = static_cast(response.status); + if (response.status == SwitchUserStatus::FAILURE) { + propValue->value.stringValue = response.errorMessage; + } + return propValue; +} + +std::unique_ptr toVehiclePropValue(const CreateUserResponse& response) { + auto propValue = std::unique_ptr(new VehiclePropValue()); + propValue->prop = static_cast(VehicleProperty::CREATE_USER); + propValue->timestamp = elapsedRealtimeNano(); + propValue->value.int32Values.resize(2); + propValue->value.int32Values[0] = static_cast(response.requestId); + propValue->value.int32Values[1] = static_cast(response.status); + if (response.status == CreateUserStatus::FAILURE) { + propValue->value.stringValue = response.errorMessage; + } + return propValue; +} + +std::unique_ptr toVehiclePropValue(const UserIdentificationResponse& response) { + auto propValue = std::unique_ptr(new VehiclePropValue()); + propValue->prop = static_cast(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION); + propValue->timestamp = elapsedRealtimeNano(); + propValue->value.int32Values.resize(2 + (response.numberAssociation * 2)); + propValue->value.int32Values[0] = static_cast(response.requestId); + propValue->value.int32Values[1] = static_cast(response.numberAssociation); + for (size_t i = 0; i < static_cast(response.numberAssociation); ++i) { + size_t int32ValuesPos = 2 + (2 * i); + propValue->value.int32Values[int32ValuesPos] = + static_cast(response.associations[i].type); + propValue->value.int32Values[int32ValuesPos + 1] = + static_cast(response.associations[i].value); + } + if (!response.errorMessage.empty()) { + propValue->value.stringValue = response.errorMessage; + } + return propValue; +} + +} // namespace user_hal_helper + +} // namespace V2_0 +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/2.0/utils/UserHalHelper.h b/automotive/vehicle/2.0/utils/UserHalHelper.h new file mode 100644 index 0000000000..bee34cf0f6 --- /dev/null +++ b/automotive/vehicle/2.0/utils/UserHalHelper.h @@ -0,0 +1,62 @@ +/* + * 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. + */ + +#ifndef android_hardware_automotive_vehicle_V2_0_impl_UserHalHelper_H_ +#define android_hardware_automotive_vehicle_V2_0_impl_UserHalHelper_H_ + +#include +#include + +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace V2_0 { + +namespace user_hal_helper { + +// Below functions parse VehiclePropValues to the respective User HAL request structs. On success, +// these functions return the User HAL struct. Otherwise, they return the error. +android::base::Result toInitialUserInfoRequest( + const VehiclePropValue& propValue); +android::base::Result toSwitchUserRequest(const VehiclePropValue& propValue); +android::base::Result toCreateUserRequest(const VehiclePropValue& propValue); +android::base::Result toRemoveUserRequest(const VehiclePropValue& propValue); +android::base::Result toUserIdentificationGetRequest( + const VehiclePropValue& propValue); +android::base::Result toUserIdentificationSetRequest( + const VehiclePropValue& propValue); + +// Below functions convert the User HAL structs to VehiclePropValues. On success, these functions +// return the pointer to VehiclePropValue. Otherwise, they return nullptr. +std::unique_ptr toVehiclePropValue(const SwitchUserRequest& request); +std::unique_ptr toVehiclePropValue(const InitialUserInfoResponse& response); +std::unique_ptr toVehiclePropValue(const SwitchUserResponse& response); +std::unique_ptr toVehiclePropValue(const CreateUserResponse& response); +std::unique_ptr toVehiclePropValue(const UserIdentificationResponse& response); + +} // namespace user_hal_helper + +} // namespace V2_0 +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_V2_0_impl_UserHalHelper_H_ diff --git a/automotive/vehicle/2.0/utils/tests/UserHalHelper_test.cpp b/automotive/vehicle/2.0/utils/tests/UserHalHelper_test.cpp new file mode 100644 index 0000000000..7da87a23c8 --- /dev/null +++ b/automotive/vehicle/2.0/utils/tests/UserHalHelper_test.cpp @@ -0,0 +1,666 @@ +/* + * 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 "UserHalHelper.h" + +#include + +#include + +#include "gmock/gmock.h" + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { +namespace V2_0 { + +namespace user_hal_helper { + +namespace { + +using testing::Eq; +using testing::Gt; +using testing::IsNull; +using testing::NotNull; +using testing::Pointee; + +constexpr int32_t INITIAL_USER_INFO = static_cast(VehicleProperty::INITIAL_USER_INFO); +constexpr int32_t SWITCH_USER = static_cast(VehicleProperty::SWITCH_USER); +constexpr int32_t CREATE_USER = static_cast(VehicleProperty::CREATE_USER); +constexpr int32_t REMOVE_USER = static_cast(VehicleProperty::REMOVE_USER); +constexpr int32_t USER_IDENTIFICATION_ASSOCIATION = + static_cast(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION); + +constexpr int32_t FIRST_BOOT_AFTER_OTA = + static_cast(InitialUserInfoRequestType::FIRST_BOOT_AFTER_OTA); +constexpr int32_t LEGACY_ANDROID_SWITCH = + static_cast(SwitchUserMessageType::LEGACY_ANDROID_SWITCH); +constexpr int32_t VEHICLE_REQUEST = static_cast(SwitchUserMessageType::VEHICLE_REQUEST); + +constexpr int32_t GUEST_USER = static_cast(UserFlags::GUEST); +constexpr int32_t NONE_USER = static_cast(UserFlags::NONE); +constexpr int32_t SYSTEM_USER = static_cast(UserFlags::SYSTEM); + +constexpr int32_t USER_ID_ASSOC_KEY_FOB = + static_cast(UserIdentificationAssociationType::KEY_FOB); +constexpr int32_t USER_ID_ASSOC_CUSTOM_1 = + static_cast(UserIdentificationAssociationType::CUSTOM_1); + +constexpr int32_t USER_ID_ASSOC_SET_CURRENT_USER = + static_cast(UserIdentificationAssociationSetValue::ASSOCIATE_CURRENT_USER); +constexpr int32_t USER_ID_ASSOC_UNSET_CURRENT_USER = + static_cast(UserIdentificationAssociationSetValue::DISASSOCIATE_CURRENT_USER); + +constexpr int32_t USER_ID_ASSOC_CURRENT_USER = + static_cast(UserIdentificationAssociationValue::ASSOCIATED_CURRENT_USER); +constexpr int32_t USER_ID_ASSOC_NO_USER = + static_cast(UserIdentificationAssociationValue::NOT_ASSOCIATED_ANY_USER); + +} // namespace + +TEST(UserHalHelperTest, TestToInitialUserInfoRequest) { + VehiclePropValue propValue{ + .prop = INITIAL_USER_INFO, + .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0, SYSTEM_USER, + 10, NONE_USER}}, + }; + InitialUserInfoRequest expected{ + .requestId = 23, + .requestType = InitialUserInfoRequestType::FIRST_BOOT_AFTER_OTA, + .usersInfo = {{10, UserFlags::NONE}, + 2, + {{0, UserFlags::SYSTEM}, {10, UserFlags::NONE}}}, + }; + + auto actual = toInitialUserInfoRequest(propValue); + + ASSERT_TRUE(actual.ok()) << actual.error().message(); + EXPECT_THAT(actual.value(), Eq(expected)); +} + +TEST(UserHalHelperTest, TestFailsToInitialUserInfoRequestWithMismatchingPropType) { + VehiclePropValue propValue{ + .prop = INT32_MAX, + .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0, SYSTEM_USER, + 10, NONE_USER}}, + }; + + auto actual = toInitialUserInfoRequest(propValue); + + EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type"; +} + +TEST(UserHalHelperTest, TestFailsToInitialUserInfoRequestWithInvalidRequestType) { + VehiclePropValue propValue{ + .prop = INITIAL_USER_INFO, + .value = {.int32Values = {23, INT32_MAX, 10, NONE_USER, 2, 0, SYSTEM_USER, 10, + NONE_USER}}, + }; + + auto actual = toInitialUserInfoRequest(propValue); + + EXPECT_FALSE(actual.ok()) << "No error returned on invalid request type"; +} + +TEST(UserHalHelperTest, TestFailsToInitialUserInfoRequestWithInvalidUserFlag) { + VehiclePropValue propValue{ + .prop = INITIAL_USER_INFO, + .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0, SYSTEM_USER, + 10, INT32_MAX}}, + }; + + auto actual = toInitialUserInfoRequest(propValue); + + EXPECT_FALSE(actual.ok()) << "No error returned on invalid user flags"; +} + +TEST(UserHalHelperTest, TestFailsToInitialUserInfoRequestWithIncompleteUsersInfo) { + VehiclePropValue propValueMissingSecondUserInfo{ + .prop = INITIAL_USER_INFO, + .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, 10, NONE_USER, 2, 0, + SYSTEM_USER /*Missing 2nd UserInfo*/}}, + }; + + auto actual = toInitialUserInfoRequest(propValueMissingSecondUserInfo); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing second user info"; + + VehiclePropValue propValueMissingUsersInfo{ + .prop = INITIAL_USER_INFO, + .value = {.int32Values = {23, FIRST_BOOT_AFTER_OTA, /*Missing UsersInfo*/}}, + }; + + actual = toInitialUserInfoRequest(propValueMissingUsersInfo); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing users info"; +} + +TEST(UserHalHelperTest, TestToSwitchUserRequest) { + VehiclePropValue propValue{ + .prop = SWITCH_USER, + .value = {.int32Values = {23, LEGACY_ANDROID_SWITCH, 0, SYSTEM_USER, 10, NONE_USER, 2, + 0, SYSTEM_USER, 10, NONE_USER}}, + }; + SwitchUserRequest expected{ + .requestId = 23, + .messageType = SwitchUserMessageType::LEGACY_ANDROID_SWITCH, + .targetUser = {0, UserFlags::SYSTEM}, + .usersInfo = {{10, UserFlags::NONE}, + 2, + {{0, UserFlags::SYSTEM}, {10, UserFlags::NONE}}}, + }; + + auto actual = toSwitchUserRequest(propValue); + + ASSERT_TRUE(actual.ok()) << actual.error().message(); + EXPECT_THAT(actual.value(), Eq(expected)); +} + +TEST(UserHalHelperTest, TestFailsToSwitchUserRequestWithMismatchingPropType) { + VehiclePropValue propValue{ + .prop = INITIAL_USER_INFO, + .value = {.int32Values = {23, LEGACY_ANDROID_SWITCH, 0, SYSTEM_USER, 10, NONE_USER, 2, + 0, SYSTEM_USER, 10, NONE_USER}}, + }; + + auto actual = toSwitchUserRequest(propValue); + + EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type"; +} + +TEST(UserHalHelperTest, TestFailsToSwitchUserRequestWithInvalidMessageType) { + VehiclePropValue propValueIncompatibleMessageType{ + .prop = SWITCH_USER, + .value = {.int32Values = {23, VEHICLE_REQUEST, 0, SYSTEM_USER, 10, NONE_USER, 2, 0, + SYSTEM_USER, 10, NONE_USER}}, + }; + + auto actual = toSwitchUserRequest(propValueIncompatibleMessageType); + + EXPECT_FALSE(actual.ok()) << "No error returned on incompatible message type"; + + VehiclePropValue propValueInvalidMessageType{ + .prop = SWITCH_USER, + .value = {.int32Values = {23, INT32_MAX, 0, SYSTEM_USER, 10, NONE_USER, 2, 0, + SYSTEM_USER, 10, NONE_USER}}, + }; + + actual = toSwitchUserRequest(propValueInvalidMessageType); + + EXPECT_FALSE(actual.ok()) << "No error returned on invalid message type"; +} + +TEST(UserHalHelperTest, TestFailsToSwitchUserRequestWithIncompleteUsersInfo) { + VehiclePropValue propValueMissingSecondUserInfo{ + .prop = SWITCH_USER, + .value = {.int32Values = {23, LEGACY_ANDROID_SWITCH, 0, SYSTEM_USER, 10, NONE_USER, 2, + 0, SYSTEM_USER, + /*Missing 2nd UserInfo*/}}, + }; + + auto actual = toSwitchUserRequest(propValueMissingSecondUserInfo); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing second user info"; + + VehiclePropValue propValueMissingUsersInfo{ + .prop = SWITCH_USER, + .value = {.int32Values = {23, LEGACY_ANDROID_SWITCH, 0, SYSTEM_USER, + /*Missing UsersInfo*/}}, + }; + + actual = toSwitchUserRequest(propValueMissingUsersInfo); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing users info"; + + VehiclePropValue propValueMissingTargetUser{ + .prop = SWITCH_USER, + .value = {.int32Values = {23, LEGACY_ANDROID_SWITCH, /*Missing target UserInfo*/}}, + }; + + actual = toSwitchUserRequest(propValueMissingTargetUser); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing target user info"; +} + +TEST(UserHalHelperTest, TestToCreateUserRequest) { + VehiclePropValue propValue{ + .prop = CREATE_USER, + .value = {.int32Values = {23, 11, GUEST_USER, 10, NONE_USER, 2, 0, SYSTEM_USER, 10, + NONE_USER}, + .stringValue = "Guest11"}, + }; + CreateUserRequest expected{ + .requestId = 23, + .newUserInfo = {11, UserFlags::GUEST}, + .newUserName = "Guest11", + .usersInfo = {{10, UserFlags::NONE}, + 2, + {{0, UserFlags::SYSTEM}, {10, UserFlags::NONE}}}, + }; + + auto actual = toCreateUserRequest(propValue); + + ASSERT_TRUE(actual.ok()) << actual.error().message(); + EXPECT_THAT(actual.value(), Eq(expected)); +} + +TEST(UserHalHelperTest, TestFailsToCreateUserRequestWithMismatchingPropType) { + VehiclePropValue propValue{ + .prop = INITIAL_USER_INFO, + .value = {.int32Values = {23, 11, GUEST_USER, 10, NONE_USER, 2, 0, SYSTEM_USER, 10, + NONE_USER}, + .stringValue = "Guest11"}, + }; + + auto actual = toCreateUserRequest(propValue); + + EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type"; +} + +TEST(UserHalHelperTest, TestFailsToCreateUserRequestWithIncompleteUsersInfo) { + VehiclePropValue propValueMissingSecondUserInfo{ + .prop = CREATE_USER, + .value = {.int32Values = {23, 11, GUEST_USER, 10, NONE_USER, 2, 0, + SYSTEM_USER /*Missing 2nd UserInfo*/}, + .stringValue = "Guest11"}, + }; + + auto actual = toCreateUserRequest(propValueMissingSecondUserInfo); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing second user info"; + + VehiclePropValue propValueMissingUsersInfo{ + .prop = CREATE_USER, + .value = {.int32Values = {23, 11, GUEST_USER, /*Missing UsersInfo*/}, + .stringValue = "Guest11"}, + }; + + actual = toCreateUserRequest(propValueMissingUsersInfo); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing users info"; + + VehiclePropValue propValueMissingCreateUserInfo{ + .prop = CREATE_USER, + .value = {.int32Values = {23, /*Missing create UserInfo*/}, .stringValue = "Guest11"}, + }; + + actual = toCreateUserRequest(propValueMissingCreateUserInfo); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing create user info"; +} + +TEST(UserHalHelperTest, TestToRemoveUserRequest) { + VehiclePropValue propValue{ + .prop = REMOVE_USER, + .value = {.int32Values = {23, 10, NONE_USER, 10, NONE_USER, 2, 0, SYSTEM_USER, 10, + NONE_USER}}, + }; + RemoveUserRequest expected{ + .requestId = 23, + .removedUserInfo = {10, UserFlags::NONE}, + .usersInfo = {{10, UserFlags::NONE}, + 2, + {{0, UserFlags::SYSTEM}, {10, UserFlags::NONE}}}, + }; + + auto actual = toRemoveUserRequest(propValue); + + ASSERT_TRUE(actual.ok()) << actual.error().message(); + EXPECT_THAT(actual.value(), Eq(expected)); +} + +TEST(UserHalHelperTest, TestFailsToRemoveUserRequestWithMismatchingPropType) { + VehiclePropValue propValue{ + .prop = INITIAL_USER_INFO, + .value = {.int32Values = {23, 10, NONE_USER, 10, NONE_USER, 2, 0, SYSTEM_USER, 10, + NONE_USER}}, + }; + + auto actual = toRemoveUserRequest(propValue); + + EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type"; +} + +TEST(UserHalHelperTest, TestFailsToRemoveUserRequestWithIncompleteUsersInfo) { + VehiclePropValue propValueMissingSecondUserInfo{ + .prop = REMOVE_USER, + .value = {.int32Values = {23, 10, NONE_USER, 10, NONE_USER, 2, 0, + SYSTEM_USER /*Missing 2nd UserInfo*/}}, + }; + + auto actual = toRemoveUserRequest(propValueMissingSecondUserInfo); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing second user info"; + + VehiclePropValue propValueMissingUsersInfo{ + .prop = REMOVE_USER, + .value = {.int32Values = {23, 10, NONE_USER, /*Missing UsersInfo*/}}, + }; + + actual = toRemoveUserRequest(propValueMissingUsersInfo); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing users info"; + + VehiclePropValue propValueMissingRemoveUserInfo{ + .prop = REMOVE_USER, + .value = {.int32Values = {23, /*Missing remove UserInfo*/}}, + }; + + actual = toRemoveUserRequest(propValueMissingRemoveUserInfo); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing remove user info"; +} + +TEST(UserHalHelperTest, TestFailsToUserIdentificationGetRequest) { + VehiclePropValue propValue{ + .prop = USER_IDENTIFICATION_ASSOCIATION, + .value = {.int32Values = {23, 10, NONE_USER, 2, USER_ID_ASSOC_KEY_FOB, + USER_ID_ASSOC_CUSTOM_1}}, + }; + UserIdentificationGetRequest expected{ + .requestId = 23, + .userInfo = {10, UserFlags::NONE}, + .numberAssociationTypes = 2, + .associationTypes = {UserIdentificationAssociationType::KEY_FOB, + UserIdentificationAssociationType::CUSTOM_1}, + }; + + auto actual = toUserIdentificationGetRequest(propValue); + + ASSERT_TRUE(actual.ok()) << actual.error().message(); + EXPECT_THAT(actual.value(), Eq(expected)); +} + +TEST(UserHalHelperTest, TestFailsToUserIdentificationGetRequestWithMismatchingPropType) { + VehiclePropValue propValue{ + .prop = INITIAL_USER_INFO, + .value = {.int32Values = {23, 10, NONE_USER, 2, USER_ID_ASSOC_KEY_FOB, + USER_ID_ASSOC_CUSTOM_1}}, + }; + + auto actual = toUserIdentificationGetRequest(propValue); + + EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type"; +} + +TEST(UserHalHelperTest, TestFailsToUserIdentificationGetRequestWithInvalidAssociationTypes) { + VehiclePropValue propValue{ + .prop = USER_IDENTIFICATION_ASSOCIATION, + .value = {.int32Values = {23, 10, NONE_USER, 1, INT32_MAX}}, + }; + + auto actual = toUserIdentificationGetRequest(propValue); + + EXPECT_FALSE(actual.ok()) << "No error returned on invalid association type"; +} + +TEST(UserHalHelperTest, TestFailsToUserIdentificationGetRequestWithIncompleteAssociationTypes) { + VehiclePropValue propValueMissingSecondAssociationType{ + .prop = USER_IDENTIFICATION_ASSOCIATION, + .value = {.int32Values = {23, 10, NONE_USER, 2, + USER_ID_ASSOC_KEY_FOB /*Missing 2nd association type*/}}, + }; + + auto actual = toUserIdentificationGetRequest(propValueMissingSecondAssociationType); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing second association type"; + + VehiclePropValue propValueMissingNumberAssociationTypes{ + .prop = USER_IDENTIFICATION_ASSOCIATION, + .value = {.int32Values = {23, 10, NONE_USER, /*Missing number association types*/}}, + }; + + actual = toUserIdentificationGetRequest(propValueMissingNumberAssociationTypes); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing number association types"; +} + +TEST(UserHalHelperTest, TestFailsToUserIdentificationGetRequestWithMissingUserInfo) { + VehiclePropValue propValue{ + .prop = USER_IDENTIFICATION_ASSOCIATION, + .value = {.int32Values = {23, /*Missing user info*/}}, + }; + + auto actual = toUserIdentificationGetRequest(propValue); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing UserInfo"; +} + +TEST(UserHalHelperTest, TestToUserIdentificationSetRequest) { + VehiclePropValue propValue{ + .prop = USER_IDENTIFICATION_ASSOCIATION, + .value = {.int32Values = {23, 10, NONE_USER, 2, USER_ID_ASSOC_KEY_FOB, + USER_ID_ASSOC_SET_CURRENT_USER, USER_ID_ASSOC_CUSTOM_1, + USER_ID_ASSOC_UNSET_CURRENT_USER}}, + }; + UserIdentificationSetRequest expected{ + .requestId = 23, + .userInfo = {10, UserFlags::NONE}, + .numberAssociations = 2, + .associations = {{UserIdentificationAssociationType::KEY_FOB, + UserIdentificationAssociationSetValue::ASSOCIATE_CURRENT_USER}, + {UserIdentificationAssociationType::CUSTOM_1, + UserIdentificationAssociationSetValue::DISASSOCIATE_CURRENT_USER}}, + }; + + auto actual = toUserIdentificationSetRequest(propValue); + + ASSERT_TRUE(actual.ok()) << actual.error().message(); + EXPECT_THAT(actual.value(), Eq(expected)); +} + +TEST(UserHalHelperTest, TestFailsToUserIdentificationSetRequestWithMismatchingPropType) { + VehiclePropValue propValue{ + .prop = INITIAL_USER_INFO, + .value = {.int32Values = {23, 10, NONE_USER, 2, USER_ID_ASSOC_KEY_FOB, + USER_ID_ASSOC_SET_CURRENT_USER, USER_ID_ASSOC_CUSTOM_1, + USER_ID_ASSOC_UNSET_CURRENT_USER}}, + }; + + auto actual = toUserIdentificationSetRequest(propValue); + + EXPECT_FALSE(actual.ok()) << "No error returned on mismatching property type"; +} + +TEST(UserHalHelperTest, TestFailsToUserIdentificationSetRequestWithInvalidAssociations) { + VehiclePropValue propValueInvalidAssociationType{ + .prop = USER_IDENTIFICATION_ASSOCIATION, + .value = {.int32Values = {23, 10, NONE_USER, 1, INT32_MAX, + USER_ID_ASSOC_SET_CURRENT_USER}}, + }; + + auto actual = toUserIdentificationSetRequest(propValueInvalidAssociationType); + + EXPECT_FALSE(actual.ok()) << "No error returned on invalid association type"; + + VehiclePropValue propValueInvalidAssociationValue{ + .prop = USER_IDENTIFICATION_ASSOCIATION, + .value = {.int32Values = {23, 10, NONE_USER, USER_ID_ASSOC_KEY_FOB, INT32_MAX}}, + }; + + actual = toUserIdentificationSetRequest(propValueInvalidAssociationValue); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing number association types"; +} + +TEST(UserHalHelperTest, TestFailsToUserIdentificationSetRequestWithIncompleteAssociations) { + VehiclePropValue propValueMissingSecondAssociationType{ + .prop = USER_IDENTIFICATION_ASSOCIATION, + .value = {.int32Values = {23, 10, NONE_USER, 2, USER_ID_ASSOC_KEY_FOB, + USER_ID_ASSOC_SET_CURRENT_USER, + /*Missing 2nd association*/}}, + }; + + auto actual = toUserIdentificationSetRequest(propValueMissingSecondAssociationType); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing second association type"; + + VehiclePropValue propValueMissingNumberAssociationTypes{ + .prop = USER_IDENTIFICATION_ASSOCIATION, + .value = {.int32Values = {23, 10, NONE_USER, /*Missing number associations*/}}, + }; + + actual = toUserIdentificationSetRequest(propValueMissingNumberAssociationTypes); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing number association types"; +} + +TEST(UserHalHelperTest, TestFailsToUserIdentificationSetRequestWithMissingUserInfo) { + VehiclePropValue propValue{ + .prop = USER_IDENTIFICATION_ASSOCIATION, + .value = {.int32Values = {23, /*Missing user info*/}}, + }; + + auto actual = toUserIdentificationSetRequest(propValue); + + EXPECT_FALSE(actual.ok()) << "No error returned on missing UserInfo"; +} + +TEST(UserHalHelperTest, TestSwitchUserRequestToVehiclePropValue) { + SwitchUserRequest request{ + .requestId = 23, + .messageType = SwitchUserMessageType::VEHICLE_REQUEST, + .targetUser = {11, UserFlags::GUEST}, + }; + VehiclePropValue expected{ + .prop = SWITCH_USER, + .value = {.int32Values = {23, + static_cast(SwitchUserMessageType::VEHICLE_REQUEST), + 11}}, + }; + + auto actual = toVehiclePropValue(request); + + ASSERT_THAT(actual, NotNull()); + EXPECT_THAT(actual->timestamp, Gt(0)); + // Don't rely on real timestamp in tests as the expected and actual objects won't have the same + // timestamps. Thus remove the timestamps before comparing them. + actual->timestamp = 0; + EXPECT_THAT(actual, Pointee(Eq(expected))); +} + +TEST(UserHalHelperTest, TestFailsSwitchUserRequestToVehiclePropValueWithIncompatibleMessageType) { + SwitchUserRequest request{ + .requestId = 23, + .messageType = SwitchUserMessageType::VEHICLE_RESPONSE, + .targetUser = {11, UserFlags::GUEST}, + }; + + auto actual = toVehiclePropValue(request); + + EXPECT_THAT(actual, IsNull()); +} + +TEST(UserHalHelperTest, TestInitialUserInfoResponseToVehiclePropValue) { + InitialUserInfoResponse response{ + .requestId = 23, + .action = InitialUserInfoResponseAction::CREATE, + .userToSwitchOrCreate = {11, UserFlags::GUEST}, + .userLocales = "en-US,pt-BR", + .userNameToCreate = "Owner", + }; + VehiclePropValue expected{ + .prop = INITIAL_USER_INFO, + .value = {.int32Values = {23, + static_cast(InitialUserInfoResponseAction::CREATE), + 11, GUEST_USER}, + .stringValue = "en-US,pt-BR||Owner"}, + }; + + auto actual = toVehiclePropValue(response); + + ASSERT_THAT(actual, NotNull()); + EXPECT_THAT(actual->timestamp, Gt(0)); + actual->timestamp = 0; + EXPECT_THAT(actual, Pointee(Eq(expected))); +} + +TEST(UserHalHelperTest, TestSwitchUserResponseToVehiclePropValue) { + SwitchUserResponse response{ + .requestId = 23, + .messageType = SwitchUserMessageType::VEHICLE_RESPONSE, + .status = SwitchUserStatus::FAILURE, + .errorMessage = "random error", + }; + VehiclePropValue expected{ + .prop = SWITCH_USER, + .value = {.int32Values = {23, + static_cast(SwitchUserMessageType::VEHICLE_RESPONSE), + static_cast(SwitchUserStatus::FAILURE)}, + .stringValue = "random error"}, + }; + + auto actual = toVehiclePropValue(response); + + ASSERT_THAT(actual, NotNull()); + EXPECT_THAT(actual->timestamp, Gt(0)); + actual->timestamp = 0; + EXPECT_THAT(actual, Pointee(Eq(expected))); +} + +TEST(UserHalHelperTest, TestCreateUserResponseToVehiclePropValue) { + CreateUserResponse response{ + .requestId = 23, + .status = CreateUserStatus::FAILURE, + .errorMessage = "random error", + }; + VehiclePropValue expected{ + .prop = CREATE_USER, + .value = {.int32Values = {23, static_cast(CreateUserStatus::FAILURE)}, + .stringValue = "random error"}, + }; + + auto actual = toVehiclePropValue(response); + + ASSERT_THAT(actual, NotNull()); + EXPECT_THAT(actual->timestamp, Gt(0)); + actual->timestamp = 0; + EXPECT_THAT(actual, Pointee(Eq(expected))); +} + +TEST(UserHalHelperTest, TestUserIdentificationResponseToVehiclePropValue) { + UserIdentificationResponse response{ + .requestId = 23, + .numberAssociation = 2, + .associations = {{UserIdentificationAssociationType::KEY_FOB, + UserIdentificationAssociationValue::ASSOCIATED_CURRENT_USER}, + {UserIdentificationAssociationType::CUSTOM_1, + UserIdentificationAssociationValue::NOT_ASSOCIATED_ANY_USER}}, + .errorMessage = "random error", + }; + VehiclePropValue expected{ + .prop = USER_IDENTIFICATION_ASSOCIATION, + .value = {.int32Values = {23, 2, USER_ID_ASSOC_KEY_FOB, USER_ID_ASSOC_CURRENT_USER, + USER_ID_ASSOC_CUSTOM_1, USER_ID_ASSOC_NO_USER}, + .stringValue = "random error"}, + }; + + auto actual = toVehiclePropValue(response); + + ASSERT_THAT(actual, NotNull()); + EXPECT_THAT(actual->timestamp, Gt(0)); + actual->timestamp = 0; + EXPECT_THAT(actual, Pointee(Eq(expected))); +} + +} // namespace user_hal_helper + +} // namespace V2_0 +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android From 1e7339550471387879cc683af4144a275c844328 Mon Sep 17 00:00:00 2001 From: Max Bires Date: Tue, 21 Jul 2020 01:45:36 -0700 Subject: [PATCH 08/27] Fixing a test in DeviceUniqueAttestationTest The EC key check for generating a device unique attestation from a non-strongbox keymaster instance left out the TAG_DEVICE_UNIQUE_ATTESTATION_TAG, so the test should fail since the attestation should succeed. This commit adds the tag into the parameters passed into attestation. Fixes: 161327512 Test: m VtsHalKeymasterV4_1TargetTest Change-Id: I75a41a75b298c91ec41fa411f8a486ac347cf748 --- keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp b/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp index 495de0f97d..f74d36c290 100644 --- a/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp +++ b/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp @@ -212,6 +212,7 @@ TEST_P(DeviceUniqueAttestationTest, NonStrongBoxOnly) { EXPECT_EQ(ErrorCode::UNIMPLEMENTED, convert(AttestKey( AuthorizationSetBuilder() + .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION) .Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge")) .Authorization(TAG_ATTESTATION_APPLICATION_ID, HidlBuf("foo")), &cert_chain))); From 2595661c0d8e088b7d9f19dfad39b0b13ac169df Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Tue, 11 Aug 2020 10:31:59 -0700 Subject: [PATCH 09/27] supplicant(vts): Stop framework after querying package manager Bug: 161951052 Test: atest VtsHalWifiSupplicantV1_0TargetTest VtsHalWifiSupplicantV1_1TargetTest VtsHalWifiSupplicantV1_2TargetTest VtsHalWifiSupplicantV1_3TargetTest Change-Id: Ic5f57ce77cae7c8f3e233065923877943460edee --- .../1.0/vts/functional/supplicant_hidl_test.cpp | 12 +++++++++--- .../functional/supplicant_p2p_iface_hidl_test.cpp | 12 +++++++++--- .../functional/supplicant_sta_iface_hidl_test.cpp | 12 +++++++++--- .../functional/supplicant_sta_network_hidl_test.cpp | 12 +++++++++--- .../vts/functional/supplicant_hidl_test_utils_1_1.h | 4 ++++ .../vts/functional/supplicant_hidl_test_utils_1_2.h | 4 ++++ .../functional/supplicant_p2p_iface_hidl_test.cpp | 2 +- .../functional/supplicant_sta_iface_hidl_test.cpp | 4 ++++ .../functional/supplicant_sta_network_hidl_test.cpp | 4 ++++ 9 files changed, 53 insertions(+), 13 deletions(-) diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test.cpp index 4f25465d79..47f0394db1 100644 --- a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test.cpp +++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test.cpp @@ -40,16 +40,22 @@ class SupplicantHidlTest virtual void SetUp() override { wifi_instance_name_ = std::get<0>(GetParam()); supplicant_instance_name_ = std::get<1>(GetParam()); + isP2pOn_ = + testing::deviceSupportsFeature("android.hardware.wifi.direct"); + // Stop Framework + std::system("/system/bin/stop"); stopSupplicant(wifi_instance_name_); startSupplicantAndWaitForHidlService(wifi_instance_name_, supplicant_instance_name_); - isP2pOn_ = - testing::deviceSupportsFeature("android.hardware.wifi.direct"); supplicant_ = getSupplicant(supplicant_instance_name_, isP2pOn_); ASSERT_NE(supplicant_.get(), nullptr); } - virtual void TearDown() override { stopSupplicant(wifi_instance_name_); } + virtual void TearDown() override { + stopSupplicant(wifi_instance_name_); + // Start Framework + std::system("/system/bin/start"); + } protected: // ISupplicant object used for all tests in this fixture. diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp index 8d6f38d8eb..c333c4f859 100644 --- a/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp +++ b/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp @@ -77,11 +77,13 @@ class SupplicantP2pIfaceHidlTest virtual void SetUp() override { wifi_instance_name_ = std::get<0>(GetParam()); supplicant_instance_name_ = std::get<1>(GetParam()); + isP2pOn_ = + testing::deviceSupportsFeature("android.hardware.wifi.direct"); + // Stop Framework + std::system("/system/bin/stop"); stopSupplicant(wifi_instance_name_); startSupplicantAndWaitForHidlService(wifi_instance_name_, supplicant_instance_name_); - isP2pOn_ = - testing::deviceSupportsFeature("android.hardware.wifi.direct"); supplicant_ = getSupplicant(supplicant_instance_name_, isP2pOn_); EXPECT_TRUE(turnOnExcessiveLogging(supplicant_)); p2p_iface_ = getSupplicantP2pIface(supplicant_); @@ -91,7 +93,11 @@ class SupplicantP2pIfaceHidlTest memcpy(peer_mac_addr_.data(), kTestPeerMacAddr, peer_mac_addr_.size()); } - virtual void TearDown() override { stopSupplicant(wifi_instance_name_); } + virtual void TearDown() override { + stopSupplicant(wifi_instance_name_); + // Start Framework + std::system("/system/bin/start"); + } protected: bool isP2pOn_ = false; diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_sta_iface_hidl_test.cpp index 089b3cd002..ff287541f8 100644 --- a/wifi/supplicant/1.0/vts/functional/supplicant_sta_iface_hidl_test.cpp +++ b/wifi/supplicant/1.0/vts/functional/supplicant_sta_iface_hidl_test.cpp @@ -72,11 +72,13 @@ class SupplicantStaIfaceHidlTest virtual void SetUp() override { wifi_instance_name_ = std::get<0>(GetParam()); supplicant_instance_name_ = std::get<1>(GetParam()); + isP2pOn_ = + testing::deviceSupportsFeature("android.hardware.wifi.direct"); + // Stop Framework + std::system("/system/bin/stop"); stopSupplicant(wifi_instance_name_); startSupplicantAndWaitForHidlService(wifi_instance_name_, supplicant_instance_name_); - isP2pOn_ = - testing::deviceSupportsFeature("android.hardware.wifi.direct"); supplicant_ = getSupplicant(supplicant_instance_name_, isP2pOn_); EXPECT_TRUE(turnOnExcessiveLogging(supplicant_)); sta_iface_ = getSupplicantStaIface(supplicant_); @@ -85,7 +87,11 @@ class SupplicantStaIfaceHidlTest memcpy(mac_addr_.data(), kTestMacAddr, mac_addr_.size()); } - virtual void TearDown() override { stopSupplicant(wifi_instance_name_); } + virtual void TearDown() override { + stopSupplicant(wifi_instance_name_); + // Start Framework + std::system("/system/bin/start"); + } protected: bool isP2pOn_ = false; diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_sta_network_hidl_test.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_sta_network_hidl_test.cpp index 5467e02799..295ebfb808 100644 --- a/wifi/supplicant/1.0/vts/functional/supplicant_sta_network_hidl_test.cpp +++ b/wifi/supplicant/1.0/vts/functional/supplicant_sta_network_hidl_test.cpp @@ -85,11 +85,13 @@ class SupplicantStaNetworkHidlTest virtual void SetUp() override { wifi_instance_name_ = std::get<0>(GetParam()); supplicant_instance_name_ = std::get<1>(GetParam()); + isP2pOn_ = + testing::deviceSupportsFeature("android.hardware.wifi.direct"); + // Stop Framework + std::system("/system/bin/stop"); stopSupplicant(wifi_instance_name_); startSupplicantAndWaitForHidlService(wifi_instance_name_, supplicant_instance_name_); - isP2pOn_ = - testing::deviceSupportsFeature("android.hardware.wifi.direct"); supplicant_ = getSupplicant(supplicant_instance_name_, isP2pOn_); EXPECT_TRUE(turnOnExcessiveLogging(supplicant_)); sta_network_ = createSupplicantStaNetwork(supplicant_); @@ -103,7 +105,11 @@ class SupplicantStaNetworkHidlTest ssid_.assign(kTestSsidStr, kTestSsidStr + strlen(kTestSsidStr)); } - virtual void TearDown() override { stopSupplicant(wifi_instance_name_); } + virtual void TearDown() override { + stopSupplicant(wifi_instance_name_); + // Start Framework + std::system("/system/bin/start"); + } protected: void removeNetwork() { diff --git a/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.h b/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.h index 3629882f94..2104794770 100644 --- a/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.h +++ b/wifi/supplicant/1.1/vts/functional/supplicant_hidl_test_utils_1_1.h @@ -44,6 +44,8 @@ class SupplicantHidlTestBase supplicant_v1_1_instance_name_ = std::get<1>(GetParam()); isP2pOn_ = testing::deviceSupportsFeature("android.hardware.wifi.direct"); + // Stop Framework + std::system("/system/bin/stop"); stopSupplicant(wifi_v1_0_instance_name_); startSupplicantAndWaitForHidlService(wifi_v1_0_instance_name_, supplicant_v1_1_instance_name_); @@ -54,6 +56,8 @@ class SupplicantHidlTestBase virtual void TearDown() override { stopSupplicant(wifi_v1_0_instance_name_); + // Start Framework + std::system("/system/bin/start"); } protected: diff --git a/wifi/supplicant/1.2/vts/functional/supplicant_hidl_test_utils_1_2.h b/wifi/supplicant/1.2/vts/functional/supplicant_hidl_test_utils_1_2.h index 5ecfdd48ef..2a432d075c 100644 --- a/wifi/supplicant/1.2/vts/functional/supplicant_hidl_test_utils_1_2.h +++ b/wifi/supplicant/1.2/vts/functional/supplicant_hidl_test_utils_1_2.h @@ -50,6 +50,8 @@ class SupplicantHidlTestBase supplicant_v1_2_instance_name_ = std::get<1>(GetParam()); isP2pOn_ = testing::deviceSupportsFeature("android.hardware.wifi.direct"); + // Stop Framework + std::system("/system/bin/stop"); stopSupplicant(wifi_v1_0_instance_name_); startSupplicantAndWaitForHidlService(wifi_v1_0_instance_name_, supplicant_v1_2_instance_name_); @@ -61,6 +63,8 @@ class SupplicantHidlTestBase virtual void TearDown() override { stopSupplicant(wifi_v1_0_instance_name_); + // Start Framework + std::system("/system/bin/start"); } protected: diff --git a/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp b/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp index 1eb8eea4ea..cab160bc1f 100644 --- a/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp +++ b/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp @@ -43,7 +43,7 @@ class SupplicantP2pIfaceHidlTest : public SupplicantHidlTestBase { virtual void SetUp() override { SupplicantHidlTestBase::SetUp(); EXPECT_TRUE(turnOnExcessiveLogging(supplicant_)); - if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct")) { + if (!isP2pOn_) { GTEST_SKIP() << "Wi-Fi Direct is not supported, skip this test."; } p2p_iface_ = getSupplicantP2pIface_1_2(supplicant_); 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 12bd122b14..011a955983 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 @@ -63,6 +63,8 @@ class SupplicantStaIfaceHidlTest supplicant_v1_3_instance_name_ = std::get<1>(GetParam()); isP2pOn_ = testing::deviceSupportsFeature("android.hardware.wifi.direct"); + // Stop Framework + std::system("/system/bin/stop"); stopSupplicant(wifi_v1_0_instance_name_); startSupplicantAndWaitForHidlService(wifi_v1_0_instance_name_, @@ -76,6 +78,8 @@ class SupplicantStaIfaceHidlTest virtual void TearDown() override { stopSupplicant(wifi_v1_0_instance_name_); + // Start Framework + std::system("/system/bin/start"); } int64_t pmkCacheExpirationTimeInSec; 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 25091a5b92..5f60746845 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 @@ -51,6 +51,8 @@ class SupplicantStaNetworkHidlTest supplicant_v1_3_instance_name_ = std::get<1>(GetParam()); isP2pOn_ = testing::deviceSupportsFeature("android.hardware.wifi.direct"); + // Stop Framework + std::system("/system/bin/stop"); stopSupplicant(wifi_v1_0_instance_name_); startSupplicantAndWaitForHidlService(wifi_v1_0_instance_name_, @@ -66,6 +68,8 @@ class SupplicantStaNetworkHidlTest virtual void TearDown() override { stopSupplicant(wifi_v1_0_instance_name_); + // Start Framework + std::system("/system/bin/start"); } protected: From 55a4f59fb8ca7fb83b3ca14d560c30e2c5239a16 Mon Sep 17 00:00:00 2001 From: Anthony Stange Date: Tue, 11 Aug 2020 12:46:31 -0400 Subject: [PATCH 10/27] Fix double release of ScopedWakelock Today, when a ScopedWakelock is moved, the default move constructor doesn't unlock the old wakelock instance. This results in the moved ScopedWakelock instance decrementing the wakelock ref count which leaves the multi-HAL out of sync from the sensor service. Fix this by adding a custom move constructor / operator to ensure old state is cleared on the moved instance. Bug: 163468874 Test: Load multi-HAL and verify that it properly waits to release the wakelock until the sensor service notifies that it has a lock held. Test: Run unit tests Change-Id: Ifd5a3c7596f78d7a756c4472f30efb625d670791 --- .../common/default/2.X/multihal/HalProxy.cpp | 4 + .../default/2.X/multihal/ScopedWakelock.cpp | 15 +++ .../multihal/include/V2_0/ScopedWakelock.h | 5 +- .../default/2.X/multihal/tests/Android.bp | 5 +- .../multihal/tests/ScopedWakelock_test.cpp | 110 ++++++++++++++++++ 5 files changed, 136 insertions(+), 3 deletions(-) create mode 100644 sensors/common/default/2.X/multihal/tests/ScopedWakelock_test.cpp diff --git a/sensors/common/default/2.X/multihal/HalProxy.cpp b/sensors/common/default/2.X/multihal/HalProxy.cpp index 75ffc17a67..fe3fc8477e 100644 --- a/sensors/common/default/2.X/multihal/HalProxy.cpp +++ b/sensors/common/default/2.X/multihal/HalProxy.cpp @@ -693,6 +693,10 @@ void HalProxy::decrementRefCountAndMaybeReleaseWakelock(size_t delta, int64_t timeoutStart /* = -1 */) { if (!mThreadsRun.load()) return; std::lock_guard lockGuard(mWakelockMutex); + if (delta > mWakelockRefCount) { + ALOGE("Decrementing wakelock ref count by %zu when count is %zu", + delta, mWakelockRefCount); + } if (timeoutStart == -1) timeoutStart = mWakelockTimeoutResetTime; if (mWakelockRefCount == 0 || timeoutStart < mWakelockTimeoutResetTime) return; mWakelockRefCount -= std::min(mWakelockRefCount, delta); diff --git a/sensors/common/default/2.X/multihal/ScopedWakelock.cpp b/sensors/common/default/2.X/multihal/ScopedWakelock.cpp index bf2ad35081..2a2baa2639 100644 --- a/sensors/common/default/2.X/multihal/ScopedWakelock.cpp +++ b/sensors/common/default/2.X/multihal/ScopedWakelock.cpp @@ -28,6 +28,21 @@ int64_t getTimeNow() { .count(); } +ScopedWakelock::ScopedWakelock(ScopedWakelock&& other) { + *this = std::move(other); +} + +ScopedWakelock& ScopedWakelock::operator=(ScopedWakelock&& other) { + mRefCounter = other.mRefCounter; + mCreatedAtTimeNs = other.mCreatedAtTimeNs; + mLocked = other.mLocked; + + other.mRefCounter = nullptr; + other.mCreatedAtTimeNs = 0; + other.mLocked = false; + return *this; +} + ScopedWakelock::ScopedWakelock(IScopedWakelockRefCounter* refCounter, bool locked) : mRefCounter(refCounter), mLocked(locked) { if (mLocked) { diff --git a/sensors/common/default/2.X/multihal/include/V2_0/ScopedWakelock.h b/sensors/common/default/2.X/multihal/include/V2_0/ScopedWakelock.h index 1cc5cd5e9e..b3f398c8eb 100644 --- a/sensors/common/default/2.X/multihal/include/V2_0/ScopedWakelock.h +++ b/sensors/common/default/2.X/multihal/include/V2_0/ScopedWakelock.h @@ -81,14 +81,15 @@ class IScopedWakelockRefCounter : public RefBase { */ class ScopedWakelock { public: - ScopedWakelock(ScopedWakelock&&) = default; - ScopedWakelock& operator=(ScopedWakelock&&) = default; + ScopedWakelock(ScopedWakelock&& other); + ScopedWakelock& operator=(ScopedWakelock&& other); virtual ~ScopedWakelock(); bool isLocked() const { return mLocked; } private: friend class HalProxyCallbackBase; + friend class ScopedWakelockTest; IScopedWakelockRefCounter* mRefCounter; int64_t mCreatedAtTimeNs; bool mLocked; diff --git a/sensors/common/default/2.X/multihal/tests/Android.bp b/sensors/common/default/2.X/multihal/tests/Android.bp index a15faed1ef..1b60f4b505 100644 --- a/sensors/common/default/2.X/multihal/tests/Android.bp +++ b/sensors/common/default/2.X/multihal/tests/Android.bp @@ -90,7 +90,10 @@ cc_test_library { cc_test { name: "android.hardware.sensors@2.X-halproxy-unit-tests", - srcs: ["HalProxy_test.cpp"], + srcs: [ + "HalProxy_test.cpp", + "ScopedWakelock_test.cpp", + ], vendor: true, header_libs: [ "android.hardware.sensors@2.X-shared-utils", diff --git a/sensors/common/default/2.X/multihal/tests/ScopedWakelock_test.cpp b/sensors/common/default/2.X/multihal/tests/ScopedWakelock_test.cpp new file mode 100644 index 0000000000..133d9e83d2 --- /dev/null +++ b/sensors/common/default/2.X/multihal/tests/ScopedWakelock_test.cpp @@ -0,0 +1,110 @@ +// +// 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 + +#include "V2_0/ScopedWakelock.h" + +namespace android { +namespace hardware { +namespace sensors { +namespace V2_0 { +namespace implementation { + +class RefCounter : public IScopedWakelockRefCounter { + public: + size_t incCount = 0; + size_t decCount = 0; + + bool incrementRefCountAndMaybeAcquireWakelock(size_t /* delta */, + int64_t* /* timeoutStart */) override { + incCount++; + return true; + } + + void decrementRefCountAndMaybeReleaseWakelock(size_t /* delta */, + int64_t /* timeoutStart */) override { + decCount++; + } +}; + +class ScopedWakelockTest : public testing::Test { + public: + ScopedWakelock createScopedWakelock(bool locked) { + return ScopedWakelock(&mRefCounter, locked); + } + + RefCounter mRefCounter; +}; + +TEST_F(ScopedWakelockTest, UnlockedAfterMoved) { + ScopedWakelock wakelock = createScopedWakelock(false /* locked */); + + ScopedWakelock movedWakelock(std::move(wakelock)); + + EXPECT_FALSE(wakelock.isLocked()); + EXPECT_FALSE(movedWakelock.isLocked()); +} + +TEST_F(ScopedWakelockTest, LockedAfterMoved) { + ScopedWakelock wakelock = createScopedWakelock(true /* locked */); + + ScopedWakelock movedWakelock(std::move(wakelock)); + + EXPECT_FALSE(wakelock.isLocked()); + EXPECT_TRUE(movedWakelock.isLocked()); +} + +TEST_F(ScopedWakelockTest, Locked) { + ScopedWakelock wakelock = createScopedWakelock(true /* locked */); + + EXPECT_TRUE(wakelock.isLocked()); +} + +TEST_F(ScopedWakelockTest, Unlocked) { + ScopedWakelock wakelock = createScopedWakelock(false /* locked */); + + EXPECT_FALSE(wakelock.isLocked()); +} + +TEST_F(ScopedWakelockTest, ScopedLocked) { + { createScopedWakelock(true /* locked */); } + + EXPECT_EQ(mRefCounter.incCount, 1); + EXPECT_EQ(mRefCounter.decCount, 1); +} + +TEST_F(ScopedWakelockTest, ScopedUnlockIsNoop) { + { createScopedWakelock(false /* locked */); } + + EXPECT_EQ(mRefCounter.incCount, 0); + EXPECT_EQ(mRefCounter.decCount, 0); +} + +TEST_F(ScopedWakelockTest, ScopedLockedMove) { + { + ScopedWakelock wakelock = createScopedWakelock(true /* locked */); + ScopedWakelock movedWakelock(std::move(wakelock)); + } + + EXPECT_EQ(mRefCounter.incCount, 1); + EXPECT_EQ(mRefCounter.decCount, 1); +} + +} // namespace implementation +} // namespace V2_0 +} // namespace sensors +} // namespace hardware +} // namespace android \ No newline at end of file From 590607780ab47c3d48390c74cb2762438316d30f Mon Sep 17 00:00:00 2001 From: Jordan Jozwiak Date: Tue, 11 Aug 2020 14:40:44 -0700 Subject: [PATCH 11/27] Add INFO_MODEL and INFO_MODEL_YEAR default values Bug: 162611157 Test: adb shell cmd car_service get-carpropertyconfig | grep MODEL Change-Id: Iff9f763aa624a2002b0dd326316410a93a47d5c0 Merged-In: Iff9f763aa624a2002b0dd326316410a93a47d5c0 (cherry picked from commit 5aa08b7d592cfc83c446c8bb6e67ac79cf67aa02) --- .../2.0/default/impl/vhal_v2_0/DefaultConfig.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) 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 16c33b9d19..16e1bf7291 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 @@ -264,6 +264,20 @@ const ConfigDeclaration kVehicleProperties[]{ .changeMode = VehiclePropertyChangeMode::STATIC, }, .initialValue = {.stringValue = "Toy Vehicle"}}, + {.config = + { + .prop = toInt(VehicleProperty::INFO_MODEL), + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::STATIC, + }, + .initialValue = {.stringValue = "Speedy Model"}}, + {.config = + { + .prop = toInt(VehicleProperty::INFO_MODEL_YEAR), + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::STATIC, + }, + .initialValue = {.int32Values = {2020}}}, {.config = { .prop = toInt(VehicleProperty::INFO_EXTERIOR_DIMENSIONS), From 92ad8215e7db04f6f43e1575ebe603d023b7eb9d Mon Sep 17 00:00:00 2001 From: Lakshman Annadorai Date: Thu, 6 Aug 2020 14:25:03 -0700 Subject: [PATCH 12/27] Update EmulatedUserHal to use UserHalHelper native library. Bug: 150409377 Test: Tested using lshal commands in go/user-hal-emulation. Change-Id: I79486a715c92111d3d6f5c011b7e1cd8c5501c25 Merged-In: I4ba2202e28ef9260b38ebbf21083d55d7aa07fc9 --- automotive/vehicle/2.0/default/Android.bp | 4 + .../impl/vhal_v2_0/EmulatedUserHal.cpp | 222 +++++++++--------- .../vehicle/2.0/utils/UserHalHelper.cpp | 35 +-- automotive/vehicle/2.0/utils/UserHalHelper.h | 5 + 4 files changed, 140 insertions(+), 126 deletions(-) diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp index d9ac239f62..9a0d89d209 100644 --- a/automotive/vehicle/2.0/default/Android.bp +++ b/automotive/vehicle/2.0/default/Android.bp @@ -108,6 +108,9 @@ cc_library_static { srcs: [ "impl/vhal_v2_0/EmulatedUserHal.cpp", ], + whole_static_libs: [ + "android.hardware.automotive.vehicle@2.0-user-hal-helper-lib", + ], } // Vehicle HAL Server reference impl lib @@ -143,6 +146,7 @@ cc_library_static { ], whole_static_libs: [ "android.hardware.automotive.vehicle@2.0-server-common-lib", + "android.hardware.automotive.vehicle@2.0-user-hal-helper-lib", ], static_libs: [ "android.hardware.automotive.vehicle@2.0-libproto-native", diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp index d0011a831e..3bdf5a84a0 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp @@ -15,10 +15,12 @@ */ #define LOG_TAG "EmulatedUserHal" +#include "EmulatedUserHal.h" + #include #include -#include "EmulatedUserHal.h" +#include "UserHalHelper.h" namespace android { namespace hardware { @@ -28,12 +30,35 @@ namespace V2_0 { namespace impl { -constexpr int INITIAL_USER_INFO = static_cast(VehicleProperty::INITIAL_USER_INFO); -constexpr int SWITCH_USER = static_cast(VehicleProperty::SWITCH_USER); -constexpr int CREATE_USER = static_cast(VehicleProperty::CREATE_USER); -constexpr int REMOVE_USER = static_cast(VehicleProperty::REMOVE_USER); -constexpr int USER_IDENTIFICATION_ASSOCIATION = - static_cast(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION); +namespace { + +using android::base::Error; +using android::base::Result; + +constexpr int32_t INITIAL_USER_INFO = static_cast(VehicleProperty::INITIAL_USER_INFO); +constexpr int32_t SWITCH_USER = static_cast(VehicleProperty::SWITCH_USER); +constexpr int32_t CREATE_USER = static_cast(VehicleProperty::CREATE_USER); +constexpr int32_t REMOVE_USER = static_cast(VehicleProperty::REMOVE_USER); +constexpr int32_t USER_IDENTIFICATION_ASSOCIATION = + static_cast(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION); + +Result getRequestId(const VehiclePropValue& value) { + if (value.value.int32Values.size() < 1) { + return Error(static_cast(StatusCode::INVALID_ARG)) + << "no int32values on " << toString(value); + } + return value.value.int32Values[0]; +} + +Result getSwitchUserMessageType(const VehiclePropValue& value) { + if (value.value.int32Values.size() < 2) { + return Error(static_cast(StatusCode::INVALID_ARG)) + << "missing switch user message type " << toString(value); + } + return user_hal_helper::verifyAndCast(value.value.int32Values[1]); +} + +} // namespace bool EmulatedUserHal::isSupported(int32_t prop) { switch (prop) { @@ -48,7 +73,7 @@ bool EmulatedUserHal::isSupported(int32_t prop) { } } -android::base::Result> EmulatedUserHal::onSetProperty( +Result> EmulatedUserHal::onSetProperty( const VehiclePropValue& value) { ALOGV("onSetProperty(): %s", toString(value).c_str()); @@ -65,12 +90,12 @@ android::base::Result> EmulatedUserHal::onSetP case USER_IDENTIFICATION_ASSOCIATION: return onSetUserIdentificationAssociation(value); default: - return android::base::Error(static_cast(StatusCode::INVALID_ARG)) + return Error(static_cast(StatusCode::INVALID_ARG)) << "Unsupported property: " << toString(value); } } -android::base::Result> EmulatedUserHal::onGetProperty( +Result> EmulatedUserHal::onGetProperty( const VehiclePropValue& value) { ALOGV("onGetProperty(%s)", toString(value).c_str()); switch (value.prop) { @@ -79,42 +104,41 @@ android::base::Result> EmulatedUserHal::onGetP case CREATE_USER: case REMOVE_USER: ALOGE("onGetProperty(): %d is only supported on SET", value.prop); - return android::base::Error(static_cast(StatusCode::INVALID_ARG)) - << "only supported on SET"; + return Error(static_cast(StatusCode::INVALID_ARG)) << "only supported on SET"; case USER_IDENTIFICATION_ASSOCIATION: return onGetUserIdentificationAssociation(value); default: ALOGE("onGetProperty(): %d is not supported", value.prop); - return android::base::Error(static_cast(StatusCode::INVALID_ARG)) - << "not supported by User HAL"; + return Error(static_cast(StatusCode::INVALID_ARG)) << "not supported by User HAL"; } } -android::base::Result> -EmulatedUserHal::onGetUserIdentificationAssociation(const VehiclePropValue& value) { - if (mSetUserIdentificationAssociationResponseFromCmd != nullptr) { - ALOGI("get(USER_IDENTIFICATION_ASSOCIATION): returning %s", - toString(*mSetUserIdentificationAssociationResponseFromCmd).c_str()); - auto newValue = std::unique_ptr( - new VehiclePropValue(*mSetUserIdentificationAssociationResponseFromCmd)); +Result> EmulatedUserHal::onGetUserIdentificationAssociation( + const VehiclePropValue& value) { + if (mSetUserIdentificationAssociationResponseFromCmd == nullptr) { + return defaultUserIdentificationAssociation(value); + } + ALOGI("get(USER_IDENTIFICATION_ASSOCIATION): returning %s", + toString(*mSetUserIdentificationAssociationResponseFromCmd).c_str()); + auto newValue = std::unique_ptr( + new VehiclePropValue(*mSetUserIdentificationAssociationResponseFromCmd)); + auto requestId = getRequestId(value); + if (requestId.ok()) { // Must use the same requestId - if (value.value.int32Values.size() > 0) { - newValue->value.int32Values[0] = value.value.int32Values[0]; - } else { - ALOGE("get(USER_IDENTIFICATION_ASSOCIATION): no requestId on %s", - toString(value).c_str()); - } - return newValue; + newValue->value.int32Values[0] = *requestId; + } else { + ALOGE("get(USER_IDENTIFICATION_ASSOCIATION): no requestId on %s", toString(value).c_str()); } - return defaultUserIdentificationAssociation(value); + return newValue; } -android::base::Result> -EmulatedUserHal::onSetInitialUserInfoResponse(const VehiclePropValue& value) { - if (value.value.int32Values.size() == 0) { - ALOGE("set(INITIAL_USER_INFO): no int32values, ignoring it: %s", toString(value).c_str()); - return android::base::Error(static_cast(StatusCode::INVALID_ARG)) - << "no int32values on " << toString(value); +Result> EmulatedUserHal::onSetInitialUserInfoResponse( + const VehiclePropValue& value) { + auto requestId = getRequestId(value); + if (!requestId.ok()) { + ALOGE("Failed to get requestId on set(INITIAL_USER_INFO): %s", + requestId.error().message().c_str()); + return requestId.error(); } if (value.areaId != 0) { @@ -124,40 +148,40 @@ EmulatedUserHal::onSetInitialUserInfoResponse(const VehiclePropValue& value) { } ALOGD("set(INITIAL_USER_INFO) called from Android: %s", toString(value).c_str()); - - int32_t requestId = value.value.int32Values[0]; if (mInitialUserResponseFromCmd != nullptr) { ALOGI("replying INITIAL_USER_INFO with lshal value: %s", toString(*mInitialUserResponseFromCmd).c_str()); - return sendUserHalResponse(std::move(mInitialUserResponseFromCmd), requestId); + return sendUserHalResponse(std::move(mInitialUserResponseFromCmd), *requestId); } // Returns default response - auto updatedValue = std::unique_ptr(new VehiclePropValue); - updatedValue->prop = INITIAL_USER_INFO; - updatedValue->timestamp = elapsedRealtimeNano(); - updatedValue->value.int32Values.resize(2); - updatedValue->value.int32Values[0] = requestId; - updatedValue->value.int32Values[1] = (int32_t)InitialUserInfoResponseAction::DEFAULT; - + auto updatedValue = user_hal_helper::toVehiclePropValue(InitialUserInfoResponse{ + .requestId = *requestId, + .action = InitialUserInfoResponseAction::DEFAULT, + }); ALOGI("no lshal response; replying with InitialUserInfoResponseAction::DEFAULT: %s", toString(*updatedValue).c_str()); - return updatedValue; } -android::base::Result> EmulatedUserHal::onSetSwitchUserResponse( +Result> EmulatedUserHal::onSetSwitchUserResponse( const VehiclePropValue& value) { - if (value.value.int32Values.size() == 0) { - ALOGE("set(SWITCH_USER): no int32values, ignoring it: %s", toString(value).c_str()); - return android::base::Error(static_cast(StatusCode::INVALID_ARG)) - << "no int32values on " << toString(value); + auto requestId = getRequestId(value); + if (!requestId.ok()) { + ALOGE("Failed to get requestId on set(SWITCH_USER): %s", + requestId.error().message().c_str()); + return requestId.error(); + } + + auto messageType = getSwitchUserMessageType(value); + if (!messageType.ok()) { + ALOGE("Failed to get messageType on set(SWITCH_USER): %s", + messageType.error().message().c_str()); + return messageType.error(); } if (value.areaId != 0) { - if (value.value.int32Values.size() >= 2 && - static_cast(value.value.int32Values[1]) == - SwitchUserMessageType::VEHICLE_REQUEST) { + if (*messageType == SwitchUserMessageType::VEHICLE_REQUEST) { // User HAL can also request a user switch, so we need to check it first ALOGD("set(SWITCH_USER) called from lshal to emulate a vehicle request: %s", toString(value).c_str()); @@ -170,48 +194,36 @@ android::base::Result> EmulatedUserHal::onSetS } ALOGD("set(SWITCH_USER) called from Android: %s", toString(value).c_str()); - int32_t requestId = value.value.int32Values[0]; if (mSwitchUserResponseFromCmd != nullptr) { ALOGI("replying SWITCH_USER with lshal value: %s", toString(*mSwitchUserResponseFromCmd).c_str()); - return sendUserHalResponse(std::move(mSwitchUserResponseFromCmd), requestId); + return sendUserHalResponse(std::move(mSwitchUserResponseFromCmd), *requestId); } - if (value.value.int32Values.size() > 1) { - auto messageType = static_cast(value.value.int32Values[1]); - switch (messageType) { - case SwitchUserMessageType::LEGACY_ANDROID_SWITCH: - ALOGI("request is LEGACY_ANDROID_SWITCH; ignoring it"); - return {}; - case SwitchUserMessageType::ANDROID_POST_SWITCH: - ALOGI("request is ANDROID_POST_SWITCH; ignoring it"); - return {}; - default: - break; - } + if (*messageType == SwitchUserMessageType::LEGACY_ANDROID_SWITCH || + *messageType == SwitchUserMessageType::ANDROID_POST_SWITCH) { + ALOGI("request is %s; ignoring it", toString(*messageType).c_str()); + return {}; } // Returns default response - auto updatedValue = std::unique_ptr(new VehiclePropValue); - updatedValue->prop = SWITCH_USER; - updatedValue->timestamp = elapsedRealtimeNano(); - updatedValue->value.int32Values.resize(3); - updatedValue->value.int32Values[0] = requestId; - updatedValue->value.int32Values[1] = (int32_t)SwitchUserMessageType::VEHICLE_RESPONSE; - updatedValue->value.int32Values[2] = (int32_t)SwitchUserStatus::SUCCESS; - + auto updatedValue = user_hal_helper::toVehiclePropValue(SwitchUserResponse{ + .requestId = *requestId, + .messageType = SwitchUserMessageType::VEHICLE_RESPONSE, + .status = SwitchUserStatus::SUCCESS, + }); ALOGI("no lshal response; replying with VEHICLE_RESPONSE / SUCCESS: %s", toString(*updatedValue).c_str()); - return updatedValue; } -android::base::Result> EmulatedUserHal::onSetCreateUserResponse( +Result> EmulatedUserHal::onSetCreateUserResponse( const VehiclePropValue& value) { - if (value.value.int32Values.size() == 0) { - ALOGE("set(CREATE_USER): no int32values, ignoring it: %s", toString(value).c_str()); - return android::base::Error(static_cast(StatusCode::INVALID_ARG)) - << "no int32values on " << toString(value); + auto requestId = getRequestId(value); + if (!requestId.ok()) { + ALOGE("Failed to get requestId on set(CREATE_USER): %s", + requestId.error().message().c_str()); + return requestId.error(); } if (value.areaId != 0) { @@ -221,33 +233,28 @@ android::base::Result> EmulatedUserHal::onSetC } ALOGD("set(CREATE_USER) called from Android: %s", toString(value).c_str()); - int32_t requestId = value.value.int32Values[0]; if (mCreateUserResponseFromCmd != nullptr) { ALOGI("replying CREATE_USER with lshal value: %s", toString(*mCreateUserResponseFromCmd).c_str()); - return sendUserHalResponse(std::move(mCreateUserResponseFromCmd), requestId); + return sendUserHalResponse(std::move(mCreateUserResponseFromCmd), *requestId); } // Returns default response - auto updatedValue = std::unique_ptr(new VehiclePropValue); - updatedValue->prop = CREATE_USER; - updatedValue->timestamp = elapsedRealtimeNano(); - updatedValue->value.int32Values.resize(2); - updatedValue->value.int32Values[0] = requestId; - updatedValue->value.int32Values[1] = (int32_t)CreateUserStatus::SUCCESS; - + auto updatedValue = user_hal_helper::toVehiclePropValue(CreateUserResponse{ + .requestId = *requestId, + .status = CreateUserStatus::SUCCESS, + }); ALOGI("no lshal response; replying with SUCCESS: %s", toString(*updatedValue).c_str()); - return updatedValue; } -android::base::Result> -EmulatedUserHal::onSetUserIdentificationAssociation(const VehiclePropValue& value) { - if (value.value.int32Values.size() == 0) { - ALOGE("set(USER_IDENTIFICATION_ASSOCIATION): no int32values, ignoring it: %s", - toString(value).c_str()); - return android::base::Error(static_cast(StatusCode::INVALID_ARG)) - << "no int32values on " << toString(value); +Result> EmulatedUserHal::onSetUserIdentificationAssociation( + const VehiclePropValue& value) { + auto requestId = getRequestId(value); + if (!requestId.ok()) { + ALOGE("Failed to get requestId on set(USER_IDENTIFICATION_ASSOCIATION): %s", + requestId.error().message().c_str()); + return requestId.error(); } if (value.areaId != 0) { @@ -258,28 +265,26 @@ EmulatedUserHal::onSetUserIdentificationAssociation(const VehiclePropValue& valu } ALOGD("set(USER_IDENTIFICATION_ASSOCIATION) called from Android: %s", toString(value).c_str()); - int32_t requestId = value.value.int32Values[0]; if (mSetUserIdentificationAssociationResponseFromCmd != nullptr) { ALOGI("replying USER_IDENTIFICATION_ASSOCIATION with lshal value: %s", toString(*mSetUserIdentificationAssociationResponseFromCmd).c_str()); // Not moving response so it can be used on GET requests auto copy = std::unique_ptr( new VehiclePropValue(*mSetUserIdentificationAssociationResponseFromCmd)); - return sendUserHalResponse(std::move(copy), requestId); + return sendUserHalResponse(std::move(copy), *requestId); } - // Returns default response return defaultUserIdentificationAssociation(value); } -android::base::Result> -EmulatedUserHal::defaultUserIdentificationAssociation(const VehiclePropValue& request) { +Result> EmulatedUserHal::defaultUserIdentificationAssociation( + const VehiclePropValue& request) { // TODO(b/159498909): return a response with NOT_ASSOCIATED_ANY_USER for all requested types ALOGE("no lshal response for %s; replying with NOT_AVAILABLE", toString(request).c_str()); - return android::base::Error(static_cast(StatusCode::NOT_AVAILABLE)) << "not set by lshal"; + return Error(static_cast(StatusCode::NOT_AVAILABLE)) << "not set by lshal"; } -android::base::Result> EmulatedUserHal::sendUserHalResponse( +Result> EmulatedUserHal::sendUserHalResponse( std::unique_ptr response, int32_t requestId) { switch (response->areaId) { case 1: @@ -293,17 +298,16 @@ android::base::Result> EmulatedUserHal::sendUs case 3: ALOGD("not generating a property change event because of lshal prop: %s", toString(*response).c_str()); - return android::base::Error(static_cast(StatusCode::NOT_AVAILABLE)) + return Error(static_cast(StatusCode::NOT_AVAILABLE)) << "not generating a property change event because of lshal prop: " << toString(*response); default: ALOGE("invalid action on lshal response: %s", toString(*response).c_str()); - return android::base::Error(static_cast(StatusCode::INTERNAL_ERROR)) + return Error(static_cast(StatusCode::INTERNAL_ERROR)) << "invalid action on lshal response: " << toString(*response); } ALOGD("updating property to: %s", toString(*response).c_str()); - return response; } diff --git a/automotive/vehicle/2.0/utils/UserHalHelper.cpp b/automotive/vehicle/2.0/utils/UserHalHelper.cpp index 33b39482da..fcfe4bf17f 100644 --- a/automotive/vehicle/2.0/utils/UserHalHelper.cpp +++ b/automotive/vehicle/2.0/utils/UserHalHelper.cpp @@ -36,22 +36,6 @@ static constexpr const char* kSeparator = "||"; static const size_t kNumFieldsPerUserInfo = 2; static const size_t kNumFieldsPerSetAssociation = 2; -template -Result verifyAndCast(int32_t value) { - T castValue = static_cast(value); - const auto iter = hidl_enum_range(); - if (castValue < *iter.begin() || castValue > *std::prev(iter.end())) { - return Error() << "Value " << value << " not in range [" << toString(*iter.begin()) << ", " - << toString(*std::prev(iter.end())) << "]"; - } - for (const auto& v : hidl_enum_range()) { - if (castValue == v) { - return castValue; - } - } - return Error() << "Value " << value << " not in enum values"; -} - Result verifyPropValue(const VehiclePropValue& propValue, VehicleProperty vehicleProperty, size_t minInt32Values) { auto prop = verifyAndCast(propValue.prop); @@ -154,6 +138,22 @@ Result parseUserAssociations(const hidl_vec& int32Values, size_t } // namespace +template +Result verifyAndCast(int32_t value) { + T castValue = static_cast(value); + const auto iter = hidl_enum_range(); + if (castValue < *iter.begin() || castValue > *std::prev(iter.end())) { + return Error() << "Value " << value << " not in range [" << toString(*iter.begin()) << ", " + << toString(*std::prev(iter.end())) << "]"; + } + for (const auto& v : hidl_enum_range()) { + if (castValue == v) { + return castValue; + } + } + return Error() << "Value " << value << " not in enum values"; +} + Result toInitialUserInfoRequest(const VehiclePropValue& propValue) { auto ret = verifyPropValue(propValue, VehicleProperty::INITIAL_USER_INFO, 2); if (!ret.ok()) { @@ -186,7 +186,8 @@ Result toSwitchUserRequest(const VehiclePropValue& propValue) if (*messageType != SwitchUserMessageType::LEGACY_ANDROID_SWITCH && *messageType != SwitchUserMessageType::ANDROID_SWITCH && *messageType != SwitchUserMessageType::ANDROID_POST_SWITCH) { - return Error() << "Invalid " << toString(*messageType) << " from Android System"; + return Error() << "Invalid " << toString(*messageType) + << " message type from Android System"; } request.requestId = propValue.value.int32Values[0]; request.messageType = *messageType; diff --git a/automotive/vehicle/2.0/utils/UserHalHelper.h b/automotive/vehicle/2.0/utils/UserHalHelper.h index bee34cf0f6..fad71451aa 100644 --- a/automotive/vehicle/2.0/utils/UserHalHelper.h +++ b/automotive/vehicle/2.0/utils/UserHalHelper.h @@ -31,6 +31,11 @@ namespace V2_0 { namespace user_hal_helper { +// Verify whether the |value| can be casted to the type |T| and return the casted value on success. +// Otherwise, return the error. +template +android::base::Result verifyAndCast(int32_t value); + // Below functions parse VehiclePropValues to the respective User HAL request structs. On success, // these functions return the User HAL struct. Otherwise, they return the error. android::base::Result toInitialUserInfoRequest( From 65516ffff5de1a040c50d38118abaabeee0b723e Mon Sep 17 00:00:00 2001 From: TF Huang Date: Wed, 1 Jul 2020 10:43:31 +0800 Subject: [PATCH 13/27] wlan: add supported interfaces in rc file Service vendor.wifi_hal_legacy should add all supported interface into relevant .rc files. Bug: 160377428 Test: Wifi presubmit tests Change-Id: I68e8d3e7ddb1470a92c5ccd30f6d4d5f90ad9e37 Merged-In: I68e8d3e7ddb1470a92c5ccd30f6d4d5f90ad9e37 (cherry picked from commit ca7a8c9559ecc330160c52eb26874300ff8fd215) --- wifi/1.4/default/android.hardware.wifi@1.0-service-lazy.rc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/wifi/1.4/default/android.hardware.wifi@1.0-service-lazy.rc b/wifi/1.4/default/android.hardware.wifi@1.0-service-lazy.rc index cf917b5458..061689dbe5 100644 --- a/wifi/1.4/default/android.hardware.wifi@1.0-service-lazy.rc +++ b/wifi/1.4/default/android.hardware.wifi@1.0-service-lazy.rc @@ -1,5 +1,9 @@ service vendor.wifi_hal_legacy /vendor/bin/hw/android.hardware.wifi@1.0-service-lazy interface android.hardware.wifi@1.0::IWifi default + interface android.hardware.wifi@1.1::IWifi default + interface android.hardware.wifi@1.2::IWifi default + interface android.hardware.wifi@1.3::IWifi default + interface android.hardware.wifi@1.4::IWifi default oneshot disabled class hal From a6cc5825e93ade1115ed9c241fa404f8bbaeeb35 Mon Sep 17 00:00:00 2001 From: lesl Date: Fri, 21 Aug 2020 19:08:17 +0800 Subject: [PATCH 14/27] vts: Fix incorrect instance name in Teardown The stopHostapd uses vendor HAL HIDL interface. The interface name should use wifi_instance. Bug: 161682236 Test: atest VtsHalWifiHostapdV1_2TargetTest Change-Id: I8215cba3e2a36f48863f57e199684c7446e20692 --- wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp b/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp index 2715891b92..a39f064aab 100644 --- a/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp +++ b/wifi/hostapd/1.2/vts/functional/hostapd_hidl_test.cpp @@ -72,7 +72,7 @@ class HostapdHidlTest "wifi_softap_wpa3_sae_supported"); } - virtual void TearDown() override { stopHostapd(hostapd_instance_name_); } + virtual void TearDown() override { stopHostapd(wifi_instance_name_); } protected: bool isWpa3SaeSupport_ = false; From 9eea6d5a735f9b852e6d71356e8e07732ffe9d6c Mon Sep 17 00:00:00 2001 From: Shuo Qian Date: Wed, 19 Aug 2020 16:55:39 -0700 Subject: [PATCH 15/27] Check emergency dialing result in DSDS or TSTS only if slot is in service or emergency only. Test: vts Bug: 156525817 Change-Id: Ic4c735e6d920fc3df28eda7bc3f0b958782bf42d --- radio/1.0/vts/functional/vts_test_util.cpp | 21 +++++++++ radio/1.0/vts/functional/vts_test_util.h | 21 +++++++++ .../1.4/vts/functional/radio_hidl_hal_api.cpp | 47 +++++++++++++++++-- .../functional/radio_hidl_hal_utils_v1_4.h | 1 + radio/1.4/vts/functional/radio_response.cpp | 3 +- 5 files changed, 89 insertions(+), 4 deletions(-) diff --git a/radio/1.0/vts/functional/vts_test_util.cpp b/radio/1.0/vts/functional/vts_test_util.cpp index 7a21a40004..9a2d089899 100644 --- a/radio/1.0/vts/functional/vts_test_util.cpp +++ b/radio/1.0/vts/functional/vts_test_util.cpp @@ -17,6 +17,7 @@ #include #include +#include "VtsCoreUtil.h" int GetRandomSerialNumber() { return rand(); @@ -78,4 +79,24 @@ bool deviceSupportsFeature(const char* feature) { __android_log_print(ANDROID_LOG_INFO, LOG_TAG, "Feature %s: %ssupported", feature, hasFeature ? "" : "not "); return hasFeature; +} + +bool isDsDsEnabled() { + return testing::checkSubstringInCommandOutput("getprop persist.radio.multisim.config", "dsds"); +} + +bool isTsTsEnabled() { + return testing::checkSubstringInCommandOutput("getprop persist.radio.multisim.config", "tsts"); +} + +bool isVoiceInService(RegState state) { + return ::android::hardware::radio::V1_0::RegState::REG_HOME == state || + ::android::hardware::radio::V1_0::RegState::REG_ROAMING == state; +} + +bool isVoiceEmergencyOnly(RegState state) { + return ::android::hardware::radio::V1_0::RegState::NOT_REG_MT_NOT_SEARCHING_OP_EM == state || + ::android::hardware::radio::V1_0::RegState::NOT_REG_MT_SEARCHING_OP_EM == state || + ::android::hardware::radio::V1_0::RegState::REG_DENIED_EM == state || + ::android::hardware::radio::V1_0::RegState::UNKNOWN_EM == state; } \ No newline at end of file diff --git a/radio/1.0/vts/functional/vts_test_util.h b/radio/1.0/vts/functional/vts_test_util.h index df8dd7718b..1625f11d5d 100644 --- a/radio/1.0/vts/functional/vts_test_util.h +++ b/radio/1.0/vts/functional/vts_test_util.h @@ -21,6 +21,7 @@ #include using ::android::hardware::radio::V1_0::RadioError; +using ::android::hardware::radio::V1_0::RegState; using ::android::hardware::radio::V1_0::SapResultCode; using namespace std; @@ -55,3 +56,23 @@ int GetRandomSerialNumber(); * Check if device supports feature. */ bool deviceSupportsFeature(const char* feature); + +/* + * Check if device is in DSDS. + */ +bool isDsDsEnabled(); + +/* + * Check if device is in TSTS. + */ +bool isTsTsEnabled(); + +/* + * Check if voice status is in emergency only. + */ +bool isVoiceEmergencyOnly(RegState state); + +/* + * Check if voice status is in service. + */ +bool isVoiceInService(RegState state); \ No newline at end of file diff --git a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp index 3ba9b9db9d..1b254a1edf 100644 --- a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp +++ b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp @@ -56,7 +56,21 @@ TEST_P(RadioHidlTest_v1_4, emergencyDial) { EXPECT_EQ(serial, radioRsp_v1_4->rspInfo.serial); ALOGI("emergencyDial, rspInfo.error = %s\n", toString(radioRsp_v1_4->rspInfo.error).c_str()); - EXPECT_EQ(RadioError::NONE, radioRsp_v1_4->rspInfo.error); + + ::android::hardware::radio::V1_0::RadioError rspEmergencyDial = radioRsp_v1_4->rspInfo.error; + // In DSDS or TSTS, we only check the result if the current slot is IN_SERVICE + // or Emergency_Only. + if (isDsDsEnabled() || isTsTsEnabled()) { + serial = GetRandomSerialNumber(); + radio_v1_4->getVoiceRegistrationState(serial); + EXPECT_EQ(std::cv_status::no_timeout, wait()); + if (isVoiceEmergencyOnly(radioRsp_v1_4->voiceRegResp.regState) || + isVoiceInService(radioRsp_v1_4->voiceRegResp.regState)) { + EXPECT_EQ(RadioError::NONE, rspEmergencyDial); + } + } else { + EXPECT_EQ(RadioError::NONE, rspEmergencyDial); + } // Give some time for modem to establish the emergency call channel. sleep(MODEM_EMERGENCY_CALL_ESTABLISH_TIME); @@ -95,8 +109,21 @@ TEST_P(RadioHidlTest_v1_4, emergencyDial_withServices) { ALOGI("emergencyDial_withServices, rspInfo.error = %s\n", toString(radioRsp_v1_4->rspInfo.error).c_str()); - EXPECT_EQ(RadioError::NONE, radioRsp_v1_4->rspInfo.error); + ::android::hardware::radio::V1_0::RadioError rspEmergencyDial = radioRsp_v1_4->rspInfo.error; + // In DSDS or TSTS, we only check the result if the current slot is IN_SERVICE + // or Emergency_Only. + if (isDsDsEnabled() || isTsTsEnabled()) { + serial = GetRandomSerialNumber(); + radio_v1_4->getVoiceRegistrationState(serial); + EXPECT_EQ(std::cv_status::no_timeout, wait()); + if (isVoiceEmergencyOnly(radioRsp_v1_4->voiceRegResp.regState) || + isVoiceInService(radioRsp_v1_4->voiceRegResp.regState)) { + EXPECT_EQ(RadioError::NONE, rspEmergencyDial); + } + } else { + EXPECT_EQ(RadioError::NONE, rspEmergencyDial); + } // Give some time for modem to establish the emergency call channel. sleep(MODEM_EMERGENCY_CALL_ESTABLISH_TIME); @@ -134,7 +161,21 @@ TEST_P(RadioHidlTest_v1_4, emergencyDial_withEmergencyRouting) { ALOGI("emergencyDial_withEmergencyRouting, rspInfo.error = %s\n", toString(radioRsp_v1_4->rspInfo.error).c_str()); - EXPECT_EQ(RadioError::NONE, radioRsp_v1_4->rspInfo.error); + ::android::hardware::radio::V1_0::RadioError rspEmergencyDial = radioRsp_v1_4->rspInfo.error; + + // In DSDS or TSTS, we only check the result if the current slot is IN_SERVICE + // or Emergency_Only. + if (isDsDsEnabled() || isTsTsEnabled()) { + serial = GetRandomSerialNumber(); + radio_v1_4->getVoiceRegistrationState(serial); + EXPECT_EQ(std::cv_status::no_timeout, wait()); + if (isVoiceEmergencyOnly(radioRsp_v1_4->voiceRegResp.regState) || + isVoiceInService(radioRsp_v1_4->voiceRegResp.regState)) { + EXPECT_EQ(RadioError::NONE, rspEmergencyDial); + } + } else { + EXPECT_EQ(RadioError::NONE, rspEmergencyDial); + } // Give some time for modem to establish the emergency call channel. sleep(MODEM_EMERGENCY_CALL_ESTABLISH_TIME); diff --git a/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h b/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h index 53a584545c..8eee811f7e 100644 --- a/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h +++ b/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h @@ -64,6 +64,7 @@ class RadioResponse_v1_4 : public ::android::hardware::radio::V1_4::IRadioRespon // Call hidl_vec<::android::hardware::radio::V1_2::Call> currentCalls; + ::android::hardware::radio::V1_2::VoiceRegStateResult voiceRegResp; // Modem bool isModemEnabled; diff --git a/radio/1.4/vts/functional/radio_response.cpp b/radio/1.4/vts/functional/radio_response.cpp index d0aae47554..3e93bf4d15 100644 --- a/radio/1.4/vts/functional/radio_response.cpp +++ b/radio/1.4/vts/functional/radio_response.cpp @@ -762,8 +762,9 @@ Return RadioResponse_v1_4::getCellInfoListResponse_1_2( Return RadioResponse_v1_4::getVoiceRegistrationStateResponse_1_2( const RadioResponseInfo& info, - const ::android::hardware::radio::V1_2::VoiceRegStateResult& /*voiceRegResponse*/) { + const ::android::hardware::radio::V1_2::VoiceRegStateResult& voiceRegResponse) { rspInfo = info; + voiceRegResp = voiceRegResponse; parent_v1_4.notify(info.serial); return Void(); } From f5b567afab73f5a41a4704ca841f25d9d7a463d4 Mon Sep 17 00:00:00 2001 From: kh0705 Date: Tue, 18 Aug 2020 14:38:38 +0900 Subject: [PATCH 16/27] Keymaster: update the verifyAuthorization call time and delta time in VerificationToken VTS The keymaster function affects the performance of secure os. When considering the swtiching time of the normal world < - > Secure world and the processing delay of the SecureOS by the scheduling policy of the normal world, it is necessary to increase the time. Even though Secure world is no problem, Sometimes there is a possibility of that the test will fail because it is a limited resource normal world. On average, it is performed in a very fast time, but sometimes it takes a lot of time. After many tests, the safe time was measured. Bug: 162115135 Change-Id: I55862204ef71f69bc88c79fe2259f7cb8365699a Signed-off-by: kh0705 --- .../4.0/vts/functional/VerificationTokenTest.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/keymaster/4.0/vts/functional/VerificationTokenTest.cpp b/keymaster/4.0/vts/functional/VerificationTokenTest.cpp index bab1439584..4f0a7a3a14 100644 --- a/keymaster/4.0/vts/functional/VerificationTokenTest.cpp +++ b/keymaster/4.0/vts/functional/VerificationTokenTest.cpp @@ -111,19 +111,19 @@ TEST_P(VerificationTokenTest, TestCreation) { EXPECT_GE(host_time_delta, time_to_sleep) << "We slept for " << time_to_sleep << " ms, the clock must have advanced by that much"; - EXPECT_LE(host_time_delta, time_to_sleep + 20) + EXPECT_LE(host_time_delta, time_to_sleep + 100) << "The verifyAuthorization call took " << (host_time_delta - time_to_sleep) << " ms? That's awful!"; auto km_time_delta = result2.token.timestamp - result1.token.timestamp; // If not too much else is going on on the system, the time delta should be quite close. Allow - // 2 ms of slop just to avoid test flakiness. + // 20 ms of slop just to avoid test flakiness. // // TODO(swillden): see if we can output values so they can be gathered across many runs and // report if times aren't nearly always <1ms apart. - EXPECT_LE(host_time_delta, km_time_delta + 2); - EXPECT_LE(km_time_delta, host_time_delta + 2); + EXPECT_LE(host_time_delta, km_time_delta + 20); + EXPECT_LE(km_time_delta, host_time_delta + 20); ASSERT_EQ(result1.token.mac.size(), result2.token.mac.size()); ASSERT_NE(0, memcmp(result1.token.mac.data(), result2.token.mac.data(), result1.token.mac.size())); @@ -172,14 +172,14 @@ TEST_P(VerificationTokenTest, MacChangesOnChangingTimestamp) { EXPECT_GE(host_time_delta, time_to_sleep) << "We slept for " << time_to_sleep << " ms, the clock must have advanced by that much"; - EXPECT_LE(host_time_delta, time_to_sleep + 20) + EXPECT_LE(host_time_delta, time_to_sleep + 100) << "The verifyAuthorization call took " << (host_time_delta - time_to_sleep) << " ms? That's awful!"; auto km_time_delta = result2.token.timestamp - result1.token.timestamp; - EXPECT_LE(host_time_delta, km_time_delta + 2); - EXPECT_LE(km_time_delta, host_time_delta + 2); + EXPECT_LE(host_time_delta, km_time_delta + 20); + EXPECT_LE(km_time_delta, host_time_delta + 20); ASSERT_EQ(result1.token.mac.size(), result2.token.mac.size()); ASSERT_NE(0, memcmp(result1.token.mac.data(), result2.token.mac.data(), result1.token.mac.size())); From 667ef2c4c710226d69d02000912905786a35f92d Mon Sep 17 00:00:00 2001 From: Treehugger Robot Date: Mon, 10 Aug 2020 19:50:59 +0000 Subject: [PATCH 17/27] Merge "Remove unnecessary type and dup for fd" am: 5428551ba9 am: f8f2391f8e Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/1374049 Change-Id: I4151bc9aa650bbdb5545875d14760455efe62fe7 --- sensors/common/default/2.X/multihal/HalProxy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sensors/common/default/2.X/multihal/HalProxy.cpp b/sensors/common/default/2.X/multihal/HalProxy.cpp index 75ffc17a67..4527c75e31 100644 --- a/sensors/common/default/2.X/multihal/HalProxy.cpp +++ b/sensors/common/default/2.X/multihal/HalProxy.cpp @@ -341,7 +341,7 @@ Return HalProxy::debug(const hidl_handle& fd, const hidl_vec& return Void(); } - android::base::borrowed_fd writeFd = dup(fd->data[0]); + int writeFd = fd->data[0]; std::ostringstream stream; stream << "===HalProxy===" << std::endl; From c40aa186ea6efd18a90183783fb1e0b5ac252aee Mon Sep 17 00:00:00 2001 From: Yu-Han Yang Date: Wed, 26 Aug 2020 13:38:40 -0700 Subject: [PATCH 18/27] Add capability check for satellite blacklist tests Bug: 166251991 Test: on device Change-Id: I27e515a5f2a6676a250f361b17b056a73e209ad3 --- .../2.1/vts/functional/gnss_hal_test_cases.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp index a3d2956199..16e634f2b0 100644 --- a/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp @@ -363,6 +363,12 @@ IGnssConfiguration::BlacklistedSource FindStrongFrequentNonGpsSource( * formerly strongest satellite */ TEST_P(GnssHalTest, BlacklistIndividualSatellites) { + if (!(gnss_cb_->last_capabilities_ & IGnssCallback_2_1::Capabilities::SATELLITE_BLACKLIST)) { + ALOGI("Test BlacklistIndividualSatellites skipped. SATELLITE_BLACKLIST capability not " + "supported."); + return; + } + const int kLocationsToAwait = 3; const int kRetriesToUnBlacklist = 10; @@ -504,6 +510,12 @@ TEST_P(GnssHalTest, BlacklistIndividualSatellites) { * 4a & b) Clean up by turning off location, and send in empty blacklist. */ TEST_P(GnssHalTest, BlacklistConstellationLocationOff) { + if (!(gnss_cb_->last_capabilities_ & IGnssCallback_2_1::Capabilities::SATELLITE_BLACKLIST)) { + ALOGI("Test BlacklistConstellationLocationOff skipped. SATELLITE_BLACKLIST capability not " + "supported."); + return; + } + const int kLocationsToAwait = 3; const int kGnssSvInfoListTimeout = 2; @@ -580,6 +592,12 @@ TEST_P(GnssHalTest, BlacklistConstellationLocationOff) { * 4a & b) Clean up by turning off location, and send in empty blacklist. */ TEST_P(GnssHalTest, BlacklistConstellationLocationOn) { + if (!(gnss_cb_->last_capabilities_ & IGnssCallback_2_1::Capabilities::SATELLITE_BLACKLIST)) { + ALOGI("Test BlacklistConstellationLocationOn skipped. SATELLITE_BLACKLIST capability not " + "supported."); + return; + } + const int kLocationsToAwait = 3; const int kGnssSvInfoListTimeout = 2; From 674b27abc31a9a06aaf661332c012eb7a33219ee Mon Sep 17 00:00:00 2001 From: Nate Jiang Date: Wed, 26 Aug 2020 16:38:19 -0700 Subject: [PATCH 19/27] WifiNanIface: Validate interface before cleanup. Calling invalidate() API twice would lead to fatal error. This commit is to check if interface isValid() before doing other operations in invalidate() API. Bug: 166412651 Test: atest VtsHalWifiNanV1_4TargetTest WifiNanIfaceTest Change-Id: Ia3fc48bb3d98660705bba9a32b7a5845ff7af79f --- wifi/1.4/default/wifi_nan_iface.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wifi/1.4/default/wifi_nan_iface.cpp b/wifi/1.4/default/wifi_nan_iface.cpp index 5764d35ec4..24ffb176e8 100644 --- a/wifi/1.4/default/wifi_nan_iface.cpp +++ b/wifi/1.4/default/wifi_nan_iface.cpp @@ -534,6 +534,9 @@ WifiNanIface::WifiNanIface( } void WifiNanIface::invalidate() { + if (!isValid()) { + return; + } // send commands to HAL to actually disable and destroy interfaces legacy_hal_.lock()->nanDisableRequest(ifname_, 0xFFFF); legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, 0xFFFE, "aware_data0"); From f2eaf2c299762e7debe7820f142ef18b4c130d44 Mon Sep 17 00:00:00 2001 From: Robert Shih Date: Thu, 27 Aug 2020 08:54:38 -0700 Subject: [PATCH 20/27] VtsHalDrm: run tests in single shard Currently drm cert provisioning is performed as an indivdual test case. Other tests (e.g. decrypt tests) have dependency on drm cert provisioning. Bug: 165493235 Test: VtsHalDrmV1_0TargetTest Test: VtsHalDrmV1_1TargetTest Test: VtsHalDrmV1_2TargetTest Test: VtsHalDrmV1_3TargetTest Change-Id: I7aad35747997e6ce5b06919344475e0f2754cd15 --- drm/1.0/vts/functional/AndroidTest.xml | 1 + drm/1.1/vts/functional/AndroidTest.xml | 1 + drm/1.2/vts/functional/AndroidTest.xml | 1 + drm/1.3/vts/functional/AndroidTest.xml | 1 + 4 files changed, 4 insertions(+) diff --git a/drm/1.0/vts/functional/AndroidTest.xml b/drm/1.0/vts/functional/AndroidTest.xml index 92ea7e48dd..02c51cce07 100644 --- a/drm/1.0/vts/functional/AndroidTest.xml +++ b/drm/1.0/vts/functional/AndroidTest.xml @@ -16,6 +16,7 @@