Merge tag 'android-security-11.0.0_r49' into int/11/fp3
Android security 11.0.0 release 49
* tag 'android-security-11.0.0_r49':
audio HAL - fix UAFs
[RESTRICT AUTOMERGE] Fix CryptoPlugin use after free vulnerability.
Fix potential decrypt destPtr overflow.
Fix potential decrypt src pointer overflow.
Change-Id: Idb9fef5844c34e140a9a8b5761e053fa8d626dd2
diff --git a/audio/common/all-versions/default/service/Android.bp b/audio/common/all-versions/default/service/Android.bp
index 3e8b715..e5d4770 100644
--- a/audio/common/all-versions/default/service/Android.bp
+++ b/audio/common/all-versions/default/service/Android.bp
@@ -20,11 +20,19 @@
shared_libs: [
"libcutils",
"libbinder",
+ "libhwbinder",
"libhidlbase",
"liblog",
"libutils",
"libhardware",
],
+ arch : {
+ arm : {
+ cflags: [
+ "-DARCH_ARM_32",
+ ]
+ }
+ },
}
// Legacy service name, use android.hardware.audio.service instead
diff --git a/audio/common/all-versions/default/service/android.hardware.audio.service.rc b/audio/common/all-versions/default/service/android.hardware.audio.service.rc
index f7e1e24..45fef9a 100644
--- a/audio/common/all-versions/default/service/android.hardware.audio.service.rc
+++ b/audio/common/all-versions/default/service/android.hardware.audio.service.rc
@@ -2,7 +2,7 @@
class hal
user audioserver
# media gid needed for /dev/fm (radio) and for /data/misc/media (tee)
- group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct wakelock
+ group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct wakelock context_hub
capabilities BLOCK_SUSPEND
ioprio rt 4
task_profiles ProcessCapacityHigh HighPerformance
diff --git a/audio/common/all-versions/default/service/service.cpp b/audio/common/all-versions/default/service/service.cpp
index 147d062..2801769 100644
--- a/audio/common/all-versions/default/service/service.cpp
+++ b/audio/common/all-versions/default/service/service.cpp
@@ -30,6 +30,18 @@
using InterfacesList = std::vector<std::string>;
+#ifdef ARCH_ARM_32
+//default h/w binder memsize is 1 MB
+#define DEFAULT_HW_BINDER_MEM_SIZE_KB 1024
+
+size_t getHWBinderMmapSize(){
+ int32_t value = DEFAULT_HW_BINDER_MEM_SIZE_KB;
+ value = property_get_int32("persist.vendor.audio.hw.binder.size_kbyte", value);
+ ALOGD("Init hw binder with mem size = %d ", value);
+ return 1024 * value;
+}
+#endif
+
/** Try to register the provided factories in the provided order.
* If any registers successfully, do not register any other and return true.
* If all fail, return false.
@@ -45,6 +57,9 @@
}
int main(int /* argc */, char* /* argv */ []) {
+#ifdef ARCH_ARM_32
+ android::hardware::ProcessState::initWithMmapSize(getHWBinderMmapSize());
+#endif
::android::ProcessState::initWithDriver("/dev/vndbinder");
// start a threadpool for vndbinder interactions
::android::ProcessState::self()->startThreadPool();
diff --git a/authsecret/1.0/vts/functional/VtsHalAuthSecretV1_0TargetTest.cpp b/authsecret/1.0/vts/functional/VtsHalAuthSecretV1_0TargetTest.cpp
index 0bff9df..f27f266 100644
--- a/authsecret/1.0/vts/functional/VtsHalAuthSecretV1_0TargetTest.cpp
+++ b/authsecret/1.0/vts/functional/VtsHalAuthSecretV1_0TargetTest.cpp
@@ -34,11 +34,19 @@
authsecret = IAuthSecret::getService(GetParam());
ASSERT_NE(authsecret, nullptr);
+ // Notify LSS to generate PIN code '1234' and corresponding secret.
+ (void)system("cmd lock_settings set-pin 1234");
+
// All tests must enroll the correct secret first as this cannot be changed
// without a factory reset and the order of tests could change.
authsecret->primaryUserCredential(CORRECT_SECRET);
}
+ static void TearDownTestSuite() {
+ // clean up PIN code after testing
+ (void)system("cmd lock_settings clear --old 1234");
+ }
+
sp<IAuthSecret> authsecret;
hidl_vec<uint8_t> CORRECT_SECRET{61, 93, 124, 240, 5, 0, 7, 201, 9, 129, 11, 12, 0, 14, 0, 16};
hidl_vec<uint8_t> WRONG_SECRET{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
diff --git a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
index 8b68fd6..f1c8f9f 100644
--- a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
+++ b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
@@ -72,6 +72,8 @@
using ::android::hardware::automotive::evs::V1_0::DisplayDesc;
using ::android::hardware::automotive::evs::V1_0::DisplayState;
using ::android::hardware::graphics::common::V1_0::PixelFormat;
+using ::android::frameworks::automotive::display::V1_0::HwDisplayConfig;
+using ::android::frameworks::automotive::display::V1_0::HwDisplayState;
using IEvsCamera_1_0 = ::android::hardware::automotive::evs::V1_0::IEvsCamera;
using IEvsCamera_1_1 = ::android::hardware::automotive::evs::V1_1::IEvsCamera;
using IEvsDisplay_1_0 = ::android::hardware::automotive::evs::V1_0::IEvsDisplay;
@@ -303,11 +305,22 @@
const auto id = 0xFFFFFFFF; // meaningless id
hidl_vec<uint8_t> values;
auto err = pCam->setExtendedInfo_1_1(id, values);
- ASSERT_NE(EvsResult::INVALID_ARG, err);
+ if (isLogicalCam) {
+ // Logical camera device does not support setExtendedInfo
+ // method.
+ ASSERT_EQ(EvsResult::INVALID_ARG, err);
+ } else {
+ ASSERT_NE(EvsResult::INVALID_ARG, err);
+ }
- pCam->getExtendedInfo_1_1(id, [](const auto& result, const auto& data) {
- ASSERT_NE(EvsResult::INVALID_ARG, result);
- ASSERT_EQ(0, data.size());
+
+ pCam->getExtendedInfo_1_1(id, [&isLogicalCam](const auto& result, const auto& data) {
+ if (isLogicalCam) {
+ ASSERT_EQ(EvsResult::INVALID_ARG, result);
+ } else {
+ ASSERT_NE(EvsResult::INVALID_ARG, result);
+ ASSERT_EQ(0, data.size());
+ }
});
// Explicitly close the camera so resources are released right away
@@ -605,7 +618,10 @@
LOG(INFO) << "Display " << targetDisplayId << " is alreay in use.";
// Get the display descriptor
- pDisplay->getDisplayInfo_1_1([](const auto& config, const auto& state) {
+ pDisplay->getDisplayInfo_1_1([](const HwDisplayConfig& config, const HwDisplayState& state) {
+ ASSERT_GT(config.size(), 0);
+ ASSERT_GT(state.size(), 0);
+
android::DisplayConfig* pConfig = (android::DisplayConfig*)config.data();
const auto width = pConfig->resolution.getWidth();
const auto height = pConfig->resolution.getHeight();
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index d9ac239..590adc5 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -108,6 +108,9 @@
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
@@ -134,7 +137,6 @@
local_include_dirs: ["common/include/vhal_v2_0"],
export_include_dirs: ["impl"],
srcs: [
- "impl/vhal_v2_0/EmulatedUserHal.cpp",
"impl/vhal_v2_0/GeneratorHub.cpp",
"impl/vhal_v2_0/JsonFakeValueGenerator.cpp",
"impl/vhal_v2_0/LinearFakeValueGenerator.cpp",
@@ -143,6 +145,7 @@
],
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/VehicleService.cpp b/automotive/vehicle/2.0/default/VehicleService.cpp
index 47133fd..cf1e4ba 100644
--- a/automotive/vehicle/2.0/default/VehicleService.cpp
+++ b/automotive/vehicle/2.0/default/VehicleService.cpp
@@ -22,7 +22,6 @@
#include <android/binder_process.h>
#include <utils/Looper.h>
-#include <vhal_v2_0/EmulatedUserHal.h>
#include <vhal_v2_0/EmulatedVehicleConnector.h>
#include <vhal_v2_0/EmulatedVehicleHal.h>
#include <vhal_v2_0/VehicleHalManager.h>
@@ -34,9 +33,8 @@
int main(int /* argc */, char* /* argv */ []) {
auto store = std::make_unique<VehiclePropertyStore>();
- auto connector = impl::makeEmulatedPassthroughConnector();
- auto userHal = connector->getEmulatedUserHal();
- auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get(), connector.get(), userHal);
+ auto connector = std::make_unique<impl::EmulatedVehicleConnector>();
+ auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get(), connector.get());
auto emulator = std::make_unique<impl::VehicleEmulator>(hal.get());
auto service = std::make_unique<VehicleHalManager>(hal.get());
connector->setValuePool(hal->getValuePool());
diff --git a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
index b09e9bf..dc5d3d3 100644
--- a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
@@ -78,6 +78,7 @@
} else {
ALOGW("Requested config for undefined property: 0x%x", prop);
_hidl_cb(StatusCode::INVALID_ARG, hidl_vec<VehiclePropConfig>());
+ return Void();
}
}
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 16c33b9..dec2d8c 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
@@ -266,6 +266,20 @@
.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),
.access = VehiclePropertyAccess::READ,
.changeMode = VehiclePropertyChangeMode::STATIC,
@@ -403,7 +417,7 @@
.minSampleRate = 1.0f,
.maxSampleRate = 2.0f,
},
- .initialValue = {.floatValues = {100.0f}}}, // units in meters
+ .initialValue = {.floatValues = {50000.0f}}}, // units in meters
{.config =
{
@@ -674,6 +688,12 @@
.prop = toInt(VehicleProperty::GEAR_SELECTION),
.access = VehiclePropertyAccess::READ,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .configArray = {(int)VehicleGear::GEAR_PARK,
+ (int)VehicleGear::GEAR_NEUTRAL,
+ (int)VehicleGear::GEAR_REVERSE,
+ (int)VehicleGear::GEAR_DRIVE, (int)VehicleGear::GEAR_1,
+ (int)VehicleGear::GEAR_2, (int)VehicleGear::GEAR_3,
+ (int)VehicleGear::GEAR_4, (int)VehicleGear::GEAR_5},
},
.initialValue = {.int32Values = {toInt(VehicleGear::GEAR_PARK)}}},
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 ea38cb3..3bdf5a8 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 <cutils/log.h>
#include <utils/SystemClock.h>
-#include "EmulatedUserHal.h"
+#include "UserHalHelper.h"
namespace android {
namespace hardware {
@@ -28,12 +30,35 @@
namespace impl {
-constexpr int INITIAL_USER_INFO = static_cast<int>(VehicleProperty::INITIAL_USER_INFO);
-constexpr int SWITCH_USER = static_cast<int>(VehicleProperty::SWITCH_USER);
-constexpr int CREATE_USER = static_cast<int>(VehicleProperty::CREATE_USER);
-constexpr int REMOVE_USER = static_cast<int>(VehicleProperty::REMOVE_USER);
-constexpr int USER_IDENTIFICATION_ASSOCIATION =
- static_cast<int>(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION);
+namespace {
+
+using android::base::Error;
+using android::base::Result;
+
+constexpr int32_t INITIAL_USER_INFO = static_cast<int32_t>(VehicleProperty::INITIAL_USER_INFO);
+constexpr int32_t SWITCH_USER = static_cast<int32_t>(VehicleProperty::SWITCH_USER);
+constexpr int32_t CREATE_USER = static_cast<int32_t>(VehicleProperty::CREATE_USER);
+constexpr int32_t REMOVE_USER = static_cast<int32_t>(VehicleProperty::REMOVE_USER);
+constexpr int32_t USER_IDENTIFICATION_ASSOCIATION =
+ static_cast<int32_t>(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION);
+
+Result<int32_t> getRequestId(const VehiclePropValue& value) {
+ if (value.value.int32Values.size() < 1) {
+ return Error(static_cast<int>(StatusCode::INVALID_ARG))
+ << "no int32values on " << toString(value);
+ }
+ return value.value.int32Values[0];
+}
+
+Result<SwitchUserMessageType> getSwitchUserMessageType(const VehiclePropValue& value) {
+ if (value.value.int32Values.size() < 2) {
+ return Error(static_cast<int>(StatusCode::INVALID_ARG))
+ << "missing switch user message type " << toString(value);
+ }
+ return user_hal_helper::verifyAndCast<SwitchUserMessageType>(value.value.int32Values[1]);
+}
+
+} // namespace
bool EmulatedUserHal::isSupported(int32_t prop) {
switch (prop) {
@@ -48,7 +73,7 @@
}
}
-android::base::Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetProperty(
+Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetProperty(
const VehiclePropValue& value) {
ALOGV("onSetProperty(): %s", toString(value).c_str());
@@ -65,12 +90,12 @@
case USER_IDENTIFICATION_ASSOCIATION:
return onSetUserIdentificationAssociation(value);
default:
- return android::base::Error(static_cast<int>(StatusCode::INVALID_ARG))
+ return Error(static_cast<int>(StatusCode::INVALID_ARG))
<< "Unsupported property: " << toString(value);
}
}
-android::base::Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onGetProperty(
+Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onGetProperty(
const VehiclePropValue& value) {
ALOGV("onGetProperty(%s)", toString(value).c_str());
switch (value.prop) {
@@ -79,42 +104,41 @@
case CREATE_USER:
case REMOVE_USER:
ALOGE("onGetProperty(): %d is only supported on SET", value.prop);
- return android::base::Error(static_cast<int>(StatusCode::INVALID_ARG))
- << "only supported on SET";
+ return Error(static_cast<int>(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<int>(StatusCode::INVALID_ARG))
- << "not supported by User HAL";
+ return Error(static_cast<int>(StatusCode::INVALID_ARG)) << "not supported by User HAL";
}
}
-android::base::Result<std::unique_ptr<VehiclePropValue>>
-EmulatedUserHal::onGetUserIdentificationAssociation(const VehiclePropValue& value) {
- if (mSetUserIdentificationAssociationResponseFromCmd != nullptr) {
- ALOGI("get(USER_IDENTIFICATION_ASSOCIATION): returning %s",
- toString(*mSetUserIdentificationAssociationResponseFromCmd).c_str());
- auto newValue = std::unique_ptr<VehiclePropValue>(
- new VehiclePropValue(*mSetUserIdentificationAssociationResponseFromCmd));
+Result<std::unique_ptr<VehiclePropValue>> 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<VehiclePropValue>(
+ 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<std::unique_ptr<VehiclePropValue>>
-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<int>(StatusCode::INVALID_ARG))
- << "no int32values on " << toString(value);
+Result<std::unique_ptr<VehiclePropValue>> 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,85 +148,82 @@
}
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<VehiclePropValue>(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<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetSwitchUserResponse(
+Result<std::unique_ptr<VehiclePropValue>> 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<int>(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 (*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());
+ return std::unique_ptr<VehiclePropValue>(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 {};
}
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<SwitchUserMessageType>(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<VehiclePropValue>(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<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetCreateUserResponse(
+Result<std::unique_ptr<VehiclePropValue>> 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<int>(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) {
@@ -212,33 +233,28 @@
}
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<VehiclePropValue>(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<std::unique_ptr<VehiclePropValue>>
-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<int>(StatusCode::INVALID_ARG))
- << "no int32values on " << toString(value);
+Result<std::unique_ptr<VehiclePropValue>> 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) {
@@ -249,28 +265,26 @@
}
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<VehiclePropValue>(
new VehiclePropValue(*mSetUserIdentificationAssociationResponseFromCmd));
- return sendUserHalResponse(std::move(copy), requestId);
+ return sendUserHalResponse(std::move(copy), *requestId);
}
-
// Returns default response
return defaultUserIdentificationAssociation(value);
}
-android::base::Result<std::unique_ptr<VehiclePropValue>>
-EmulatedUserHal::defaultUserIdentificationAssociation(const VehiclePropValue& request) {
+Result<std::unique_ptr<VehiclePropValue>> 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<int>(StatusCode::NOT_AVAILABLE)) << "not set by lshal";
+ return Error(static_cast<int>(StatusCode::NOT_AVAILABLE)) << "not set by lshal";
}
-android::base::Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::sendUserHalResponse(
+Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::sendUserHalResponse(
std::unique_ptr<VehiclePropValue> response, int32_t requestId) {
switch (response->areaId) {
case 1:
@@ -284,17 +298,16 @@
case 3:
ALOGD("not generating a property change event because of lshal prop: %s",
toString(*response).c_str());
- return android::base::Error(static_cast<int>(StatusCode::NOT_AVAILABLE))
+ return Error(static_cast<int>(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<int>(StatusCode::INTERNAL_ERROR))
+ return Error(static_cast<int>(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/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
index 7f9362f..ed3f4a2 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
@@ -35,13 +35,33 @@
namespace impl {
-class EmulatedPassthroughConnector : public PassthroughConnector {
- public:
- bool onDump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
-};
+EmulatedUserHal* EmulatedVehicleConnector::getEmulatedUserHal() {
+ return &mEmulatedUserHal;
+}
-bool EmulatedPassthroughConnector::onDump(const hidl_handle& handle,
- const hidl_vec<hidl_string>& options) {
+StatusCode EmulatedVehicleConnector::onSetProperty(const VehiclePropValue& value,
+ bool updateStatus) {
+ if (mEmulatedUserHal.isSupported(value.prop)) {
+ LOG(INFO) << "onSetProperty(): property " << value.prop << " will be handled by UserHal";
+
+ const auto& ret = mEmulatedUserHal.onSetProperty(value);
+ if (!ret.ok()) {
+ LOG(ERROR) << "onSetProperty(): HAL returned error: " << ret.error().message();
+ return StatusCode(ret.error().code());
+ }
+ auto updatedValue = ret.value().get();
+ if (updatedValue != nullptr) {
+ LOG(INFO) << "onSetProperty(): updating property returned by HAL: "
+ << toString(*updatedValue);
+ onPropertyValueFromCar(*updatedValue, updateStatus);
+ }
+ return StatusCode::OK;
+ }
+ return this->VehicleHalServer::onSetProperty(value, updateStatus);
+}
+
+bool EmulatedVehicleConnector::onDump(const hidl_handle& handle,
+ const hidl_vec<hidl_string>& options) {
int fd = handle->data[0];
if (options.size() > 0) {
@@ -68,10 +88,6 @@
return true;
}
-PassthroughConnectorPtr makeEmulatedPassthroughConnector() {
- return std::make_unique<EmulatedPassthroughConnector>();
-}
-
} // namespace impl
} // namespace V2_0
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h
index 57cbb8b..4c6c661 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h
@@ -19,6 +19,7 @@
#include <vhal_v2_0/VehicleConnector.h>
+#include "EmulatedUserHal.h"
#include "VehicleHalClient.h"
#include "VehicleHalServer.h"
@@ -30,10 +31,20 @@
namespace impl {
-using PassthroughConnector = IPassThroughConnector<VehicleHalClient, VehicleHalServer>;
-using PassthroughConnectorPtr = std::unique_ptr<PassthroughConnector>;
+class EmulatedVehicleConnector : public IPassThroughConnector<VehicleHalClient, VehicleHalServer> {
+ public:
+ EmulatedVehicleConnector() {}
-PassthroughConnectorPtr makeEmulatedPassthroughConnector();
+ EmulatedUserHal* getEmulatedUserHal();
+
+ // Methods from VehicleHalServer
+ StatusCode onSetProperty(const VehiclePropValue& value, bool updateStatus) override;
+
+ bool onDump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
+
+ private:
+ EmulatedUserHal mEmulatedUserHal;
+};
} // 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 a0b566d..1d51600 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
@@ -15,13 +15,8 @@
*/
#define LOG_TAG "DefaultVehicleHal_v2_0"
-#include <android-base/macros.h>
-#include <android-base/properties.h>
#include <android/log.h>
-#include <dirent.h>
-#include <sys/system_properties.h>
-#include <fstream>
-#include <regex>
+#include <android-base/macros.h>
#include "EmulatedVehicleHal.h"
#include "JsonFakeValueGenerator.h"
@@ -107,30 +102,6 @@
mVehicleClient->registerPropertyValueCallback(std::bind(&EmulatedVehicleHal::onPropertyValue,
this, std::placeholders::_1,
std::placeholders::_2));
-
- mInitVhalValueOverride =
- android::base::GetBoolProperty("persist.vendor.vhal_init_value_override", false);
- if (mInitVhalValueOverride) {
- getAllPropertiesOverride();
- }
-}
-
-void EmulatedVehicleHal::getAllPropertiesOverride() {
- if (auto dir = opendir("/vendor/etc/vhaloverride/")) {
- std::regex reg_json(".*[.]json", std::regex::icase);
- while (auto f = readdir(dir)) {
- if (!regex_match(f->d_name, reg_json)) {
- continue;
- }
- std::string file = "/vendor/etc/vhaloverride/" + std::string(f->d_name);
- JsonFakeValueGenerator tmpGenerator(file);
-
- std::vector<VehiclePropValue> propvalues = tmpGenerator.getAllEvents();
- mVehiclePropertiesOverride.insert(std::end(mVehiclePropertiesOverride),
- std::begin(propvalues), std::end(propvalues));
- }
- closedir(dir);
- }
}
VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::get(
@@ -239,14 +210,6 @@
return StatusCode::NOT_AVAILABLE;
}
- if (mInEmulator && propValue.prop == toInt(VehicleProperty::DISPLAY_BRIGHTNESS)) {
- // Emulator does not support remote brightness control, b/139959479
- // do not send it down so that it does not bring unnecessary property change event
- // return other error code, such NOT_AVAILABLE, causes Emulator to be freezing
- // TODO: return StatusCode::NOT_AVAILABLE once the above issue is fixed
- return StatusCode::OK;
- }
-
/**
* After checking all conditions, such as the property is available, a real vhal will
* sent the events to Car ECU to take actions.
@@ -272,17 +235,6 @@
return false;
}
-// determine if it's running inside Android Emulator
-static bool isInEmulator() {
- char propValue[PROP_VALUE_MAX];
- bool isEmulator = (__system_property_get("ro.kernel.qemu", propValue) != 0);
- if (!isEmulator) {
- isEmulator = (__system_property_get("ro.hardware", propValue) != 0) &&
- (!strcmp(propValue, "ranchu") || !strcmp(propValue, "goldfish"));
- }
- return isEmulator;
-}
-
// Parse supported properties list and generate vector of property values to hold current values.
void EmulatedVehicleHal::onCreate() {
static constexpr bool shouldUpdateStatus = true;
@@ -327,21 +279,12 @@
}
} else {
prop.value = it.initialValue;
- if (mInitVhalValueOverride) {
- for (auto& itOverride : mVehiclePropertiesOverride) {
- if (itOverride.prop == cfg.prop) {
- prop.value = itOverride.value;
- }
- }
- }
}
mPropStore->writeValue(prop, shouldUpdateStatus);
}
}
initObd2LiveFrame(*mPropStore->getConfigOrDie(OBD2_LIVE_FRAME));
initObd2FreezeFrame(*mPropStore->getConfigOrDie(OBD2_FREEZE_FRAME));
- mInEmulator = isInEmulator();
- ALOGD("mInEmulator=%s", mInEmulator ? "true" : "false");
}
std::vector<VehiclePropConfig> EmulatedVehicleHal::listProperties() {
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 eb38d7d..30f6bfa 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
@@ -63,7 +63,6 @@
// Methods from EmulatedVehicleHalIface
bool setPropertyFromVehicle(const VehiclePropValue& propValue) override;
std::vector<VehiclePropValue> getAllProperties() const override;
- void getAllPropertiesOverride();
private:
constexpr std::chrono::nanoseconds hertzToNanoseconds(float hz) const {
@@ -88,9 +87,6 @@
std::unordered_set<int32_t> mHvacPowerProps;
RecurrentTimer mRecurrentTimer;
VehicleHalClient* mVehicleClient;
- bool mInEmulator;
- bool mInitVhalValueOverride;
- std::vector<VehiclePropValue> mVehiclePropertiesOverride;
EmulatedUserHal* mEmulatedUserHal;
};
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.cpp
index 548285a..9be9ea7 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.cpp
@@ -31,6 +31,14 @@
GeneratorHub::GeneratorHub(const OnHalEvent& onHalEvent)
: mOnHalEvent(onHalEvent), mThread(&GeneratorHub::run, this) {}
+GeneratorHub::~GeneratorHub() {
+ mShuttingDownFlag.store(true);
+ mCond.notify_all();
+ if (mThread.joinable()) {
+ mThread.join();
+ }
+}
+
void GeneratorHub::registerGenerator(int32_t cookie, FakeValueGeneratorPtr generator) {
{
std::lock_guard<std::mutex> g(mLock);
@@ -58,15 +66,18 @@
}
void GeneratorHub::run() {
- while (true) {
+ while (!mShuttingDownFlag.load()) {
std::unique_lock<std::mutex> g(mLock);
// Pop events whose generator does not exist (may be already unregistered)
while (!mEventQueue.empty()
&& mGenerators.find(mEventQueue.top().cookie) == mGenerators.end()) {
mEventQueue.pop();
}
- // Wait until event queue is not empty
- mCond.wait(g, [this] { return !mEventQueue.empty(); });
+ // Wait until event queue is not empty or shutting down flag is set
+ mCond.wait(g, [this] { return !mEventQueue.empty() || mShuttingDownFlag.load(); });
+ if (mShuttingDownFlag.load()) {
+ break;
+ }
const VhalEvent& curEvent = mEventQueue.top();
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.h
index dcf6a4f..b25dbf1 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.h
@@ -58,7 +58,7 @@
public:
GeneratorHub(const OnHalEvent& onHalEvent);
- ~GeneratorHub() = default;
+ ~GeneratorHub();
/**
* Register a new generator. The generator will be discarded if it could not produce next event.
@@ -84,6 +84,7 @@
mutable std::mutex mLock;
std::condition_variable mCond;
std::thread mThread;
+ std::atomic<bool> mShuttingDownFlag{false};
};
} // namespace impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp
index 890eb33..8677f83 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp
@@ -48,22 +48,6 @@
mNumOfIterations = v.int32Values.size() < 2 ? -1 : v.int32Values[1];
}
-JsonFakeValueGenerator::JsonFakeValueGenerator(std::string path) {
- std::ifstream ifs(path);
- if (!ifs) {
- ALOGE("%s: couldn't open %s for parsing.", __func__, path.c_str());
- }
- mGenCfg = {
- .index = 0,
- .events = parseFakeValueJson(ifs),
- };
- mNumOfIterations = mGenCfg.events.size();
-}
-
-std::vector<VehiclePropValue> JsonFakeValueGenerator::getAllEvents() {
- return mGenCfg.events;
-}
-
VehiclePropValue JsonFakeValueGenerator::nextEvent() {
VehiclePropValue generatedValue;
if (!hasNext()) {
@@ -125,7 +109,6 @@
Json::Value rawEventValue = rawEvent["value"];
auto& value = event.value;
- int32_t count;
switch (getPropType(event.prop)) {
case VehiclePropertyType::BOOLEAN:
case VehiclePropertyType::INT32:
@@ -143,13 +126,6 @@
case VehiclePropertyType::STRING:
value.stringValue = rawEventValue.asString();
break;
- case VehiclePropertyType::INT32_VEC:
- value.int32Values.resize(rawEventValue.size());
- count = 0;
- for (auto& it : rawEventValue) {
- value.int32Values[count++] = it.asInt();
- }
- break;
case VehiclePropertyType::MIXED:
copyMixedValueJson(value, rawEventValue);
if (isDiagnosticProperty(event.prop)) {
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h
index dc8ff66..70575f7 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h
@@ -41,12 +41,9 @@
public:
JsonFakeValueGenerator(const VehiclePropValue& request);
- JsonFakeValueGenerator(std::string path);
-
~JsonFakeValueGenerator() = default;
VehiclePropValue nextEvent();
- std::vector<VehiclePropValue> getAllEvents();
bool hasNext();
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 36f2534..0ee1835 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,10 +41,6 @@
return mValuePool;
}
-EmulatedUserHal* VehicleHalServer::getEmulatedUserHal() {
- return &mEmulatedUserHal;
-}
-
void VehicleHalServer::setValuePool(VehiclePropValuePool* valuePool) {
if (!valuePool) {
LOG(WARNING) << __func__ << ": Setting value pool to nullptr!";
@@ -185,22 +181,6 @@
}
StatusCode VehicleHalServer::onSetProperty(const VehiclePropValue& value, bool updateStatus) {
- if (mEmulatedUserHal.isSupported(value.prop)) {
- LOG(INFO) << "onSetProperty(): property " << value.prop << " will be handled by UserHal";
-
- const auto& ret = mEmulatedUserHal.onSetProperty(value);
- if (!ret.ok()) {
- LOG(ERROR) << "onSetProperty(): HAL returned error: " << ret.error().message();
- return StatusCode(ret.error().code());
- }
- auto updatedValue = ret.value().get();
- if (updatedValue != nullptr) {
- LOG(INFO) << "onSetProperty(): updating property returned by HAL: "
- << toString(*updatedValue);
- onPropertyValueFromCar(*updatedValue, updateStatus);
- }
- return StatusCode::OK;
- }
LOG(DEBUG) << "onSetProperty(" << value.prop << ")";
// Some properties need to be treated non-trivially
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 fca78bc..117eadb 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
@@ -19,7 +19,6 @@
#include <vhal_v2_0/VehicleObjectPool.h>
#include <vhal_v2_0/VehicleServer.h>
-#include "EmulatedUserHal.h"
#include "GeneratorHub.h"
namespace android::hardware::automotive::vehicle::V2_0::impl {
@@ -38,8 +37,6 @@
// Set the Property Value Pool used in this server
void setValuePool(VehiclePropValuePool* valuePool);
- EmulatedUserHal* getEmulatedUserHal();
-
private:
using VehiclePropValuePtr = recyclable_ptr<VehiclePropValue>;
@@ -56,11 +53,6 @@
VehiclePropValuePtr createHwInputKeyProp(VehicleHwKeyInputAction action, int32_t keyCode,
int32_t targetDisplay);
- // data members
-
- protected:
- EmulatedUserHal mEmulatedUserHal;
-
private:
GeneratorHub mGeneratorHub{
std::bind(&VehicleHalServer::onFakeValueGenerated, this, std::placeholders::_1)};
diff --git a/automotive/vehicle/2.0/utils/Android.bp b/automotive/vehicle/2.0/utils/Android.bp
new file mode 100644
index 0000000..e354634
--- /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 0000000..abf59b7
--- /dev/null
+++ b/automotive/vehicle/2.0/utils/UserHalHelper.cpp
@@ -0,0 +1,362 @@
+/*
+ * 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 <log/log.h>
+#include <utils/SystemClock.h>
+
+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;
+
+Result<void> verifyPropValue(const VehiclePropValue& propValue, VehicleProperty vehicleProperty,
+ size_t minInt32Values) {
+ auto prop = verifyAndCast<VehicleProperty>(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<void> parseUserInfo(const hidl_vec<int32_t>& 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<UserFlags>(int32Values[startPos + 1]);
+ if (!userFlags.ok()) {
+ return Error() << "Invalid user flags: " << userFlags.error();
+ }
+ userInfo->flags = *userFlags;
+ return {};
+}
+
+Result<void> parseUsersInfo(const hidl_vec<int32_t>& 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<size_t>(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<void> parseUserAssociationTypes(
+ const hidl_vec<int32_t>& int32Values, size_t startPos, size_t numberAssociationTypes,
+ hidl_vec<UserIdentificationAssociationType>* 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<size_t>(numberAssociationTypes); ++i) {
+ size_t pos = startPos + i;
+ auto type = verifyAndCast<UserIdentificationAssociationType>(int32Values[pos]);
+ if (!type.ok()) {
+ return Error() << "Invalid association type in query '" << i << "': " << type.error();
+ }
+ (*associationTypes)[i] = *type;
+ }
+ return {};
+}
+
+Result<void> parseUserAssociations(const hidl_vec<int32_t>& int32Values, size_t startPos,
+ size_t numberAssociations,
+ hidl_vec<UserIdentificationSetAssociation>* 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<size_t>(numberAssociations); ++i) {
+ size_t pos = startPos + (kNumFieldsPerSetAssociation * i);
+ auto type = verifyAndCast<UserIdentificationAssociationType>(int32Values[pos]);
+ if (!type.ok()) {
+ return Error() << "Invalid association type in request '" << i << "': " << type.error();
+ }
+ (*associations)[i].type = *type;
+ auto value = verifyAndCast<UserIdentificationAssociationSetValue>(int32Values[pos + 1]);
+ if (!value.ok()) {
+ return Error() << "Invalid association set value in request '" << i
+ << "': " << value.error();
+ }
+ (*associations)[i].value = *value;
+ }
+ return {};
+}
+
+} // namespace
+
+template <typename T>
+Result<T> verifyAndCast(int32_t value) {
+ T castValue = static_cast<T>(value);
+ for (const auto& v : hidl_enum_range<T>()) {
+ if (castValue == v) {
+ return castValue;
+ }
+ }
+ return Error() << "Value " << value << " not in enum values";
+}
+
+Result<InitialUserInfoRequest> 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<InitialUserInfoRequestType>(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<SwitchUserRequest> toSwitchUserRequest(const VehiclePropValue& propValue) {
+ auto ret = verifyPropValue(propValue, VehicleProperty::SWITCH_USER, 2);
+ if (!ret.ok()) {
+ return ret.error();
+ }
+ SwitchUserRequest request;
+ auto messageType = verifyAndCast<SwitchUserMessageType>(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)
+ << " message type 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<CreateUserRequest> 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<RemoveUserRequest> 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<UserIdentificationGetRequest> 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<UserIdentificationSetRequest> 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<VehiclePropValue> 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<VehiclePropValue>(new VehiclePropValue());
+ propValue->prop = static_cast<int32_t>(VehicleProperty::SWITCH_USER);
+ propValue->timestamp = elapsedRealtimeNano();
+ propValue->value.int32Values.resize(3);
+ propValue->value.int32Values[0] = static_cast<int32_t>(request.requestId);
+ propValue->value.int32Values[1] = static_cast<int32_t>(request.messageType);
+ propValue->value.int32Values[2] = static_cast<int32_t>(request.targetUser.userId);
+ return propValue;
+}
+
+std::unique_ptr<VehiclePropValue> toVehiclePropValue(const InitialUserInfoResponse& response) {
+ auto propValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue());
+ propValue->prop = static_cast<int32_t>(VehicleProperty::INITIAL_USER_INFO);
+ propValue->timestamp = elapsedRealtimeNano();
+ propValue->value.int32Values.resize(4);
+ propValue->value.int32Values[0] = static_cast<int32_t>(response.requestId);
+ propValue->value.int32Values[1] = static_cast<int32_t>(response.action);
+ propValue->value.int32Values[2] = static_cast<int32_t>(response.userToSwitchOrCreate.userId);
+ propValue->value.int32Values[3] = static_cast<int32_t>(response.userToSwitchOrCreate.flags);
+ propValue->value.stringValue = std::string(response.userLocales) + std::string(kSeparator) +
+ std::string(response.userNameToCreate);
+ return propValue;
+}
+
+std::unique_ptr<VehiclePropValue> toVehiclePropValue(const SwitchUserResponse& response) {
+ auto propValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue());
+ propValue->prop = static_cast<int32_t>(VehicleProperty::SWITCH_USER);
+ propValue->timestamp = elapsedRealtimeNano();
+ propValue->value.int32Values.resize(3);
+ propValue->value.int32Values[0] = static_cast<int32_t>(response.requestId);
+ propValue->value.int32Values[1] = static_cast<int32_t>(response.messageType);
+ propValue->value.int32Values[2] = static_cast<int32_t>(response.status);
+ if (response.status == SwitchUserStatus::FAILURE) {
+ propValue->value.stringValue = response.errorMessage;
+ }
+ return propValue;
+}
+
+std::unique_ptr<VehiclePropValue> toVehiclePropValue(const CreateUserResponse& response) {
+ auto propValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue());
+ propValue->prop = static_cast<int32_t>(VehicleProperty::CREATE_USER);
+ propValue->timestamp = elapsedRealtimeNano();
+ propValue->value.int32Values.resize(2);
+ propValue->value.int32Values[0] = static_cast<int32_t>(response.requestId);
+ propValue->value.int32Values[1] = static_cast<int32_t>(response.status);
+ if (response.status == CreateUserStatus::FAILURE) {
+ propValue->value.stringValue = response.errorMessage;
+ }
+ return propValue;
+}
+
+std::unique_ptr<VehiclePropValue> toVehiclePropValue(const UserIdentificationResponse& response) {
+ auto propValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue());
+ propValue->prop = static_cast<int32_t>(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION);
+ propValue->timestamp = elapsedRealtimeNano();
+ propValue->value.int32Values.resize(2 + (response.numberAssociation * 2));
+ propValue->value.int32Values[0] = static_cast<int32_t>(response.requestId);
+ propValue->value.int32Values[1] = static_cast<int32_t>(response.numberAssociation);
+ for (size_t i = 0; i < static_cast<size_t>(response.numberAssociation); ++i) {
+ size_t int32ValuesPos = 2 + (2 * i);
+ propValue->value.int32Values[int32ValuesPos] =
+ static_cast<int32_t>(response.associations[i].type);
+ propValue->value.int32Values[int32ValuesPos + 1] =
+ static_cast<int32_t>(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 0000000..fad7145
--- /dev/null
+++ b/automotive/vehicle/2.0/utils/UserHalHelper.h
@@ -0,0 +1,67 @@
+/*
+ * 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 <android-base/result.h>
+#include <android/hardware/automotive/vehicle/2.0/types.h>
+
+#include <functional>
+#include <memory>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+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 <typename T>
+android::base::Result<T> 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<InitialUserInfoRequest> toInitialUserInfoRequest(
+ const VehiclePropValue& propValue);
+android::base::Result<SwitchUserRequest> toSwitchUserRequest(const VehiclePropValue& propValue);
+android::base::Result<CreateUserRequest> toCreateUserRequest(const VehiclePropValue& propValue);
+android::base::Result<RemoveUserRequest> toRemoveUserRequest(const VehiclePropValue& propValue);
+android::base::Result<UserIdentificationGetRequest> toUserIdentificationGetRequest(
+ const VehiclePropValue& propValue);
+android::base::Result<UserIdentificationSetRequest> 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<VehiclePropValue> toVehiclePropValue(const SwitchUserRequest& request);
+std::unique_ptr<VehiclePropValue> toVehiclePropValue(const InitialUserInfoResponse& response);
+std::unique_ptr<VehiclePropValue> toVehiclePropValue(const SwitchUserResponse& response);
+std::unique_ptr<VehiclePropValue> toVehiclePropValue(const CreateUserResponse& response);
+std::unique_ptr<VehiclePropValue> 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 0000000..7da87a2
--- /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 <gtest/gtest.h>
+
+#include <cstdint>
+
+#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<int32_t>(VehicleProperty::INITIAL_USER_INFO);
+constexpr int32_t SWITCH_USER = static_cast<int32_t>(VehicleProperty::SWITCH_USER);
+constexpr int32_t CREATE_USER = static_cast<int32_t>(VehicleProperty::CREATE_USER);
+constexpr int32_t REMOVE_USER = static_cast<int32_t>(VehicleProperty::REMOVE_USER);
+constexpr int32_t USER_IDENTIFICATION_ASSOCIATION =
+ static_cast<int32_t>(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION);
+
+constexpr int32_t FIRST_BOOT_AFTER_OTA =
+ static_cast<int32_t>(InitialUserInfoRequestType::FIRST_BOOT_AFTER_OTA);
+constexpr int32_t LEGACY_ANDROID_SWITCH =
+ static_cast<int32_t>(SwitchUserMessageType::LEGACY_ANDROID_SWITCH);
+constexpr int32_t VEHICLE_REQUEST = static_cast<int32_t>(SwitchUserMessageType::VEHICLE_REQUEST);
+
+constexpr int32_t GUEST_USER = static_cast<int32_t>(UserFlags::GUEST);
+constexpr int32_t NONE_USER = static_cast<int32_t>(UserFlags::NONE);
+constexpr int32_t SYSTEM_USER = static_cast<int32_t>(UserFlags::SYSTEM);
+
+constexpr int32_t USER_ID_ASSOC_KEY_FOB =
+ static_cast<int32_t>(UserIdentificationAssociationType::KEY_FOB);
+constexpr int32_t USER_ID_ASSOC_CUSTOM_1 =
+ static_cast<int32_t>(UserIdentificationAssociationType::CUSTOM_1);
+
+constexpr int32_t USER_ID_ASSOC_SET_CURRENT_USER =
+ static_cast<int32_t>(UserIdentificationAssociationSetValue::ASSOCIATE_CURRENT_USER);
+constexpr int32_t USER_ID_ASSOC_UNSET_CURRENT_USER =
+ static_cast<int32_t>(UserIdentificationAssociationSetValue::DISASSOCIATE_CURRENT_USER);
+
+constexpr int32_t USER_ID_ASSOC_CURRENT_USER =
+ static_cast<int32_t>(UserIdentificationAssociationValue::ASSOCIATED_CURRENT_USER);
+constexpr int32_t USER_ID_ASSOC_NO_USER =
+ static_cast<int32_t>(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<int32_t>(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<int32_t>(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<int32_t>(SwitchUserMessageType::VEHICLE_RESPONSE),
+ static_cast<int32_t>(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<int32_t>(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
diff --git a/bluetooth/audio/2.0/default/session/BluetoothAudioSupportedCodecsDB.cpp b/bluetooth/audio/2.0/default/session/BluetoothAudioSupportedCodecsDB.cpp
index 6ea61e1..c368197 100644
--- a/bluetooth/audio/2.0/default/session/BluetoothAudioSupportedCodecsDB.cpp
+++ b/bluetooth/audio/2.0/default/session/BluetoothAudioSupportedCodecsDB.cpp
@@ -74,7 +74,7 @@
.objectType = AacObjectType::MPEG2_LC,
.sampleRate = SampleRate::RATE_44100,
.channelMode = ChannelMode::STEREO,
- .variableBitRateEnabled = AacVariableBitRate::DISABLED,
+ .variableBitRateEnabled = AacVariableBitRate::ENABLED,
.bitsPerSample = BitsPerSample::BITS_16};
// LDAC: mSampleRate:(44100|48000|88200|96000), mBitsPerSample:(16|24|32),
diff --git a/boot/1.0/default/Android.bp b/boot/1.0/default/Android.bp
index fdf7a1e..e6d46be 100644
--- a/boot/1.0/default/Android.bp
+++ b/boot/1.0/default/Android.bp
@@ -30,6 +30,13 @@
"libhidlbase",
"libutils",
"android.hardware.boot@1.0",
+ "libhwbinder",
],
-
+ arch: {
+ arm: {
+ cflags: [
+ "-DARCH_ARM_32"
+ ],
+ },
+ },
}
diff --git a/boot/1.0/default/service.cpp b/boot/1.0/default/service.cpp
index f3996ef..2b50740 100644
--- a/boot/1.0/default/service.cpp
+++ b/boot/1.0/default/service.cpp
@@ -17,10 +17,14 @@
#include <android/hardware/boot/1.0/IBootControl.h>
#include <hidl/LegacySupport.h>
+#include <hwbinder/ProcessState.h>
using ::android::hardware::boot::V1_0::IBootControl;
using android::hardware::defaultPassthroughServiceImplementation;
int main (int /* argc */, char * /* argv */ []) {
+#ifdef ARCH_ARM_32
+ android::hardware::ProcessState::initWithMmapSize((size_t)8192);
+#endif
return defaultPassthroughServiceImplementation<IBootControl>();
}
diff --git a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
index d170a6d..694d52a 100644
--- a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
+++ b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
@@ -116,7 +116,10 @@
};
static void printSkipped(std::string msg) {
- std::cout << "[ SKIPPED ] " << msg << std::endl;
+ const auto testInfo = testing::UnitTest::GetInstance()->current_test_info();
+ std::cout << "[ SKIPPED ] " << testInfo->test_case_name() << "." << testInfo->name()
+ << std::endl;
+ std::cout << msg << std::endl;
}
MATCHER_P(InfoHasId, id,
@@ -428,8 +431,9 @@
ProgramInfo infoCb = {};
EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChanged_,
InfoHasId(utils::make_identifier(IdentifierType::AMFM_FREQUENCY, freq)))
- .Times(AnyNumber())
- .WillOnce(DoAll(SaveArg<0>(&infoCb), testing::Return(ByMove(Void()))));
+ .Times(AnyNumber())
+ .WillOnce(DoAll(SaveArg<0>(&infoCb), testing::Return(ByMove(Void()))))
+ .WillRepeatedly(testing::InvokeWithoutArgs([] { return Void(); }));
auto result = mSession->tune(sel);
// expect a failure if it's not supported
diff --git a/camera/common/1.0/default/CameraModule.cpp b/camera/common/1.0/default/CameraModule.cpp
index 86f26e4..188b4be 100644
--- a/camera/common/1.0/default/CameraModule.cpp
+++ b/camera/common/1.0/default/CameraModule.cpp
@@ -267,6 +267,22 @@
return res;
}
+int CameraModule::getCameraDeviceVersion(int cameraId, uint32_t* version) {
+ ATRACE_CALL();
+ int ret;
+ if (getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_5 &&
+ mModule->get_camera_device_version != NULL) {
+ ret = mModule->get_camera_device_version(cameraId, version);
+ } else {
+ struct camera_info info;
+ ret = getCameraInfo(cameraId, &info);
+ if (ret == OK) {
+ *version = info.device_version;
+ }
+ }
+ return ret;
+}
+
int CameraModule::getCameraInfo(int cameraId, struct camera_info *info) {
ATRACE_CALL();
Mutex::Autolock lock(mCameraInfoLock);
@@ -367,11 +383,9 @@
int CameraModule::getDeviceVersion(int cameraId) {
ssize_t index = mDeviceVersionMap.indexOfKey(cameraId);
if (index == NAME_NOT_FOUND) {
- int deviceVersion;
+ uint32_t deviceVersion;
if (getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_0) {
- struct camera_info info;
- getCameraInfo(cameraId, &info);
- deviceVersion = info.device_version;
+ getCameraDeviceVersion(cameraId, &deviceVersion);
} else {
deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
}
@@ -529,24 +543,28 @@
}
void CameraModule::removeCamera(int cameraId) {
- std::unordered_set<std::string> physicalIds;
- camera_metadata_t *metadata = const_cast<camera_metadata_t*>(
- mCameraInfoMap.valueFor(cameraId).static_camera_characteristics);
- common::V1_0::helper::CameraMetadata hidlMetadata(metadata);
+ // Skip HAL1 devices which isn't cached in mCameraInfoMap and don't advertise
+ // static_camera_characteristics
+ if (getDeviceVersion(cameraId) >= CAMERA_DEVICE_API_VERSION_3_0) {
+ std::unordered_set<std::string> physicalIds;
+ camera_metadata_t *metadata = const_cast<camera_metadata_t*>(
+ mCameraInfoMap.valueFor(cameraId).static_camera_characteristics);
+ common::V1_0::helper::CameraMetadata hidlMetadata(metadata);
- if (isLogicalMultiCamera(hidlMetadata, &physicalIds)) {
- for (const auto& id : physicalIds) {
- int idInt = std::stoi(id);
- if (mPhysicalCameraInfoMap.indexOfKey(idInt) >= 0) {
- free_camera_metadata(mPhysicalCameraInfoMap[idInt]);
- mPhysicalCameraInfoMap.removeItem(idInt);
- } else {
- ALOGE("%s: Cannot find corresponding static metadata for physical id %s",
- __FUNCTION__, id.c_str());
+ if (isLogicalMultiCamera(hidlMetadata, &physicalIds)) {
+ for (const auto& id : physicalIds) {
+ int idInt = std::stoi(id);
+ if (mPhysicalCameraInfoMap.indexOfKey(idInt) >= 0) {
+ free_camera_metadata(mPhysicalCameraInfoMap[idInt]);
+ mPhysicalCameraInfoMap.removeItem(idInt);
+ } else {
+ ALOGE("%s: Cannot find corresponding static metadata for physical id %s",
+ __FUNCTION__, id.c_str());
+ }
}
}
}
- free_camera_metadata(metadata);
+
mCameraInfoMap.removeItem(cameraId);
mDeviceVersionMap.removeItem(cameraId);
}
diff --git a/camera/common/1.0/default/include/CameraModule.h b/camera/common/1.0/default/include/CameraModule.h
index c89e934..8195835 100644
--- a/camera/common/1.0/default/include/CameraModule.h
+++ b/camera/common/1.0/default/include/CameraModule.h
@@ -49,6 +49,7 @@
// Returns OK on success, NO_INIT on failure
int init();
+ int getCameraDeviceVersion(int cameraId, uint32_t* version);
int getCameraInfo(int cameraId, struct camera_info *info);
int getDeviceVersion(int cameraId);
int getNumberOfCameras(void);
diff --git a/camera/device/1.0/default/Android.bp b/camera/device/1.0/default/Android.bp
index da70577..f407476 100644
--- a/camera/device/1.0/default/Android.bp
+++ b/camera/device/1.0/default/Android.bp
@@ -10,6 +10,7 @@
"libhidlmemory",
"libutils",
"android.hardware.camera.device@1.0",
+ "vendor.qti.hardware.camera.device@1.0",
"android.hardware.camera.common@1.0",
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.mapper@2.0",
@@ -31,4 +32,8 @@
"media_plugin_headers",
],
export_include_dirs: ["."],
+ // Since this platform module has been forked to depend on a vendor
+ // proprietary library, we exclude it from the vendor snapshot so that it
+ // will be built from source as part of the vendor build.
+ exclude_from_vendor_snapshot: true,
}
diff --git a/camera/device/1.0/default/CameraDevice.cpp b/camera/device/1.0/default/CameraDevice.cpp
index 2dd6094..9b6e4b9 100644
--- a/camera/device/1.0/default/CameraDevice.cpp
+++ b/camera/device/1.0/default/CameraDevice.cpp
@@ -430,30 +430,68 @@
index, mem->mNumBufs);
return;
}
- if (object->mDeviceCallback != nullptr) {
- CameraFrameMetadata hidlMetadata;
- if (metadata) {
- hidlMetadata.faces.resize(metadata->number_of_faces);
- for (size_t i = 0; i < hidlMetadata.faces.size(); i++) {
- hidlMetadata.faces[i].score = metadata->faces[i].score;
- hidlMetadata.faces[i].id = metadata->faces[i].id;
- for (int k = 0; k < 4; k++) {
- hidlMetadata.faces[i].rect[k] = metadata->faces[i].rect[k];
- }
- for (int k = 0; k < 2; k++) {
- hidlMetadata.faces[i].leftEye[k] = metadata->faces[i].left_eye[k];
- }
- for (int k = 0; k < 2; k++) {
- hidlMetadata.faces[i].rightEye[k] = metadata->faces[i].right_eye[k];
- }
- for (int k = 0; k < 2; k++) {
- hidlMetadata.faces[i].mouth[k] = metadata->faces[i].mouth[k];
- }
- }
- }
- CameraHeapMemory* mem = static_cast<CameraHeapMemory *>(data->handle);
- object->mDeviceCallback->dataCallback(
- (DataCallbackMsg) msg_type, mem->handle.mId, index, hidlMetadata);
+ if(object->mQDeviceCallback != nullptr) {
+ vendor::qti::hardware::camera::device::V1_0::QCameraFrameMetadata hidlMetadata;
+ if (metadata) {
+ hidlMetadata.faces.resize(metadata->number_of_faces);
+ for (size_t i = 0; i < hidlMetadata.faces.size(); i++) {
+ hidlMetadata.faces[i].score = metadata->faces[i].score;
+ hidlMetadata.faces[i].id = metadata->faces[i].id;
+ for (int k = 0; k < 4; k++) {
+ hidlMetadata.faces[i].rect[k] = metadata->faces[i].rect[k];
+ }
+ for (int k = 0; k < 2; k++) {
+ hidlMetadata.faces[i].leftEye[k] = metadata->faces[i].left_eye[k];
+ }
+ for (int k = 0; k < 2; k++) {
+ hidlMetadata.faces[i].rightEye[k] = metadata->faces[i].right_eye[k];
+ }
+ for (int k = 0; k < 2; k++) {
+ hidlMetadata.faces[i].mouth[k] = metadata->faces[i].mouth[k];
+ }
+ hidlMetadata.faces[i].smile_degree = metadata->faces[i].smile_degree;
+ hidlMetadata.faces[i].smile_score = metadata->faces[i].smile_score;
+ hidlMetadata.faces[i].blink_detected = metadata->faces[i].blink_detected;
+ hidlMetadata.faces[i].face_recognised = metadata->faces[i].face_recognised;
+ hidlMetadata.faces[i].gaze_angle = metadata->faces[i].gaze_angle;
+ hidlMetadata.faces[i].updown_dir = metadata->faces[i].updown_dir;
+ hidlMetadata.faces[i].leftright_dir = metadata->faces[i].leftright_dir;
+ hidlMetadata.faces[i].roll_dir = metadata->faces[i].roll_dir;
+ hidlMetadata.faces[i].left_right_gaze = metadata->faces[i].left_right_gaze;
+ hidlMetadata.faces[i].top_bottom_gaze = metadata->faces[i].top_bottom_gaze;
+ hidlMetadata.faces[i].leye_blink = metadata->faces[i].leye_blink;
+ hidlMetadata.faces[i].reye_blink = metadata->faces[i].reye_blink;
+ }
+ }
+ CameraHeapMemory* mem = static_cast<CameraHeapMemory *>(data->handle);
+ object->mQDeviceCallback->QDataCallback(
+ (DataCallbackMsg) msg_type, mem->handle.mId, index, hidlMetadata);
+ } else {
+ if (object->mDeviceCallback != nullptr) {
+ CameraFrameMetadata hidlMetadata;
+ if (metadata) {
+ hidlMetadata.faces.resize(metadata->number_of_faces);
+ for (size_t i = 0; i < hidlMetadata.faces.size(); i++) {
+ hidlMetadata.faces[i].score = metadata->faces[i].score;
+ hidlMetadata.faces[i].id = metadata->faces[i].id;
+ for (int k = 0; k < 4; k++) {
+ hidlMetadata.faces[i].rect[k] = metadata->faces[i].rect[k];
+ }
+ for (int k = 0; k < 2; k++) {
+ hidlMetadata.faces[i].leftEye[k] = metadata->faces[i].left_eye[k];
+ }
+ for (int k = 0; k < 2; k++) {
+ hidlMetadata.faces[i].rightEye[k] = metadata->faces[i].right_eye[k];
+ }
+ for (int k = 0; k < 2; k++) {
+ hidlMetadata.faces[i].mouth[k] = metadata->faces[i].mouth[k];
+ }
+ }
+ }
+ CameraHeapMemory* mem = static_cast<CameraHeapMemory *>(data->handle);
+ object->mDeviceCallback->dataCallback(
+ (DataCallbackMsg) msg_type, mem->handle.mId, index, hidlMetadata);
+ }
}
}
@@ -669,6 +707,11 @@
initHalPreviewWindow();
mDeviceCallback = callback;
+ mQDeviceCallback =
+ vendor::qti::hardware::camera::device::V1_0::IQCameraDeviceCallback::castFrom(callback);
+ if(mQDeviceCallback == nullptr) {
+ ALOGI("could not cast ICameraDeviceCallback to IQCameraDeviceCallback");
+ }
if (mDevice->ops->set_callbacks) {
mDevice->ops->set_callbacks(mDevice,
diff --git a/camera/device/1.0/default/CameraDevice_1_0.h b/camera/device/1.0/default/CameraDevice_1_0.h
index 2c980f0..e5a194e 100644
--- a/camera/device/1.0/default/CameraDevice_1_0.h
+++ b/camera/device/1.0/default/CameraDevice_1_0.h
@@ -24,6 +24,7 @@
#include "HandleImporter.h"
#include <android/hardware/camera/device/1.0/ICameraDevice.h>
+#include <vendor/qti/hardware/camera/device/1.0/IQCameraDeviceCallback.h>
#include <android/hidl/allocator/1.0/IAllocator.h>
#include <android/hidl/memory/1.0/IMemory.h>
#include <hidl/MQDescriptor.h>
@@ -44,6 +45,7 @@
using ::android::hardware::camera::device::V1_0::CameraInfo;
using ::android::hardware::camera::device::V1_0::CommandType;
using ::android::hardware::camera::device::V1_0::ICameraDevice;
+using ::vendor::qti::hardware::camera::device::V1_0::IQCameraDeviceCallback;
using ::android::hardware::camera::device::V1_0::ICameraDeviceCallback;
using ::android::hardware::camera::device::V1_0::ICameraDevicePreviewCallback;
using ::android::hardware::camera::device::V1_0::MemoryId;
@@ -164,6 +166,7 @@
const SortedVector<std::pair<std::string, std::string>>& mCameraDeviceNames;
sp<ICameraDeviceCallback> mDeviceCallback = nullptr;
+ sp<IQCameraDeviceCallback> mQDeviceCallback = nullptr;
mutable Mutex mMemoryMapLock; // gating access to mMemoryMap
// must not hold mLock after this lock is acquired
diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp
index 99cdccb..8d3bf02 100644
--- a/camera/device/3.2/default/CameraDeviceSession.cpp
+++ b/camera/device/3.2/default/CameraDeviceSession.cpp
@@ -925,12 +925,12 @@
mStreamMap[id].data_space);
mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{});
} else {
- // width/height/format must not change, but usage/rotation might need to change
+ // width/height must not change, but usage/rotation might need to change
+ // format might change and get updated with overrideFormat
if (mStreamMap[id].stream_type !=
(int) requestedConfiguration.streams[i].streamType ||
mStreamMap[id].width != requestedConfiguration.streams[i].width ||
mStreamMap[id].height != requestedConfiguration.streams[i].height ||
- mStreamMap[id].format != (int) requestedConfiguration.streams[i].format ||
mStreamMap[id].data_space !=
mapToLegacyDataspace( static_cast<android_dataspace_t> (
requestedConfiguration.streams[i].dataSpace))) {
diff --git a/camera/device/3.2/default/convert.cpp b/camera/device/3.2/default/convert.cpp
index 06ad7e9..628b7af 100644
--- a/camera/device/3.2/default/convert.cpp
+++ b/camera/device/3.2/default/convert.cpp
@@ -66,6 +66,8 @@
dst->data_space = (android_dataspace_t) src.dataSpace;
dst->rotation = (int) src.rotation;
dst->usage = (uint32_t) src.usage;
+ dst->reserved[0] = NULL;
+ dst->reserved[1] = NULL;
// Fields to be filled by HAL (max_buffers, priv) are initialized to 0
dst->max_buffers = 0;
dst->priv = 0;
@@ -88,6 +90,23 @@
ALOGW("%s: Stream type %d is not currently supported!",
__FUNCTION__, src->stream_type);
}
+
+ HalStream* halStream = NULL;
+ if (src->reserved[0] != NULL) {
+ halStream = (HalStream*)(src->reserved[0]);
+ } else if (src->reserved[1] != NULL) {
+ halStream = (HalStream*)(src->reserved[1]);
+ }
+
+ // Check if overrideFormat is set and honor it
+ if (halStream != NULL) {
+ dst->overrideFormat = (PixelFormat) halStream->overrideFormat;
+ if (src->stream_type == CAMERA3_STREAM_OUTPUT) {
+ dst->producerUsage = (BufferUsageFlags)halStream->producerUsage;
+ } else if (src->stream_type == CAMERA3_STREAM_INPUT) {
+ dst->consumerUsage = (BufferUsageFlags)halStream->consumerUsage;
+ }
+ }
}
void convertToHidl(const camera3_stream_configuration_t& src, HalStreamConfiguration* dst) {
diff --git a/camera/device/3.3/default/convert.cpp b/camera/device/3.3/default/convert.cpp
index dae190b..ac17d83 100644
--- a/camera/device/3.3/default/convert.cpp
+++ b/camera/device/3.3/default/convert.cpp
@@ -47,6 +47,22 @@
ALOGW("%s: Stream type %d is not currently supported!",
__FUNCTION__, src->stream_type);
}
+
+ HalStream* halStream = NULL;
+ if (src->reserved[0] != NULL) {
+ halStream = (HalStream*)(src->reserved[0]);
+ } else if (src->reserved[1] != NULL) {
+ halStream = (HalStream*)(src->reserved[1]);
+ }
+
+ if (halStream != NULL) {
+ dst->v3_2.overrideFormat = (PixelFormat) halStream->v3_2.overrideFormat;
+ if (src->stream_type == CAMERA3_STREAM_OUTPUT) {
+ dst->v3_2.producerUsage = (BufferUsageFlags)halStream->v3_2.producerUsage;
+ } else if (src->stream_type == CAMERA3_STREAM_INPUT) {
+ dst->v3_2.consumerUsage = (BufferUsageFlags)halStream->v3_2.consumerUsage;
+ }
+ }
}
void convertToHidl(const camera3_stream_configuration_t& src, HalStreamConfiguration* dst) {
diff --git a/camera/provider/2.4/default/Android.bp b/camera/provider/2.4/default/Android.bp
index 627ddf4..24ab95e 100644
--- a/camera/provider/2.4/default/Android.bp
+++ b/camera/provider/2.4/default/Android.bp
@@ -6,6 +6,7 @@
shared_libs: [
"android.hardware.camera.common@1.0",
"android.hardware.camera.device@1.0",
+ "vendor.qti.hardware.camera.device@1.0",
"android.hardware.camera.device@3.2",
"android.hardware.camera.device@3.3",
"android.hardware.camera.device@3.4",
@@ -36,6 +37,10 @@
"camera.device@3.5-impl_headers",
],
export_include_dirs: ["."],
+ // Since this framework module has been forked to depend on a vendor
+ // proprietary library, we exclude this module from the vendor snapshot so
+ // that it will be built from source as part of the vendor image build.
+ exclude_from_vendor_snapshot: true,
}
cc_library_shared {
@@ -79,6 +84,10 @@
"camera.device@3.6-external-impl_headers"
],
export_include_dirs: ["."],
+ // Since this framework module has a transitive dependency on a vendor
+ // proprietary library, we exclude this module from the vendor snapshot so
+ // that it will be built from source as part of the vendor image build.
+ exclude_from_vendor_snapshot: true,
}
cc_library_shared {
@@ -127,6 +136,10 @@
"android.hardware.camera.common@1.0-helper",
],
export_include_dirs: ["."],
+ // Since this framework module has a transitive dependency on a vendor
+ // proprietary library, we exclude this module from the vendor snapshot so
+ // that it will be built from source as part of the vendor image build.
+ exclude_from_vendor_snapshot: true,
}
cc_defaults {
@@ -138,6 +151,7 @@
shared_libs: [
"android.hardware.camera.common@1.0",
"android.hardware.camera.device@1.0",
+ "vendor.qti.hardware.camera.device@1.0",
"android.hardware.camera.device@3.2",
"android.hardware.camera.device@3.3",
"android.hardware.camera.device@3.4",
@@ -164,6 +178,10 @@
"camera.device@3.5-external-impl_headers",
"camera.device@3.5-impl_headers",
],
+ // Since this framework module has been forked to depend on a vendor
+ // proprietary library, we exclude this module from the vendor snapshot so
+ // that it will be built from source as part of the vendor image build.
+ exclude_from_vendor_snapshot: true,
}
cc_binary {
@@ -226,4 +244,8 @@
"camera.device@3.5-external-impl_headers",
"camera.device@3.5-impl_headers",
],
+ // Since this framework module has a transitive dependency on a vendor
+ // proprietary library, we exclude this module from the vendor snapshot so
+ // that it will be built from source as part of the vendor image build.
+ exclude_from_vendor_snapshot: true,
}
diff --git a/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.cpp b/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.cpp
index 4cff1b7..18149e5 100644
--- a/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.cpp
+++ b/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.cpp
@@ -87,23 +87,32 @@
if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_2 &&
mModule->isOpenLegacyDefined()) {
// try open_legacy to see if it actually works
- struct hw_device_t* halDev = nullptr;
- int ret = mModule->openLegacy(cameraId, CAMERA_DEVICE_API_VERSION_1_0, &halDev);
- if (ret == 0) {
- mOpenLegacySupported[cameraIdStr] = true;
- halDev->close(halDev);
- deviceNamePair = std::make_pair(cameraIdStr,
+ if ((property_get_bool("ro.config.low_ram", /*default*/ false))) {
+ deviceNamePair = std::make_pair(cameraIdStr,
getHidlDeviceName(cameraIdStr, CAMERA_DEVICE_API_VERSION_1_0));
- mCameraDeviceNames.add(deviceNamePair);
- if (cam_new) {
- mCallbacks->cameraDeviceStatusChange(deviceNamePair.second, status);
- }
- } else if (ret == -EBUSY || ret == -EUSERS) {
+ mCameraDeviceNames.add(deviceNamePair);
+ if (cam_new) {
+ mCallbacks->cameraDeviceStatusChange(deviceNamePair.second, status);
+ }
+ } else {
+ struct hw_device_t* halDev = nullptr;
+ int ret = mModule->openLegacy(cameraId, CAMERA_DEVICE_API_VERSION_1_0, &halDev);
+ if (ret == 0) {
+ mOpenLegacySupported[cameraIdStr] = true;
+ halDev->close(halDev);
+ deviceNamePair = std::make_pair(cameraIdStr,
+ getHidlDeviceName(cameraIdStr, CAMERA_DEVICE_API_VERSION_1_0));
+ mCameraDeviceNames.add(deviceNamePair);
+ if (cam_new) {
+ mCallbacks->cameraDeviceStatusChange(deviceNamePair.second, status);
+ }
+ } else if (ret == -EBUSY || ret == -EUSERS) {
// Looks like this provider instance is not initialized during
// system startup and there are other camera users already.
// Not a good sign but not fatal.
- ALOGW("%s: open_legacy try failed!", __FUNCTION__);
- }
+ ALOGW("%s: open_legacy try failed!", __FUNCTION__);
+ }
+ }
}
}
@@ -314,15 +323,15 @@
mNumberOfLegacyCameras = mModule->getNumberOfCameras();
for (int i = 0; i < mNumberOfLegacyCameras; i++) {
- struct camera_info info;
- auto rc = mModule->getCameraInfo(i, &info);
+ uint32_t device_version;
+ auto rc = mModule->getCameraDeviceVersion(i, &device_version);
if (rc != NO_ERROR) {
- ALOGE("%s: Camera info query failed!", __func__);
+ ALOGE("%s: Camera device version query failed!", __func__);
mModule.clear();
return true;
}
- if (checkCameraVersion(i, info) != OK) {
+ if (checkCameraVersion(i, device_version) != OK) {
ALOGE("%s: Camera version check failed!", __func__);
mModule.clear();
return true;
@@ -342,7 +351,7 @@
/**
* Check that the device HAL version is still in supported.
*/
-int LegacyCameraProviderImpl_2_4::checkCameraVersion(int id, camera_info info) {
+int LegacyCameraProviderImpl_2_4::checkCameraVersion(int id, uint32_t device_version) {
if (mModule == nullptr) {
return NO_INIT;
}
@@ -352,7 +361,7 @@
uint16_t moduleVersion = mModule->getModuleApiVersion();
if (moduleVersion >= CAMERA_MODULE_API_VERSION_2_0) {
// Verify the device version is in the supported range
- switch (info.device_version) {
+ switch (device_version) {
case CAMERA_DEVICE_API_VERSION_1_0:
case CAMERA_DEVICE_API_VERSION_3_2:
case CAMERA_DEVICE_API_VERSION_3_3:
@@ -370,7 +379,7 @@
if (moduleVersion < CAMERA_MODULE_API_VERSION_2_5) {
ALOGE("%s: Device %d has unsupported version combination:"
"HAL version %x and module version %x",
- __FUNCTION__, id, info.device_version, moduleVersion);
+ __FUNCTION__, id, device_version, moduleVersion);
return NO_INIT;
}
break;
@@ -380,8 +389,8 @@
case CAMERA_DEVICE_API_VERSION_3_1:
// no longer supported
default:
- ALOGE("%s: Device %d has HAL version %x, which is not supported",
- __FUNCTION__, id, info.device_version);
+ ALOGE("%s: Device %d has HAL version %x, which is not supported", __FUNCTION__, id,
+ device_version);
return NO_INIT;
}
}
diff --git a/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.h b/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.h
index b4914b3..9ec5c5e 100644
--- a/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.h
+++ b/camera/provider/2.4/default/LegacyCameraProviderImpl_2_4.h
@@ -97,7 +97,7 @@
hidl_vec<VendorTagSection> mVendorTagSections;
bool setUpVendorTags();
- int checkCameraVersion(int id, camera_info info);
+ int checkCameraVersion(int id, uint32_t device_version);
// create HIDL device name from camera ID and legacy device version
std::string getHidlDeviceName(std::string cameraId, int deviceVersion);
diff --git a/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service.rc b/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service.rc
index f7ac9f8..ff924ed 100644
--- a/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service.rc
+++ b/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service.rc
@@ -5,4 +5,4 @@
group audio camera input drmrpc
ioprio rt 4
capabilities SYS_NICE
- task_profiles CameraServiceCapacity MaxPerformance
+ task_profiles CameraServiceCapacity HighPerformance
diff --git a/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service_64.rc b/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service_64.rc
index a32dd46..642e84e 100644
--- a/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service_64.rc
+++ b/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service_64.rc
@@ -5,4 +5,4 @@
group audio camera input drmrpc
ioprio rt 4
capabilities SYS_NICE
- task_profiles CameraServiceCapacity MaxPerformance
+ task_profiles CameraServiceCapacity HighPerformance
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index f235235..560b24e 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -888,6 +888,8 @@
static Status getSystemCameraKind(const camera_metadata_t* staticMeta,
SystemCameraKind* systemCameraKind);
+ static V3_2::DataspaceFlags getDataspace(PixelFormat format);
+
void processCaptureRequestInternal(uint64_t bufferusage, RequestTemplate reqTemplate,
bool useSecureOnlyCameras);
@@ -3173,7 +3175,6 @@
}
}
-
// Verify that all supported stream formats and sizes can be configured
// successfully.
TEST_P(CameraHidlTest, configureStreamsAvailableOutputs) {
@@ -3216,17 +3217,7 @@
uint32_t streamConfigCounter = 0;
for (auto& it : outputStreams) {
V3_2::Stream stream3_2;
- V3_2::DataspaceFlags dataspaceFlag = 0;
- switch (static_cast<PixelFormat>(it.format)) {
- case PixelFormat::BLOB:
- dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::V0_JFIF);
- break;
- case PixelFormat::Y16:
- dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::DEPTH);
- break;
- default:
- dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::UNKNOWN);
- }
+ V3_2::DataspaceFlags dataspaceFlag = getDataspace(static_cast<PixelFormat>(it.format));
stream3_2 = {streamId,
StreamType::OUTPUT,
static_cast<uint32_t>(it.width),
@@ -3346,17 +3337,8 @@
size_t j = 0;
for (const auto& it : outputStreams) {
V3_2::Stream stream3_2;
- V3_2::DataspaceFlags dataspaceFlag = 0;
- switch (static_cast<PixelFormat>(it.format)) {
- case PixelFormat::BLOB:
- dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::V0_JFIF);
- break;
- case PixelFormat::Y16:
- dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::DEPTH);
- break;
- default:
- dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::UNKNOWN);
- }
+ V3_2::DataspaceFlags dataspaceFlag =
+ getDataspace(static_cast<PixelFormat>(it.format));
stream3_2 = {streamId++,
StreamType::OUTPUT,
static_cast<uint32_t>(it.width),
@@ -4453,9 +4435,12 @@
nullptr};
} else {
allocateGraphicBuffer(testStream.width, testStream.height,
- android_convertGralloc1To0Usage(halStreamConfig.streams[0].producerUsage,
- halStreamConfig.streams[0].consumerUsage),
- halStreamConfig.streams[0].overrideFormat, &buffer_handle);
+ /* We don't look at halStreamConfig.streams[0].consumerUsage
+ * since that is 0 for output streams
+ */
+ android_convertGralloc1To0Usage(
+ halStreamConfig.streams[0].producerUsage, bufferUsage),
+ halStreamConfig.streams[0].overrideFormat, &buffer_handle);
outputBuffer = {halStreamConfig.streams[0].id,
bufferId,
buffer_handle,
@@ -5893,6 +5878,23 @@
return ret;
}
+// Select an appropriate dataspace given a specific pixel format.
+V3_2::DataspaceFlags CameraHidlTest::getDataspace(PixelFormat format) {
+ switch (format) {
+ case PixelFormat::BLOB:
+ return static_cast<V3_2::DataspaceFlags>(Dataspace::V0_JFIF);
+ case PixelFormat::Y16:
+ return static_cast<V3_2::DataspaceFlags>(Dataspace::DEPTH);
+ case PixelFormat::RAW16:
+ case PixelFormat::RAW_OPAQUE:
+ case PixelFormat::RAW10:
+ case PixelFormat::RAW12:
+ return static_cast<V3_2::DataspaceFlags>(Dataspace::ARBITRARY);
+ default:
+ return static_cast<V3_2::DataspaceFlags>(Dataspace::UNKNOWN);
+ }
+}
+
// Check whether this is a monochrome camera using the static camera characteristics.
Status CameraHidlTest::isMonochromeCamera(const camera_metadata_t *staticMeta) {
Status ret = Status::METHOD_NOT_SUPPORTED;
@@ -6267,17 +6269,8 @@
ASSERT_EQ(Status::OK, rc);
ASSERT_FALSE(outputStreams.empty());
- V3_2::DataspaceFlags dataspaceFlag = 0;
- switch (static_cast<PixelFormat>(outputStreams[idx].format)) {
- case PixelFormat::BLOB:
- dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::V0_JFIF);
- break;
- case PixelFormat::Y16:
- dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::DEPTH);
- break;
- default:
- dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::UNKNOWN);
- }
+ V3_2::DataspaceFlags dataspaceFlag =
+ getDataspace(static_cast<PixelFormat>(outputStreams[idx].format));
::android::hardware::hidl_vec<V3_4::Stream> streams3_4(/*size*/1);
V3_4::Stream stream3_4 = {{ 0 /*streamId*/, StreamType::OUTPUT,
diff --git a/camera/provider/2.5/default/Android.bp b/camera/provider/2.5/default/Android.bp
index 9ddf651..66a2d5b 100644
--- a/camera/provider/2.5/default/Android.bp
+++ b/camera/provider/2.5/default/Android.bp
@@ -35,6 +35,10 @@
"camera.device@3.5-impl_headers",
],
export_include_dirs: ["."],
+ // Since this framework module has a transitive dependency on a vendor
+ // proprietary library, we exclude this module from the vendor snapshot so
+ // that it will be built from source as part of the vendor image build.
+ exclude_from_vendor_snapshot: true,
}
cc_library_shared {
@@ -78,6 +82,10 @@
"camera.device@3.6-external-impl_headers"
],
export_include_dirs: ["."],
+ // Since this framework module has a transitive dependency on a vendor
+ // proprietary library, we exclude this module from the vendor snapshot so
+ // that it will be built from source as part of the vendor image build.
+ exclude_from_vendor_snapshot: true,
}
cc_defaults {
@@ -114,6 +122,10 @@
"camera.device@3.4-impl_headers",
"camera.device@3.5-impl_headers"
],
+ // Since this framework module has a transitive dependency on a vendor
+ // proprietary library, we exclude this module from the vendor snapshot so
+ // that it will be built from source as part of the vendor image build.
+ exclude_from_vendor_snapshot: true,
}
cc_binary {
@@ -187,4 +199,8 @@
"camera.device@3.5-impl_headers",
"camera.device@3.6-external-impl_headers",
],
+ // Since this framework module has a transitive dependency on a vendor
+ // proprietary library, we exclude this module from the vendor snapshot so
+ // that it will be built from source as part of the vendor image build.
+ exclude_from_vendor_snapshot: true,
}
diff --git a/cas/1.0/default/Android.bp b/cas/1.0/default/Android.bp
index f9977ff..3891a0e 100644
--- a/cas/1.0/default/Android.bp
+++ b/cas/1.0/default/Android.bp
@@ -24,10 +24,16 @@
"liblog",
"libstagefright_foundation",
"libutils",
+ "libhwbinder"
],
header_libs: [
"media_plugin_headers",
],
+ arch: {
+ arm: {
+ cflags: ["-DARCH_ARM_32"],
+ },
+ },
}
cc_binary {
diff --git a/cas/1.0/default/service.cpp b/cas/1.0/default/service.cpp
index 754c0c5..dfb385d 100644
--- a/cas/1.0/default/service.cpp
+++ b/cas/1.0/default/service.cpp
@@ -27,6 +27,10 @@
#include "MediaCasService.h"
+#ifdef ARCH_ARM_32
+#include <hwbinder/ProcessState.h>
+#endif
+
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using android::hardware::LazyServiceRegistrar;
@@ -40,6 +44,9 @@
#endif
int main() {
+ #ifdef ARCH_ARM_32
+ android::hardware::ProcessState::initWithMmapSize((size_t)32768);
+ #endif
configureRpcThreadpool(8, true /* callerWillJoin */);
// Setup hwbinder service
diff --git a/compatibility_matrices/compatibility_matrix.4.xml b/compatibility_matrices/compatibility_matrix.4.xml
index e5e012c..9f486dd 100644
--- a/compatibility_matrices/compatibility_matrix.4.xml
+++ b/compatibility_matrices/compatibility_matrix.4.xml
@@ -499,6 +499,7 @@
<interface>
<name>IHostapd</name>
<instance>default</instance>
+ <instance>wigighostapd</instance>
</interface>
</hal>
<hal format="hidl" optional="true">
diff --git a/compatibility_matrices/compatibility_matrix.5.xml b/compatibility_matrices/compatibility_matrix.5.xml
index e772b6f..53b9be8 100644
--- a/compatibility_matrices/compatibility_matrix.5.xml
+++ b/compatibility_matrices/compatibility_matrix.5.xml
@@ -541,6 +541,7 @@
<interface>
<name>IHostapd</name>
<instance>default</instance>
+ <instance>wigighostapd</instance>
</interface>
</hal>
<hal format="hidl" optional="true">
diff --git a/current.txt b/current.txt
index 6696516..6f509c3 100644
--- a/current.txt
+++ b/current.txt
@@ -765,3 +765,13 @@
2ce1f7fb52e49f80b13a9b153d491bce530552f02357ea729acae922a8659f93 android.hardware.wifi.supplicant@1.3::ISupplicantStaIfaceCallback
77531c8d048f8f8ae532babd0ca86332a865ec9aace1b051226ef2b21123e645 android.hardware.wifi.supplicant@1.3::ISupplicantStaNetwork
98592d193a717066facf91428426e5abe211e3bd718bc372e29fb944ddbe6e7c android.hardware.wifi.supplicant@1.3::types
+
+# ABI preserving changes to HALs
+1ca372cd67d197df099e87616a613ba6ede6552638a603e18f86c8834302c3d1 android.hardware.gnss@1.0::IGnssMeasurementCallback
+6a271e493907e8ba20912e42771bd0d99ae45431a851d5675ef9496d02510a34 android.hardware.gnss@1.1::IGnssMeasurementCallback
+cd84ab19c590e0e73dd2307b591a3093ee18147ef95e6d5418644463a6620076 android.hardware.neuralnetworks@1.2::IDevice
+9625e85f56515ad2cf87b6a1847906db669f746ea4ab02cd3d4ca25abc9b0109 android.hardware.neuralnetworks@1.2::types
+9e758e208d14f7256e0885d6d8ad0b61121b21d8c313864f981727ae55bffd16 android.hardware.neuralnetworks@1.3::types
+0f53d70e1eadf8d987766db4bf6ae2048004682168f4cab118da576787def3fa android.hardware.radio@1.0::types
+38d65fb20c60a5b823298560fc0825457ecdc49603a4b4e94bf81511790737da android.hardware.radio@1.4::types
+954c334efd80e8869b66d1ce5fe2755712d96ba4b3c38d415739c330af5fb4cb android.hardware.radio@1.5::types
diff --git a/drm/1.0/default/Android.bp b/drm/1.0/default/Android.bp
index 1122e46..48e084e 100644
--- a/drm/1.0/default/Android.bp
+++ b/drm/1.0/default/Android.bp
@@ -1,3 +1,17 @@
+// Copyright (C) 2016-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.
+
cc_library_static {
name: "android.hardware.drm@1.0-helper",
vendor_available: true,
@@ -22,3 +36,111 @@
],
export_include_dirs: ["include"],
}
+
+soong_config_module_type {
+ name: "android_hardware_drm_1_0_multilib",
+ module_type: "cc_defaults",
+ config_namespace: "ANDROID",
+ bool_variables: ["TARGET_ENABLE_MEDIADRM_64"],
+ properties: ["compile_multilib"],
+}
+
+android_hardware_drm_1_0_multilib {
+ name: "android.hardware.drm@1.0-multilib-lib",
+ compile_multilib: "32",
+ soong_config_variables: {
+ TARGET_ENABLE_MEDIADRM_64: {
+ compile_multilib: "both",
+ }
+ }
+}
+
+android_hardware_drm_1_0_multilib {
+ name: "android.hardware.drm@1.0-multilib-exe",
+ compile_multilib: "32",
+ soong_config_variables: {
+ TARGET_ENABLE_MEDIADRM_64: {
+ compile_multilib: "first",
+ }
+ }
+}
+
+cc_defaults {
+ name: "android.hardware.drm@1.0-service-defaults",
+ proprietary: true,
+ relative_install_path: "hw",
+ include_dirs: ["hardware/interfaces/drm"],
+ header_libs: ["media_plugin_headers"],
+ static_libs: ["android.hardware.drm@1.0-helper"],
+
+ shared_libs: [
+ "android.hardware.drm@1.0",
+ "android.hidl.memory@1.0",
+ "libhidlbase",
+ "libhardware",
+ "liblog",
+ "libutils",
+ "libbinder",
+ ],
+}
+
+//############ Build legacy drm service ############
+
+cc_binary {
+ name: "android.hardware.drm@1.0-service",
+ defaults: [
+ "android.hardware.drm@1.0-multilib-exe",
+ "android.hardware.drm@1.0-service-defaults"
+ ],
+ init_rc: ["android.hardware.drm@1.0-service.rc"],
+ srcs: ["service.cpp"],
+}
+
+//############ Build legacy drm lazy service ############
+
+cc_binary {
+ name: "android.hardware.drm@1.0-service-lazy",
+ defaults: [
+ "android.hardware.drm@1.0-multilib-exe",
+ "android.hardware.drm@1.0-service-defaults"
+ ],
+ overrides: ["android.hardware.drm@1.0-service"],
+ init_rc: ["android.hardware.drm@1.0-service-lazy.rc"],
+ srcs: ["serviceLazy.cpp"],
+}
+
+//############ Build legacy drm impl library ############
+
+cc_library_shared {
+ name: "android.hardware.drm@1.0-impl",
+ defaults: ["android.hardware.drm@1.0-multilib-lib"],
+ proprietary: true,
+ relative_install_path: "hw",
+
+ include_dirs: [
+ "frameworks/native/include",
+ "frameworks/av/include",
+ ],
+
+ shared_libs: [
+ "android.hardware.drm@1.0",
+ "android.hidl.memory@1.0",
+ "libcutils",
+ "libhidlbase",
+ "libhidlmemory",
+ "liblog",
+ "libstagefright_foundation",
+ "libutils",
+ ],
+
+ static_libs: ["android.hardware.drm@1.0-helper"],
+
+ srcs: [
+ "DrmFactory.cpp",
+ "DrmPlugin.cpp",
+ "CryptoFactory.cpp",
+ "CryptoPlugin.cpp",
+ "LegacyPluginPath.cpp",
+ "TypeConvert.cpp",
+ ],
+}
diff --git a/drm/1.0/default/Android.mk b/drm/1.0/default/Android.mk
deleted file mode 100644
index 9016dc3..0000000
--- a/drm/1.0/default/Android.mk
+++ /dev/null
@@ -1,81 +0,0 @@
-#
-# Copyright (C) 2016 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.
-
-
-############# Build legacy drm service ############
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-include $(LOCAL_PATH)/common_default_service.mk
-LOCAL_MODULE := android.hardware.drm@1.0-service
-LOCAL_INIT_RC := android.hardware.drm@1.0-service.rc
-LOCAL_SRC_FILES := service.cpp
-
-include $(BUILD_EXECUTABLE)
-
-############# Build legacy drm lazy service ############
-
-include $(CLEAR_VARS)
-
-include $(LOCAL_PATH)/common_default_service.mk
-LOCAL_MODULE := android.hardware.drm@1.0-service-lazy
-LOCAL_OVERRIDES_MODULES := android.hardware.drm@1.0-service
-LOCAL_INIT_RC := android.hardware.drm@1.0-service-lazy.rc
-LOCAL_SRC_FILES := serviceLazy.cpp
-
-include $(BUILD_EXECUTABLE)
-
-############# Build legacy drm impl library ############
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.drm@1.0-impl
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_SRC_FILES := \
- DrmFactory.cpp \
- DrmPlugin.cpp \
- CryptoFactory.cpp \
- CryptoPlugin.cpp \
- LegacyPluginPath.cpp \
- TypeConvert.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
- android.hardware.drm@1.0 \
- android.hidl.memory@1.0 \
- libcutils \
- libhidlbase \
- libhidlmemory \
- liblog \
- libstagefright_foundation \
- libutils \
-
-LOCAL_STATIC_LIBRARIES := \
- android.hardware.drm@1.0-helper \
-
-LOCAL_C_INCLUDES := \
- frameworks/native/include \
- frameworks/av/include
-
-# TODO: Some legacy DRM plugins only support 32-bit. They need to be migrated to
-# 64-bit. (b/18948909) Once all of a device's legacy DRM plugins support 64-bit,
-# that device can turn on TARGET_ENABLE_MEDIADRM_64 to build this impl as
-# 64-bit.
-ifneq ($(TARGET_ENABLE_MEDIADRM_64), true)
-LOCAL_32_BIT_ONLY := true
-endif
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/drm/1.0/default/common_default_service.mk b/drm/1.0/default/common_default_service.mk
deleted file mode 100644
index 1b5a975..0000000
--- a/drm/1.0/default/common_default_service.mk
+++ /dev/null
@@ -1,44 +0,0 @@
-#
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-include $(CLEAR_VARS)
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := hw
-
-LOCAL_SHARED_LIBRARIES := \
- android.hardware.drm@1.0 \
- android.hidl.memory@1.0 \
- libhidlbase \
- libhardware \
- liblog \
- libutils \
- libbinder \
-
-LOCAL_STATIC_LIBRARIES := \
- android.hardware.drm@1.0-helper \
-
-LOCAL_C_INCLUDES := \
- hardware/interfaces/drm
-
-LOCAL_HEADER_LIBRARIES := \
- media_plugin_headers
-
-# TODO(b/18948909) Some legacy DRM plugins only support 32-bit. They need to be
-# migrated to 64-bit. Once all of a device's legacy DRM plugins support 64-bit,
-# that device can turn on TARGET_ENABLE_MEDIADRM_64 to build this service as
-# 64-bit.
-ifneq ($(TARGET_ENABLE_MEDIADRM_64), true)
-LOCAL_32_BIT_ONLY := true
-endif
diff --git a/drm/1.0/vts/functional/AndroidTest.xml b/drm/1.0/vts/functional/AndroidTest.xml
index 92ea7e4..02c51cc 100644
--- a/drm/1.0/vts/functional/AndroidTest.xml
+++ b/drm/1.0/vts/functional/AndroidTest.xml
@@ -16,6 +16,7 @@
<configuration description="Runs VtsHalDrmV1_0TargetTest.">
<option name="test-suite-tag" value="apct" />
<option name="test-suite-tag" value="apct-native" />
+ <option name="not-shardable" value="true" />
<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
diff --git a/drm/1.1/vts/functional/AndroidTest.xml b/drm/1.1/vts/functional/AndroidTest.xml
index 24eeb72..4757d4a 100644
--- a/drm/1.1/vts/functional/AndroidTest.xml
+++ b/drm/1.1/vts/functional/AndroidTest.xml
@@ -16,6 +16,7 @@
<configuration description="Runs VtsHalDrmV1_1TargetTest.">
<option name="test-suite-tag" value="apct" />
<option name="test-suite-tag" value="apct-native" />
+ <option name="not-shardable" value="true" />
<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
diff --git a/drm/1.2/vts/functional/AndroidTest.xml b/drm/1.2/vts/functional/AndroidTest.xml
index 3285c37..106ad33 100644
--- a/drm/1.2/vts/functional/AndroidTest.xml
+++ b/drm/1.2/vts/functional/AndroidTest.xml
@@ -16,6 +16,7 @@
<configuration description="Runs VtsHalDrmV1_2TargetTest.">
<option name="test-suite-tag" value="apct" />
<option name="test-suite-tag" value="apct-native" />
+ <option name="not-shardable" value="true" />
<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
diff --git a/drm/1.3/vts/functional/AndroidTest.xml b/drm/1.3/vts/functional/AndroidTest.xml
index 9cc8e0c..4ec5c70 100644
--- a/drm/1.3/vts/functional/AndroidTest.xml
+++ b/drm/1.3/vts/functional/AndroidTest.xml
@@ -16,6 +16,7 @@
<configuration description="Runs VtsHalDrmV1_3TargetTest.">
<option name="test-suite-tag" value="apct" />
<option name="test-suite-tag" value="apct-native" />
+ <option name="not-shardable" value="true" />
<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
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 33feb5e..16e634f 100644
--- a/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp
@@ -247,8 +247,10 @@
ALOGD("Observed %d GnssSvStatus, while awaiting one location (%d received)",
sv_info_list_cbq_size, location_called_count);
- hidl_vec<IGnssCallback_2_1::GnssSvInfo> last_sv_info_list;
- ASSERT_TRUE(gnss_cb_->sv_info_list_cbq_.retrieve(last_sv_info_list, 1));
+ // Get the last sv_info_list
+ std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_vec_list;
+ gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec_list, sv_info_list_cbq_size, 1);
+ hidl_vec<IGnssCallback_2_1::GnssSvInfo> last_sv_info_list = sv_info_vec_list.back();
bool nonZeroCn0Found = false;
for (auto sv_info : last_sv_info_list) {
@@ -361,6 +363,12 @@
* 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;
@@ -502,6 +510,12 @@
* 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;
@@ -578,6 +592,12 @@
* 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;
@@ -673,4 +693,4 @@
iMeasurementCorrections->setCorrections_1_1(Utils::getMockMeasurementCorrections_1_1());
ASSERT_TRUE(result.isOk());
EXPECT_TRUE(result);
-}
\ No newline at end of file
+}
diff --git a/graphics/allocator/2.0/default/Android.bp b/graphics/allocator/2.0/default/Android.bp
index 59229b0..3a2808e 100644
--- a/graphics/allocator/2.0/default/Android.bp
+++ b/graphics/allocator/2.0/default/Android.bp
@@ -33,4 +33,11 @@
"liblog",
"libutils",
],
+ arch: {
+ arm: {
+ cflags: [
+ "-DARCH_ARM_32"
+ ],
+ },
+ },
}
diff --git a/graphics/allocator/2.0/default/service.cpp b/graphics/allocator/2.0/default/service.cpp
index bc0539a..ca1fee4 100644
--- a/graphics/allocator/2.0/default/service.cpp
+++ b/graphics/allocator/2.0/default/service.cpp
@@ -19,10 +19,15 @@
#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
#include <hidl/LegacySupport.h>
+#include <hwbinder/ProcessState.h>
using android::hardware::defaultPassthroughServiceImplementation;
using android::hardware::graphics::allocator::V2_0::IAllocator;
int main() {
+
+#ifdef ARCH_ARM_32
+ android::hardware::ProcessState::initWithMmapSize((size_t)(32768));
+#endif
return defaultPassthroughServiceImplementation<IAllocator>(4);
}
diff --git a/graphics/composer/2.1/default/Android.bp b/graphics/composer/2.1/default/Android.bp
index 533687b..422dc5f 100644
--- a/graphics/composer/2.1/default/Android.bp
+++ b/graphics/composer/2.1/default/Android.bp
@@ -1,31 +1,3 @@
-cc_library_shared {
- name: "android.hardware.graphics.composer@2.1-impl",
- defaults: ["hidl_defaults"],
- vendor: true,
- relative_install_path: "hw",
- srcs: ["passthrough.cpp"],
- header_libs: [
- "android.hardware.graphics.composer@2.1-passthrough",
- ],
- shared_libs: [
- "android.hardware.graphics.composer@2.1",
- "android.hardware.graphics.composer@2.1-resources",
- "libbase",
- "libcutils",
- "libfmq",
- "libhardware",
- "libhidlbase",
- "liblog",
- "libsync",
- "libutils",
- "libhwc2on1adapter",
- "libhwc2onfbadapter",
- ],
- cflags: [
- "-DLOG_TAG=\"ComposerHal\""
- ],
-}
-
cc_binary {
name: "android.hardware.graphics.composer@2.1-service",
defaults: ["hidl_defaults"],
@@ -33,12 +5,30 @@
relative_install_path: "hw",
srcs: ["service.cpp"],
init_rc: ["android.hardware.graphics.composer@2.1-service.rc"],
+ header_libs: [
+ "android.hardware.graphics.composer@2.1-passthrough",
+ ],
shared_libs: [
"android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.composer@2.1-resources",
+ "libbase",
+ "libhwbinder",
"libbinder",
+ "libcutils",
+ "libfmq",
+ "libhardware",
"libhidlbase",
+ "libhwc2on1adapter",
+ "libhwc2onfbadapter",
"liblog",
"libsync",
"libutils",
],
+ arch: {
+ arm: {
+ cflags: [
+ "-DARCH_ARM_32"
+ ],
+ },
+ },
}
diff --git a/graphics/composer/2.1/default/android.hardware.graphics.composer@2.1-service.rc b/graphics/composer/2.1/default/android.hardware.graphics.composer@2.1-service.rc
index cbd589a..5b8a46f 100644
--- a/graphics/composer/2.1/default/android.hardware.graphics.composer@2.1-service.rc
+++ b/graphics/composer/2.1/default/android.hardware.graphics.composer@2.1-service.rc
@@ -1,8 +1,8 @@
service vendor.hwcomposer-2-1 /vendor/bin/hw/android.hardware.graphics.composer@2.1-service
- interface android.hardware.graphics.composer@2.1::IComposer default
class hal animation
user system
group graphics drmrpc
capabilities SYS_NICE
onrestart restart surfaceflinger
writepid /dev/cpuset/system-background/tasks
+ socket pps stream 0660 system system
diff --git a/graphics/composer/2.1/default/passthrough.cpp b/graphics/composer/2.1/default/passthrough.cpp
deleted file mode 100644
index ef7ed7c..0000000
--- a/graphics/composer/2.1/default/passthrough.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android/hardware/graphics/composer/2.1/IComposer.h>
-#include <composer-passthrough/2.1/HwcLoader.h>
-
-using android::hardware::graphics::composer::V2_1::IComposer;
-using android::hardware::graphics::composer::V2_1::passthrough::HwcLoader;
-
-extern "C" IComposer* HIDL_FETCH_IComposer(const char* /* name */) {
- return HwcLoader::load();
-}
diff --git a/graphics/composer/2.1/default/service.cpp b/graphics/composer/2.1/default/service.cpp
index 82a33f6..b8ddd21 100644
--- a/graphics/composer/2.1/default/service.cpp
+++ b/graphics/composer/2.1/default/service.cpp
@@ -21,10 +21,12 @@
#include <android/hardware/graphics/composer/2.1/IComposer.h>
#include <binder/ProcessState.h>
+#include <composer-passthrough/2.1/HwcLoader.h>
#include <hidl/LegacySupport.h>
+#include <hwbinder/ProcessState.h>
using android::hardware::graphics::composer::V2_1::IComposer;
-using android::hardware::defaultPassthroughServiceImplementation;
+using android::hardware::graphics::composer::V2_1::passthrough::HwcLoader;
int main() {
// the conventional HAL might start binder services
@@ -40,5 +42,23 @@
ALOGE("Couldn't set SCHED_FIFO: %d", errno);
}
- return defaultPassthroughServiceImplementation<IComposer>(4);
+#ifdef ARCH_ARM_32
+ android::hardware::ProcessState::initWithMmapSize((size_t)(32768));
+#endif
+
+ android::hardware::configureRpcThreadpool(4, true /* will join */);
+
+ android::sp<IComposer> composer = HwcLoader::load();
+ if (composer == nullptr) {
+ return 1;
+ }
+ if (composer->registerAsService() != android::NO_ERROR) {
+ ALOGE("failed to register service");
+ return 1;
+ }
+
+ android::hardware::joinRpcThreadpool();
+
+ ALOGE("service is terminating");
+ return 1;
}
diff --git a/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc b/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc
index efe6dad..289a91c 100644
--- a/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc
+++ b/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc
@@ -4,4 +4,5 @@
group graphics drmrpc
capabilities SYS_NICE
onrestart restart surfaceflinger
+ socket pps stream 0660 system system
writepid /dev/cpuset/system-background/tasks
diff --git a/graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc b/graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc
index 81ce890..5cc19bb 100644
--- a/graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc
+++ b/graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc
@@ -4,4 +4,5 @@
group graphics drmrpc
capabilities SYS_NICE
onrestart restart surfaceflinger
+ socket pps stream 0660 system system
writepid /dev/cpuset/system-background/tasks
diff --git a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
index e0e1394..19c4653 100644
--- a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
+++ b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
@@ -222,6 +222,10 @@
Error getDisplayCapabilities(
Display display,
std::vector<IComposerClient::DisplayCapability>* outCapabilities) override {
+ if (!mDispatch.getDisplayCapabilities) {
+ return Error::UNSUPPORTED;
+ }
+
uint32_t count = 0;
int32_t error = mDispatch.getDisplayCapabilities(mDevice, display, &count, nullptr);
if (error != HWC2_ERROR_NONE) {
diff --git a/graphics/composer/2.4/default/android.hardware.graphics.composer@2.4-service.rc b/graphics/composer/2.4/default/android.hardware.graphics.composer@2.4-service.rc
index a296b0a..802b99e 100644
--- a/graphics/composer/2.4/default/android.hardware.graphics.composer@2.4-service.rc
+++ b/graphics/composer/2.4/default/android.hardware.graphics.composer@2.4-service.rc
@@ -5,3 +5,4 @@
capabilities SYS_NICE
onrestart restart surfaceflinger
writepid /dev/cpuset/system-background/tasks
+ socket pps stream 0660 system system
diff --git a/health/1.0/default/Android.bp b/health/1.0/default/Android.bp
index 7581335..b815eae 100644
--- a/health/1.0/default/Android.bp
+++ b/health/1.0/default/Android.bp
@@ -51,6 +51,12 @@
"android.hardware.health@1.0-convert",
"libhealthd.default",
],
+
+ shared_libs: [
+ "libhidlbase",
+ "libutils",
+ "android.hardware.health@1.0",
+ ],
}
cc_binary {
diff --git a/health/1.0/default/android.hardware.health@1.0-service.rc b/health/1.0/default/android.hardware.health@1.0-service.rc
index 405784f..569dc88 100644
--- a/health/1.0/default/android.hardware.health@1.0-service.rc
+++ b/health/1.0/default/android.hardware.health@1.0-service.rc
@@ -2,4 +2,4 @@
class hal
user system
group system
- capabilities WAKE_ALARM
+ capabilities WAKE_ALARM BLOCK_SUSPEND
diff --git a/health/2.1/default/android.hardware.health@2.1-service.rc b/health/2.1/default/android.hardware.health@2.1-service.rc
index b6d9e3b..8728257 100644
--- a/health/2.1/default/android.hardware.health@2.1-service.rc
+++ b/health/2.1/default/android.hardware.health@2.1-service.rc
@@ -2,5 +2,5 @@
class hal charger
user system
group system
- capabilities WAKE_ALARM
+ capabilities WAKE_ALARM BLOCK_SUSPEND
file /dev/kmsg w
diff --git a/identity/aidl/android/hardware/identity/IIdentityCredential.aidl b/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
index 730b601..702334d 100644
--- a/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
+++ b/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
@@ -55,7 +55,7 @@
* This method may only be called once per instance. If called more than once, STATUS_FAILED
* will be returned.
*
- * @return the unencrypted key-pair in PKCS#8 format.
+ * @return the private key, in DER format as specified in RFC 5915.
*/
byte[] createEphemeralKeyPair();
@@ -88,10 +88,10 @@
* The setRequestedNamespaces() and setVerificationToken() methods will be called before
* this method is called.
*
- * This method be called after createEphemeralKeyPair(), setReaderEphemeralPublicKey(),
- * createAuthChallenge() and before startRetrieveEntry(). This method call is followed by
- * multiple calls of startRetrieveEntryValue(), retrieveEntryValue(), and finally
- * finishRetrieval().
+ * This method is called after createEphemeralKeyPair(), setReaderEphemeralPublicKey(),
+ * createAuthChallenge() (note that those calls are optional) and before startRetrieveEntry().
+ * This method call is followed by multiple calls of startRetrieveEntryValue(),
+ * retrieveEntryValue(), and finally finishRetrieval().
*
* It is permissible to perform data retrievals multiple times using the same instance (e.g.
* startRetrieval(), then multiple calls of startRetrieveEntryValue(), retrieveEntryValue(),
@@ -343,12 +343,13 @@
*
* - signature: must be set to ECDSA.
*
- * - subject: CN shall be set to "Android Identity Credential Authentication Key".
+ * - subject: CN shall be set to "Android Identity Credential Authentication Key". (fixed
+ * value: same on all certs)
*
- * - issuer: shall be set to "credentialStoreName (credentialStoreAuthorName)" using the
- * values returned in HardwareInformation.
+ * - issuer: CN shall be set to "Android Identity Credential Key". (fixed value:
+ * same on all certs)
*
- * - validity: should be from current time and one year in the future.
+ * - validity: should be from current time and one year in the future (365 days).
*
* - subjectPublicKeyInfo: must contain attested public key.
*
diff --git a/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl b/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
index 297fd1d..c48cb66 100644
--- a/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
+++ b/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
@@ -37,12 +37,12 @@
*
* - signature: must be set to ECDSA.
*
- * - subject: CN shall be set to "Android Identity Credential Key".
+ * - subject: CN shall be set to "Android Identity Credential Key". (fixed value:
+ * same on all certs)
*
- * - issuer: shall be set to "credentialStoreName (credentialStoreAuthorName)" using the
- * values returned in HardwareInformation.
+ * - issuer: Same as the subject field of the batch attestation key.
*
- * - validity: should be from current time and expire at the same time as the
+ * - validity: Should be set to current time and expire at the same time as the
* attestation batch certificate used.
*
* - subjectPublicKeyInfo: must contain attested public key.
@@ -55,19 +55,14 @@
*
* - The attestationSecurityLevel field must be set to either Software (0),
* TrustedEnvironment (1), or StrongBox (2) depending on how attestation is
- * implemented. Only the default AOSP implementation of this HAL may use
- * value 0 (additionally, this implementation must not be used on production
- * devices).
+ * implemented.
*
- * - The keymasterVersion field in the attestation extension must be set to (10*major + minor)
- * where major and minor are the Identity Credential interface major and minor versions.
- * Specifically for this version of the interface (1.0) this value is 10.
+ * - The keymasterVersion field in the attestation extension must be set to the.
+ * same value as used for Android Keystore keys.
*
* - The keymasterSecurityLevel field in the attestation extension must be set to
* either Software (0), TrustedEnvironment (1), or StrongBox (2) depending on how
- * the Trusted Application backing the HAL implementation is implemented. Only
- * the default AOSP implementation of this HAL may use value 0 (additionally, this
- * implementation must not be used on production devices)
+ * the Trusted Application backing the HAL implementation is implemented.
*
* - The attestationChallenge field must be set to the passed-in challenge.
*
@@ -81,7 +76,8 @@
*
* - Tag::IDENTITY_CREDENTIAL_KEY which indicates that the key is an Identity
* Credential key (which can only sign/MAC very specific messages) and not an Android
- * Keystore key (which can be used to sign/MAC anything).
+ * Keystore key (which can be used to sign/MAC anything). This must not be set
+ * for test credentials.
*
* - Tag::PURPOSE must be set to SIGN
*
@@ -95,10 +91,13 @@
*
* - Tag::EC_CURVE must be set to P_256
*
- * Additional authorizations may be needed in the softwareEnforced and teeEnforced
- * fields - the above is not an exhaustive list. Specifically, authorizations containing
- * information about the root of trust, OS version, verified boot state, and so on should
- * be included.
+ * - Tag::ROOT_OF_TRUST must be set
+ *
+ * - Tag::OS_VERSION and Tag::OS_PATCHLEVEL must be set
+ *
+ * Additional authorizations may be appear in the softwareEnforced and teeEnforced
+ * fields. For example if the device has a boot or vendor partitions, then BOOT_PATCHLEVEL
+ * and VENDOR_PATCHLEVEL should be set.
*
* Since the chain is required to be generated using Keymaster Attestation, the returned
* certificate chain has the following properties:
@@ -112,8 +111,8 @@
* As with any user of attestation, the Issuing Authority (as a relying party) wishing
* to issue a credential to a device using these APIs, must carefully examine the
* returned certificate chain for all of the above (and more). In particular, the Issuing
- * Authority should check the root of trust, verified boot state, patch level,
- * application id, etc.
+ * Authority should check the root of trust (which include verified boot state), patch level,
+ * attestation application id, etc.
*
* This all depends on the needs of the Issuing Authority and the kind of credential but
* in general an Issuing Authority should never issue a credential to a device without
diff --git a/identity/aidl/default/IdentityCredential.cpp b/identity/aidl/default/IdentityCredential.cpp
index 10f9aa5..41d410d 100644
--- a/identity/aidl/default/IdentityCredential.cpp
+++ b/identity/aidl/default/IdentityCredential.cpp
@@ -276,6 +276,7 @@
auto itemsRequest = byteStringToUnsigned(itemsRequestS);
auto readerSignature = byteStringToUnsigned(readerSignatureS);
+ std::unique_ptr<cppbor::Item> sessionTranscriptItem;
if (sessionTranscript.size() > 0) {
auto [item, _, message] = cppbor::parse(sessionTranscript);
if (item == nullptr) {
@@ -283,7 +284,7 @@
IIdentityCredentialStore::STATUS_INVALID_DATA,
"SessionTranscript contains invalid CBOR"));
}
- sessionTranscriptItem_ = std::move(item);
+ sessionTranscriptItem = std::move(item);
}
if (numStartRetrievalCalls_ > 0) {
if (sessionTranscript_ != sessionTranscript) {
@@ -323,7 +324,7 @@
vector<uint8_t> encodedReaderAuthentication =
cppbor::Array()
.add("ReaderAuthentication")
- .add(sessionTranscriptItem_->clone())
+ .add(std::move(sessionTranscriptItem))
.add(cppbor::Semantic(24, itemsRequestBytes))
.encode();
vector<uint8_t> encodedReaderAuthenticationBytes =
@@ -781,13 +782,6 @@
optional<vector<uint8_t>> mac;
if (signingKeyBlob_.size() > 0 && sessionTranscript_.size() > 0 &&
readerPublicKey_.size() > 0) {
- cppbor::Array array;
- array.add("DeviceAuthentication");
- array.add(sessionTranscriptItem_->clone());
- array.add(docType_);
- array.add(cppbor::Semantic(24, encodedDeviceNameSpaces));
- vector<uint8_t> deviceAuthenticationBytes = cppbor::Semantic(24, array.encode()).encode();
-
vector<uint8_t> docTypeAsBlob(docType_.begin(), docType_.end());
optional<vector<uint8_t>> signingKey =
support::decryptAes128Gcm(storageKey_, signingKeyBlob_, docTypeAsBlob);
@@ -797,31 +791,15 @@
"Error decrypting signingKeyBlob"));
}
- optional<vector<uint8_t>> sharedSecret =
- support::ecdh(readerPublicKey_, signingKey.value());
- if (!sharedSecret) {
- return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
- IIdentityCredentialStore::STATUS_FAILED, "Error doing ECDH"));
- }
-
- // Mix-in SessionTranscriptBytes
vector<uint8_t> sessionTranscriptBytes = cppbor::Semantic(24, sessionTranscript_).encode();
- vector<uint8_t> sharedSecretWithSessionTranscriptBytes = sharedSecret.value();
- std::copy(sessionTranscriptBytes.begin(), sessionTranscriptBytes.end(),
- std::back_inserter(sharedSecretWithSessionTranscriptBytes));
-
- vector<uint8_t> salt = {0x00};
- vector<uint8_t> info = {};
- optional<vector<uint8_t>> derivedKey =
- support::hkdf(sharedSecretWithSessionTranscriptBytes, salt, info, 32);
- if (!derivedKey) {
+ optional<vector<uint8_t>> eMacKey =
+ support::calcEMacKey(signingKey.value(), readerPublicKey_, sessionTranscriptBytes);
+ if (!eMacKey) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
- IIdentityCredentialStore::STATUS_FAILED,
- "Error deriving key from shared secret"));
+ IIdentityCredentialStore::STATUS_FAILED, "Error calculating EMacKey"));
}
-
- mac = support::coseMac0(derivedKey.value(), {}, // payload
- deviceAuthenticationBytes); // detached content
+ mac = support::calcMac(sessionTranscript_, docType_, encodedDeviceNameSpaces,
+ eMacKey.value());
if (!mac) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_FAILED, "Error MACing data"));
@@ -835,9 +813,9 @@
ndk::ScopedAStatus IdentityCredential::generateSigningKeyPair(
vector<int8_t>* outSigningKeyBlob, Certificate* outSigningKeyCertificate) {
- string serialDecimal = "0"; // TODO: set serial to something unique
- string issuer = "Android Open Source Project";
- string subject = "Android IdentityCredential Reference Implementation";
+ string serialDecimal = "1";
+ string issuer = "Android Identity Credential Key";
+ string subject = "Android Identity Credential Authentication Key";
time_t validityNotBefore = time(nullptr);
time_t validityNotAfter = validityNotBefore + 365 * 24 * 3600;
diff --git a/identity/aidl/default/IdentityCredential.h b/identity/aidl/default/IdentityCredential.h
index 40070c0..f44d731 100644
--- a/identity/aidl/default/IdentityCredential.h
+++ b/identity/aidl/default/IdentityCredential.h
@@ -103,7 +103,6 @@
map<int32_t, int> profileIdToAccessCheckResult_;
vector<uint8_t> signingKeyBlob_;
vector<uint8_t> sessionTranscript_;
- std::unique_ptr<cppbor::Item> sessionTranscriptItem_;
vector<uint8_t> itemsRequest_;
vector<int32_t> requestCountsRemaining_;
map<string, set<string>> requestedNameSpacesAndNames_;
diff --git a/identity/aidl/default/WritableIdentityCredential.cpp b/identity/aidl/default/WritableIdentityCredential.cpp
index c218866..4428543 100644
--- a/identity/aidl/default/WritableIdentityCredential.cpp
+++ b/identity/aidl/default/WritableIdentityCredential.cpp
@@ -74,7 +74,7 @@
vector<uint8_t> appId(attestationApplicationId.begin(), attestationApplicationId.end());
optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> keyAttestationPair =
- support::createEcKeyPairAndAttestation(challenge, appId);
+ support::createEcKeyPairAndAttestation(challenge, appId, testCredential_);
if (!keyAttestationPair) {
LOG(ERROR) << "Error creating credentialKey and attestation";
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
diff --git a/identity/aidl/vts/Android.bp b/identity/aidl/vts/Android.bp
index c1f44e7..03966de 100644
--- a/identity/aidl/vts/Android.bp
+++ b/identity/aidl/vts/Android.bp
@@ -9,7 +9,6 @@
"VtsIWritableIdentityCredentialTests.cpp",
"VtsIdentityTestUtils.cpp",
"VtsAttestationTests.cpp",
- "VtsAttestationParserSupport.cpp",
"UserAuthTests.cpp",
"ReaderAuthTests.cpp",
],
@@ -20,13 +19,14 @@
static_libs: [
"libcppbor",
"libkeymaster_portable",
- "libsoft_attestation_cert",
"libpuresoftkeymasterdevice",
"android.hardware.keymaster@4.0",
"android.hardware.identity-support-lib",
"android.hardware.identity-cpp",
"android.hardware.keymaster-cpp",
"android.hardware.keymaster-ndk_platform",
+ "libkeymaster4support",
+ "libkeymaster4_1support",
],
test_suites: [
"general-tests",
diff --git a/identity/aidl/vts/VtsAttestationParserSupport.cpp b/identity/aidl/vts/VtsAttestationParserSupport.cpp
deleted file mode 100644
index 71fe733..0000000
--- a/identity/aidl/vts/VtsAttestationParserSupport.cpp
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "VtsAttestationParserSupport.h"
-
-#include <aidl/Gtest.h>
-#include <map>
-
-namespace android::hardware::identity::test_utils {
-
-using std::endl;
-using std::map;
-using std::optional;
-using std::string;
-using std::vector;
-
-using ::android::sp;
-using ::android::String16;
-using ::android::binder::Status;
-
-using ::keymaster::ASN1_OBJECT_Ptr;
-using ::keymaster::AuthorizationSet;
-using ::keymaster::EVP_PKEY_Ptr;
-using ::keymaster::kAttestionRecordOid;
-using ::keymaster::TAG_ATTESTATION_APPLICATION_ID;
-using ::keymaster::TAG_IDENTITY_CREDENTIAL_KEY;
-using ::keymaster::TAG_INCLUDE_UNIQUE_ID;
-using ::keymaster::TypedTag;
-using ::keymaster::X509_Ptr;
-
-using support::certificateChainSplit;
-
-optional<keymaster_cert_chain_t> AttestationCertificateParser::certificateChainToKeymasterChain(
- const vector<Certificate>& certificates) {
- if (certificates.size() <= 0) {
- return {};
- }
-
- keymaster_cert_chain_t kCert;
- kCert.entry_count = certificates.size();
- kCert.entries = (keymaster_blob_t*)malloc(sizeof(keymaster_blob_t) * kCert.entry_count);
-
- int index = 0;
- for (const auto& c : certificates) {
- kCert.entries[index].data_length = c.encodedCertificate.size();
- uint8_t* data = (uint8_t*)malloc(c.encodedCertificate.size());
-
- memcpy(data, c.encodedCertificate.data(), c.encodedCertificate.size());
- kCert.entries[index].data = (const uint8_t*)data;
- index++;
- }
-
- return kCert;
-}
-
-bool AttestationCertificateParser::parse() {
- optional<keymaster_cert_chain_t> cert_chain = certificateChainToKeymasterChain(origCertChain_);
- if (!cert_chain) {
- return false;
- }
-
- if (cert_chain.value().entry_count < 3) {
- return false;
- }
-
- if (!verifyChain(cert_chain.value())) {
- return false;
- }
-
- if (!verifyAttestationRecord(cert_chain.value().entries[0])) {
- return false;
- }
-
- keymaster_free_cert_chain(&cert_chain.value());
- return true;
-}
-
-ASN1_OCTET_STRING* AttestationCertificateParser::getAttestationRecord(X509* certificate) {
- ASN1_OBJECT_Ptr oid(OBJ_txt2obj(kAttestionRecordOid, 1));
- if (!oid.get()) return nullptr;
-
- int location = X509_get_ext_by_OBJ(certificate, oid.get(), -1);
- if (location == -1) return nullptr;
-
- X509_EXTENSION* attest_rec_ext = X509_get_ext(certificate, location);
- if (!attest_rec_ext) return nullptr;
-
- ASN1_OCTET_STRING* attest_rec = X509_EXTENSION_get_data(attest_rec_ext);
- return attest_rec;
-}
-
-X509* AttestationCertificateParser::parseCertBlob(const keymaster_blob_t& blob) {
- const uint8_t* p = blob.data;
- return d2i_X509(nullptr, &p, blob.data_length);
-}
-
-bool AttestationCertificateParser::verifyAttestationRecord(
- const keymaster_blob_t& attestation_cert) {
- X509_Ptr cert(parseCertBlob(attestation_cert));
- if (!cert.get()) {
- return false;
- }
-
- ASN1_OCTET_STRING* attest_rec = getAttestationRecord(cert.get());
- if (!attest_rec) {
- return false;
- }
-
- keymaster_blob_t att_unique_id = {};
- keymaster_blob_t att_challenge;
- keymaster_error_t ret = parse_attestation_record(
- attest_rec->data, attest_rec->length, &att_attestation_version_,
- &att_attestation_security_level_, &att_keymaster_version_,
- &att_keymaster_security_level_, &att_challenge, &att_sw_enforced_, &att_hw_enforced_,
- &att_unique_id);
- if (ret) {
- return false;
- }
-
- att_challenge_.assign(att_challenge.data, att_challenge.data + att_challenge.data_length);
- return true;
-}
-
-uint32_t AttestationCertificateParser::getKeymasterVersion() {
- return att_keymaster_version_;
-}
-
-uint32_t AttestationCertificateParser::getAttestationVersion() {
- return att_attestation_version_;
-}
-
-vector<uint8_t> AttestationCertificateParser::getAttestationChallenge() {
- return att_challenge_;
-}
-
-keymaster_security_level_t AttestationCertificateParser::getKeymasterSecurityLevel() {
- return att_keymaster_security_level_;
-}
-
-keymaster_security_level_t AttestationCertificateParser::getAttestationSecurityLevel() {
- return att_attestation_security_level_;
-}
-
-// Verify the Attestation certificates are correctly chained.
-bool AttestationCertificateParser::verifyChain(const keymaster_cert_chain_t& chain) {
- for (size_t i = 0; i < chain.entry_count - 1; ++i) {
- keymaster_blob_t& key_cert_blob = chain.entries[i];
- keymaster_blob_t& signing_cert_blob = chain.entries[i + 1];
-
- X509_Ptr key_cert(parseCertBlob(key_cert_blob));
- X509_Ptr signing_cert(parseCertBlob(signing_cert_blob));
- if (!key_cert.get() || !signing_cert.get()) {
- return false;
- }
-
- EVP_PKEY_Ptr signing_pubkey(X509_get_pubkey(signing_cert.get()));
- if (!signing_pubkey.get()) return false;
-
- if (X509_verify(key_cert.get(), signing_pubkey.get()) != 1) {
- return false;
- }
-
- if (i + 1 == chain.entry_count - 1) {
- // Last entry is self-signed.
- if (X509_verify(signing_cert.get(), signing_pubkey.get()) != 1) {
- return false;
- }
- }
- }
-
- return true;
-}
-
-} // namespace android::hardware::identity::test_utils
diff --git a/identity/aidl/vts/VtsAttestationParserSupport.h b/identity/aidl/vts/VtsAttestationParserSupport.h
deleted file mode 100644
index 7c7e1b6..0000000
--- a/identity/aidl/vts/VtsAttestationParserSupport.h
+++ /dev/null
@@ -1,122 +0,0 @@
-
-/*
- * Copyright 2019, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef VTS_ATTESTATION_PARSER_SUPPORT_H
-#define VTS_ATTESTATION_PARSER_SUPPORT_H
-
-//#include <aidl/Gtest.h>
-#include <android/hardware/identity/IIdentityCredentialStore.h>
-#include <android/hardware/identity/support/IdentityCredentialSupport.h>
-#include <android/hardware/keymaster/4.0/types.h>
-#include <hardware/keymaster_defs.h>
-#include <keymaster/android_keymaster_utils.h>
-#include <keymaster/authorization_set.h>
-#include <keymaster/contexts/pure_soft_keymaster_context.h>
-#include <keymaster/contexts/soft_attestation_cert.h>
-#include <keymaster/keymaster_tags.h>
-#include <keymaster/km_openssl/attestation_utils.h>
-#include <vector>
-
-namespace android::hardware::identity::test_utils {
-
-using ::std::optional;
-using ::std::string;
-using ::std::vector;
-
-using ::keymaster::AuthorizationSet;
-using ::keymaster::TypedTag;
-
-class AttestationCertificateParser {
- public:
- AttestationCertificateParser(const vector<Certificate>& certChain)
- : origCertChain_(certChain) {}
-
- bool parse();
-
- uint32_t getKeymasterVersion();
- uint32_t getAttestationVersion();
- vector<uint8_t> getAttestationChallenge();
- keymaster_security_level_t getKeymasterSecurityLevel();
- keymaster_security_level_t getAttestationSecurityLevel();
-
- template <keymaster_tag_t Tag>
- bool getSwEnforcedBool(TypedTag<KM_BOOL, Tag> tag) {
- if (att_sw_enforced_.GetTagValue(tag)) {
- return true;
- }
-
- return false;
- }
-
- template <keymaster_tag_t Tag>
- bool getHwEnforcedBool(TypedTag<KM_BOOL, Tag> tag) {
- if (att_hw_enforced_.GetTagValue(tag)) {
- return true;
- }
-
- return false;
- }
-
- template <keymaster_tag_t Tag>
- optional<vector<uint8_t>> getHwEnforcedBlob(TypedTag<KM_BYTES, Tag> tag) {
- keymaster_blob_t blob;
- if (att_hw_enforced_.GetTagValue(tag, &blob)) {
- return {};
- }
-
- vector<uint8_t> ret(blob.data, blob.data + blob.data_length);
- return ret;
- }
-
- template <keymaster_tag_t Tag>
- optional<vector<uint8_t>> getSwEnforcedBlob(TypedTag<KM_BYTES, Tag> tag) {
- keymaster_blob_t blob;
- if (!att_sw_enforced_.GetTagValue(tag, &blob)) {
- return {};
- }
-
- vector<uint8_t> ret(blob.data, blob.data + blob.data_length);
- return ret;
- }
-
- private:
- // Helper functions.
- bool verifyChain(const keymaster_cert_chain_t& chain);
-
- ASN1_OCTET_STRING* getAttestationRecord(X509* certificate);
-
- X509* parseCertBlob(const keymaster_blob_t& blob);
-
- bool verifyAttestationRecord(const keymaster_blob_t& attestation_cert);
-
- optional<keymaster_cert_chain_t> certificateChainToKeymasterChain(
- const vector<Certificate>& certificates);
-
- // Private variables.
- vector<Certificate> origCertChain_;
- AuthorizationSet att_sw_enforced_;
- AuthorizationSet att_hw_enforced_;
- uint32_t att_attestation_version_;
- uint32_t att_keymaster_version_;
- keymaster_security_level_t att_attestation_security_level_;
- keymaster_security_level_t att_keymaster_security_level_;
- vector<uint8_t> att_challenge_;
-};
-
-} // namespace android::hardware::identity::test_utils
-
-#endif // VTS_ATTESTATION_PARSER_SUPPORT_H
diff --git a/identity/aidl/vts/VtsAttestationTests.cpp b/identity/aidl/vts/VtsAttestationTests.cpp
index c7cdfc7..e5871fb 100644
--- a/identity/aidl/vts/VtsAttestationTests.cpp
+++ b/identity/aidl/vts/VtsAttestationTests.cpp
@@ -29,7 +29,6 @@
#include <future>
#include <map>
-#include "VtsAttestationParserSupport.h"
#include "VtsIdentityTestUtils.h"
namespace android::hardware::identity {
@@ -44,7 +43,6 @@
using ::android::String16;
using ::android::binder::Status;
-using test_utils::AttestationCertificateParser;
using test_utils::setupWritableCredential;
using test_utils::validateAttestationCertificate;
@@ -61,38 +59,12 @@
sp<IIdentityCredentialStore> credentialStore_;
};
-TEST_P(VtsAttestationTests, verifyAttestationWithNonemptyChallengeEmptyId) {
- Status result;
-
- HardwareInformation hwInfo;
- ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
-
- sp<IWritableIdentityCredential> writableCredential;
- ASSERT_TRUE(setupWritableCredential(writableCredential, credentialStore_));
-
- string challenge = "NotSoRandomChallenge";
- vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
- vector<Certificate> attestationCertificate;
- vector<uint8_t> attestationApplicationId = {};
-
- result = writableCredential->getAttestationCertificate(
- attestationApplicationId, attestationChallenge, &attestationCertificate);
-
- ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
- << endl;
-
- EXPECT_TRUE(validateAttestationCertificate(attestationCertificate, attestationChallenge,
- attestationApplicationId, hwInfo));
-}
-
TEST_P(VtsAttestationTests, verifyAttestationWithNonemptyChallengeNonemptyId) {
Status result;
- HardwareInformation hwInfo;
- ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
-
sp<IWritableIdentityCredential> writableCredential;
- ASSERT_TRUE(setupWritableCredential(writableCredential, credentialStore_));
+ ASSERT_TRUE(setupWritableCredential(writableCredential, credentialStore_,
+ false /* testCredential */));
string challenge = "NotSoRandomChallenge1NotSoRandomChallenge1NotSoRandomChallenge1";
vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
@@ -106,18 +78,16 @@
ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
<< endl;
- EXPECT_TRUE(validateAttestationCertificate(attestationCertificate, attestationChallenge,
- attestationApplicationId, hwInfo));
+ validateAttestationCertificate(attestationCertificate, attestationChallenge,
+ attestationApplicationId, false);
}
TEST_P(VtsAttestationTests, verifyAttestationWithVeryShortChallengeAndId) {
Status result;
- HardwareInformation hwInfo;
- ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
-
sp<IWritableIdentityCredential> writableCredential;
- ASSERT_TRUE(setupWritableCredential(writableCredential, credentialStore_));
+ ASSERT_TRUE(setupWritableCredential(writableCredential, credentialStore_,
+ false /* testCredential */));
string challenge = "c";
vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
@@ -131,8 +101,8 @@
ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
<< endl;
- EXPECT_TRUE(validateAttestationCertificate(attestationCertificate, attestationChallenge,
- attestationApplicationId, hwInfo));
+ validateAttestationCertificate(attestationCertificate, attestationChallenge,
+ attestationApplicationId, false);
}
INSTANTIATE_TEST_SUITE_P(
diff --git a/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp b/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp
index e347654..7657943 100644
--- a/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp
+++ b/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp
@@ -174,16 +174,17 @@
string cborPretty;
sp<IWritableIdentityCredential> writableCredential;
- ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+ ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+ true /* testCredential */));
string challenge = "attestationChallenge";
- test_utils::AttestationData attData(writableCredential, challenge, {});
+ test_utils::AttestationData attData(writableCredential, challenge,
+ {1} /* atteestationApplicationId */);
ASSERT_TRUE(attData.result.isOk())
<< attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
- EXPECT_TRUE(validateAttestationCertificate(attData.attestationCertificate,
- attData.attestationChallenge,
- attData.attestationApplicationId, hwInfo));
+ validateAttestationCertificate(attData.attestationCertificate, attData.attestationChallenge,
+ attData.attestationApplicationId, true);
// This is kinda of a hack but we need to give the size of
// ProofOfProvisioning that we'll expect to receive.
@@ -368,6 +369,7 @@
optional<vector<uint8_t>> signingPubKey =
support::certificateChainGetTopMostKey(signingKeyCertificate.encodedCertificate);
EXPECT_TRUE(signingPubKey);
+ test_utils::verifyAuthKeyCertificate(signingKeyCertificate.encodedCertificate);
// Since we're using a test-credential we know storageKey meaning we can get the
// private key. Do this, derive the public key from it, and check this matches what
@@ -418,9 +420,9 @@
}
vector<uint8_t> mac;
- vector<uint8_t> deviceNameSpacesBytes;
- ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesBytes).isOk());
- cborPretty = support::cborPrettyPrint(deviceNameSpacesBytes, 32, {});
+ vector<uint8_t> deviceNameSpacesEncoded;
+ ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesEncoded).isOk());
+ cborPretty = support::cborPrettyPrint(deviceNameSpacesEncoded, 32, {});
ASSERT_EQ(
"{\n"
" 'PersonalData' : {\n"
@@ -435,37 +437,19 @@
" },\n"
"}",
cborPretty);
- // The data that is MACed is ["DeviceAuthentication", sessionTranscript, docType,
- // deviceNameSpacesBytes] so build up that structure
- cppbor::Array deviceAuthentication;
- deviceAuthentication.add("DeviceAuthentication");
- deviceAuthentication.add(sessionTranscript.clone());
string docType = "org.iso.18013-5.2019.mdl";
- deviceAuthentication.add(docType);
- deviceAuthentication.add(cppbor::Semantic(24, deviceNameSpacesBytes));
- vector<uint8_t> deviceAuthenticationBytes =
- cppbor::Semantic(24, deviceAuthentication.encode()).encode();
- // Derive the key used for MACing.
optional<vector<uint8_t>> readerEphemeralPrivateKey =
support::ecKeyPairGetPrivateKey(readerEphemeralKeyPair.value());
- optional<vector<uint8_t>> sharedSecret =
- support::ecdh(signingPubKey.value(), readerEphemeralPrivateKey.value());
- ASSERT_TRUE(sharedSecret);
- // Mix-in SessionTranscriptBytes
- vector<uint8_t> sessionTranscriptBytes =
- cppbor::Semantic(24, sessionTranscript.encode()).encode();
- vector<uint8_t> sharedSecretWithSessionTranscriptBytes = sharedSecret.value();
- std::copy(sessionTranscriptBytes.begin(), sessionTranscriptBytes.end(),
- std::back_inserter(sharedSecretWithSessionTranscriptBytes));
- vector<uint8_t> salt = {0x00};
- vector<uint8_t> info = {};
- optional<vector<uint8_t>> derivedKey =
- support::hkdf(sharedSecretWithSessionTranscriptBytes, salt, info, 32);
- ASSERT_TRUE(derivedKey);
+ optional<vector<uint8_t>> eMacKey = support::calcEMacKey(
+ readerEphemeralPrivateKey.value(), // Private Key
+ signingPubKey.value(), // Public Key
+ cppbor::Semantic(24, sessionTranscript.encode()).encode()); // SessionTranscriptBytes
optional<vector<uint8_t>> calculatedMac =
- support::coseMac0(derivedKey.value(), {}, // payload
- deviceAuthenticationBytes); // detached content
+ support::calcMac(sessionTranscript.encode(), // SessionTranscript
+ docType, // DocType
+ deviceNameSpacesEncoded, // DeviceNamespaces
+ eMacKey.value()); // EMacKey
ASSERT_TRUE(calculatedMac);
EXPECT_EQ(mac, calculatedMac);
@@ -480,18 +464,14 @@
signingKeyBlob, sessionTranscriptEncoded, {}, // readerSignature,
testEntriesEntryCounts)
.isOk());
- ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesBytes).isOk());
- cborPretty = support::cborPrettyPrint(deviceNameSpacesBytes, 32, {});
+ ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesEncoded).isOk());
+ cborPretty = support::cborPrettyPrint(deviceNameSpacesEncoded, 32, {});
ASSERT_EQ("{}", cborPretty);
// Calculate DeviceAuthentication and MAC (MACing key hasn't changed)
- deviceAuthentication = cppbor::Array();
- deviceAuthentication.add("DeviceAuthentication");
- deviceAuthentication.add(sessionTranscript.clone());
- deviceAuthentication.add(docType);
- deviceAuthentication.add(cppbor::Semantic(24, deviceNameSpacesBytes));
- deviceAuthenticationBytes = cppbor::Semantic(24, deviceAuthentication.encode()).encode();
- calculatedMac = support::coseMac0(derivedKey.value(), {}, // payload
- deviceAuthenticationBytes); // detached content
+ calculatedMac = support::calcMac(sessionTranscript.encode(), // SessionTranscript
+ docType, // DocType
+ deviceNameSpacesEncoded, // DeviceNamespaces
+ eMacKey.value()); // EMacKey
ASSERT_TRUE(calculatedMac);
EXPECT_EQ(mac, calculatedMac);
@@ -506,18 +486,14 @@
signingKeyBlob, sessionTranscriptEncoded, {}, // readerSignature,
testEntriesEntryCounts)
.isOk());
- ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesBytes).isOk());
- cborPretty = support::cborPrettyPrint(deviceNameSpacesBytes, 32, {});
+ ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesEncoded).isOk());
+ cborPretty = support::cborPrettyPrint(deviceNameSpacesEncoded, 32, {});
ASSERT_EQ("{}", cborPretty);
// Calculate DeviceAuthentication and MAC (MACing key hasn't changed)
- deviceAuthentication = cppbor::Array();
- deviceAuthentication.add("DeviceAuthentication");
- deviceAuthentication.add(sessionTranscript.clone());
- deviceAuthentication.add(docType);
- deviceAuthentication.add(cppbor::Semantic(24, deviceNameSpacesBytes));
- deviceAuthenticationBytes = cppbor::Semantic(24, deviceAuthentication.encode()).encode();
- calculatedMac = support::coseMac0(derivedKey.value(), {}, // payload
- deviceAuthenticationBytes); // detached content
+ calculatedMac = support::calcMac(sessionTranscript.encode(), // SessionTranscript
+ docType, // DocType
+ deviceNameSpacesEncoded, // DeviceNamespaces
+ eMacKey.value()); // EMacKey
ASSERT_TRUE(calculatedMac);
EXPECT_EQ(mac, calculatedMac);
}
diff --git a/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp b/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
index b572b0f..5435ed8 100644
--- a/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
+++ b/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
@@ -61,7 +61,8 @@
ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
sp<IWritableIdentityCredential> writableCredential;
- ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+ ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+ false /* testCredential */));
vector<uint8_t> attestationChallenge;
vector<Certificate> attestationCertificate;
@@ -82,12 +83,13 @@
ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
sp<IWritableIdentityCredential> writableCredential;
- ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+ ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+ false /* testCredential */));
string challenge = "NotSoRandomChallenge1NotSoRandomChallenge1NotSoRandomChallenge1";
vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
vector<Certificate> attestationCertificate;
- vector<uint8_t> attestationApplicationId = {};
+ vector<uint8_t> attestationApplicationId = {1};
result = writableCredential->getAttestationCertificate(
attestationApplicationId, attestationChallenge, &attestationCertificate);
@@ -95,27 +97,27 @@
EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
<< endl;
- EXPECT_TRUE(test_utils::validateAttestationCertificate(
- attestationCertificate, attestationChallenge, attestationApplicationId, hwInfo));
+ test_utils::validateAttestationCertificate(attestationCertificate, attestationChallenge,
+ attestationApplicationId, false);
}
TEST_P(IdentityCredentialTests, verifyAttestationDoubleCallFails) {
Status result;
- HardwareInformation hwInfo;
- ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
-
sp<IWritableIdentityCredential> writableCredential;
- ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+ ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+ false /* testCredential */));
string challenge = "NotSoRandomChallenge1";
- test_utils::AttestationData attData(writableCredential, challenge, {});
- ASSERT_TRUE(test_utils::validateAttestationCertificate(
- attData.attestationCertificate, attData.attestationChallenge,
- attData.attestationApplicationId, hwInfo));
+ test_utils::AttestationData attData(writableCredential, challenge,
+ {1} /* atteestationApplicationId */);
+ test_utils::validateAttestationCertificate(attData.attestationCertificate,
+ attData.attestationChallenge,
+ attData.attestationApplicationId, false);
string challenge2 = "NotSoRandomChallenge2";
- test_utils::AttestationData attData2(writableCredential, challenge2, {});
+ test_utils::AttestationData attData2(writableCredential, challenge2,
+ {} /* atteestationApplicationId */);
EXPECT_FALSE(attData2.result.isOk()) << attData2.result.exceptionCode() << "; "
<< attData2.result.exceptionMessage() << endl;
EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, attData2.result.exceptionCode());
@@ -125,7 +127,8 @@
TEST_P(IdentityCredentialTests, verifyStartPersonalization) {
Status result;
sp<IWritableIdentityCredential> writableCredential;
- ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+ ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+ false /* testCredential */));
// First call should go through
const vector<int32_t> entryCounts = {2, 4};
@@ -147,7 +150,8 @@
TEST_P(IdentityCredentialTests, verifyStartPersonalizationMin) {
Status result;
sp<IWritableIdentityCredential> writableCredential;
- ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+ ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+ false /* testCredential */));
// Verify minimal number of profile count and entry count
const vector<int32_t> entryCounts = {1, 1};
@@ -160,7 +164,8 @@
TEST_P(IdentityCredentialTests, verifyStartPersonalizationOne) {
Status result;
sp<IWritableIdentityCredential> writableCredential;
- ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+ ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+ false /* testCredential */));
// Verify minimal number of profile count and entry count
const vector<int32_t> entryCounts = {1};
@@ -173,7 +178,8 @@
TEST_P(IdentityCredentialTests, verifyStartPersonalizationLarge) {
Status result;
sp<IWritableIdentityCredential> writableCredential;
- ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+ ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+ false /* testCredential */));
// Verify set a large number of profile count and entry count is ok
const vector<int32_t> entryCounts = {3000};
@@ -186,7 +192,8 @@
TEST_P(IdentityCredentialTests, verifyProfileNumberMismatchShouldFail) {
Status result;
sp<IWritableIdentityCredential> writableCredential;
- ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+ ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+ false /* testCredential */));
// Enter mismatched entry and profile numbers
const vector<int32_t> entryCounts = {5, 6};
@@ -224,7 +231,8 @@
TEST_P(IdentityCredentialTests, verifyDuplicateProfileId) {
Status result;
sp<IWritableIdentityCredential> writableCredential;
- ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+ ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+ false /* testCredential */));
const vector<int32_t> entryCounts = {3, 6};
writableCredential->setExpectedProofOfProvisioningSize(123456);
@@ -283,10 +291,12 @@
ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
sp<IWritableIdentityCredential> writableCredential;
- ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+ ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+ false /* testCredential */));
string challenge = "NotSoRandomChallenge1";
- test_utils::AttestationData attData(writableCredential, challenge, {});
+ test_utils::AttestationData attData(writableCredential, challenge,
+ {} /* atteestationApplicationId */);
EXPECT_TRUE(attData.result.isOk())
<< attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
@@ -294,7 +304,7 @@
ASSERT_TRUE(readerCertificate1);
const vector<int32_t> entryCounts = {1u};
- size_t expectedPoPSize = 186 + readerCertificate1.value().size();
+ size_t expectedPoPSize = 185 + readerCertificate1.value().size();
// OK to fail, not available in v1 HAL
writableCredential->setExpectedProofOfProvisioningSize(expectedPoPSize);
result = writableCredential->startPersonalization(1, entryCounts);
@@ -308,7 +318,7 @@
ASSERT_TRUE(secureProfiles);
const vector<test_utils::TestEntryData> testEntries1 = {
- {"Name Space", "Last name", string("Turing"), vector<int32_t>{0, 1}},
+ {"Name Space", "Last name", string("Turing"), vector<int32_t>{1}},
};
map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
@@ -347,11 +357,11 @@
" {\n"
" 'name' : 'Last name',\n"
" 'value' : 'Turing',\n"
- " 'accessControlProfiles' : [0, 1, ],\n"
+ " 'accessControlProfiles' : [1, ],\n"
" },\n"
" ],\n"
" },\n"
- " true,\n"
+ " false,\n"
"]",
cborPretty);
@@ -370,10 +380,12 @@
ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
sp<IWritableIdentityCredential> writableCredential;
- ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+ ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+ false /* testCredential */));
string challenge = "NotSoRandomChallenge";
- test_utils::AttestationData attData(writableCredential, challenge, {});
+ test_utils::AttestationData attData(writableCredential, challenge,
+ {} /* atteestationApplicationId */);
EXPECT_TRUE(attData.result.isOk())
<< attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
@@ -510,7 +522,7 @@
" },\n"
" ],\n"
" },\n"
- " true,\n"
+ " false,\n"
"]",
cborPretty);
@@ -529,10 +541,12 @@
ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
sp<IWritableIdentityCredential> writableCredential;
- ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+ ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+ false /* testCredential */));
string challenge = "NotSoRandomChallenge";
- test_utils::AttestationData attData(writableCredential, challenge, {});
+ test_utils::AttestationData attData(writableCredential, challenge,
+ {} /* atteestationApplicationId */);
ASSERT_TRUE(attData.result.isOk())
<< attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
@@ -591,10 +605,12 @@
ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
sp<IWritableIdentityCredential> writableCredential;
- ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+ ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+ false /* testCredential */));
string challenge = "NotSoRandomChallenge";
- test_utils::AttestationData attData(writableCredential, challenge, {});
+ test_utils::AttestationData attData(writableCredential, challenge,
+ {} /* atteestationApplicationId */);
ASSERT_TRUE(attData.result.isOk())
<< attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
@@ -667,7 +683,8 @@
TEST_P(IdentityCredentialTests, verifyAccessControlProfileIdOutOfRange) {
sp<IWritableIdentityCredential> writableCredential;
- ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+ ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_,
+ false /* testCredential */));
const vector<int32_t> entryCounts = {1};
writableCredential->setExpectedProofOfProvisioningSize(123456);
diff --git a/identity/aidl/vts/VtsIdentityTestUtils.cpp b/identity/aidl/vts/VtsIdentityTestUtils.cpp
index b6ed80f..3b10651 100644
--- a/identity/aidl/vts/VtsIdentityTestUtils.cpp
+++ b/identity/aidl/vts/VtsIdentityTestUtils.cpp
@@ -14,13 +14,17 @@
* limitations under the License.
*/
+#define LOG_TAG "VtsIdentityTestUtils"
+
#include "VtsIdentityTestUtils.h"
#include <aidl/Gtest.h>
+#include <android-base/logging.h>
+#include <keymaster/km_openssl/openssl_utils.h>
+#include <keymasterV4_1/attestation_record.h>
+#include <charconv>
#include <map>
-#include "VtsAttestationParserSupport.h"
-
namespace android::hardware::identity::test_utils {
using std::endl;
@@ -32,15 +36,15 @@
using ::android::sp;
using ::android::String16;
using ::android::binder::Status;
+using ::keymaster::X509_Ptr;
bool setupWritableCredential(sp<IWritableIdentityCredential>& writableCredential,
- sp<IIdentityCredentialStore>& credentialStore) {
+ sp<IIdentityCredentialStore>& credentialStore, bool testCredential) {
if (credentialStore == nullptr) {
return false;
}
string docType = "org.iso.18013-5.2019.mdl";
- bool testCredential = true;
Status result = credentialStore->createCredential(docType, testCredential, &writableCredential);
if (result.isOk() && writableCredential != nullptr) {
@@ -178,63 +182,269 @@
}
}
-bool validateAttestationCertificate(const vector<Certificate>& inputCertificates,
- const vector<uint8_t>& expectedChallenge,
- const vector<uint8_t>& expectedAppId,
- const HardwareInformation& hwInfo) {
- AttestationCertificateParser certParser_(inputCertificates);
- bool ret = certParser_.parse();
- EXPECT_TRUE(ret);
- if (!ret) {
+string x509NameToRfc2253String(X509_NAME* name) {
+ char* buf;
+ size_t bufSize;
+ BIO* bio;
+
+ bio = BIO_new(BIO_s_mem());
+ X509_NAME_print_ex(bio, name, 0, XN_FLAG_RFC2253);
+ bufSize = BIO_get_mem_data(bio, &buf);
+ string ret = string(buf, bufSize);
+ BIO_free(bio);
+
+ return ret;
+}
+
+int parseDigits(const char** s, int numDigits) {
+ int result;
+ auto [_, ec] = std::from_chars(*s, *s + numDigits, result);
+ if (ec != std::errc()) {
+ LOG(ERROR) << "Error parsing " << numDigits << " digits "
+ << " from " << s;
+ return 0;
+ }
+ *s += numDigits;
+ return result;
+}
+
+bool parseAsn1Time(const ASN1_TIME* asn1Time, time_t* outTime) {
+ struct tm tm;
+
+ memset(&tm, '\0', sizeof(tm));
+ const char* timeStr = (const char*)asn1Time->data;
+ const char* s = timeStr;
+ if (asn1Time->type == V_ASN1_UTCTIME) {
+ tm.tm_year = parseDigits(&s, 2);
+ if (tm.tm_year < 70) {
+ tm.tm_year += 100;
+ }
+ } else if (asn1Time->type == V_ASN1_GENERALIZEDTIME) {
+ tm.tm_year = parseDigits(&s, 4) - 1900;
+ tm.tm_year -= 1900;
+ } else {
+ LOG(ERROR) << "Unsupported ASN1_TIME type " << asn1Time->type;
+ return false;
+ }
+ tm.tm_mon = parseDigits(&s, 2) - 1;
+ tm.tm_mday = parseDigits(&s, 2);
+ tm.tm_hour = parseDigits(&s, 2);
+ tm.tm_min = parseDigits(&s, 2);
+ tm.tm_sec = parseDigits(&s, 2);
+ // This may need to be updated if someone create certificates using +/- instead of Z.
+ //
+ if (*s != 'Z') {
+ LOG(ERROR) << "Expected Z in string '" << timeStr << "' at offset " << (s - timeStr);
return false;
}
- // As per the IC HAL, the version of the Identity
- // Credential HAL is 1.0 - and this is encoded as major*10 + minor. This field is used by
- // Keymaster which is known to report integers less than or equal to 4 (for KM up to 4.0)
- // and integers greater or equal than 41 (for KM starting with 4.1).
- //
- // Since we won't get to version 4.0 of the IC HAL for a while, let's also check that a KM
- // version isn't errornously returned.
- EXPECT_LE(10, certParser_.getKeymasterVersion());
- EXPECT_GT(40, certParser_.getKeymasterVersion());
- EXPECT_LE(3, certParser_.getAttestationVersion());
-
- // Verify the app id matches to whatever we set it to be.
- optional<vector<uint8_t>> appId =
- certParser_.getSwEnforcedBlob(::keymaster::TAG_ATTESTATION_APPLICATION_ID);
- if (appId) {
- EXPECT_EQ(expectedAppId.size(), appId.value().size());
- EXPECT_EQ(0, memcmp(expectedAppId.data(), appId.value().data(), expectedAppId.size()));
- } else {
- // app id not found
- EXPECT_EQ(0, expectedAppId.size());
+ time_t t = timegm(&tm);
+ if (t == -1) {
+ LOG(ERROR) << "Error converting broken-down time to time_t";
+ return false;
}
-
- EXPECT_TRUE(certParser_.getHwEnforcedBool(::keymaster::TAG_IDENTITY_CREDENTIAL_KEY));
- EXPECT_FALSE(certParser_.getHwEnforcedBool(::keymaster::TAG_INCLUDE_UNIQUE_ID));
-
- // Verify the challenge always matches in size and data of what is passed
- // in.
- vector<uint8_t> attChallenge = certParser_.getAttestationChallenge();
- EXPECT_EQ(expectedChallenge.size(), attChallenge.size());
- EXPECT_EQ(0, memcmp(expectedChallenge.data(), attChallenge.data(), expectedChallenge.size()));
-
- // Ensure the attestation conveys that it's implemented in secure hardware (with carve-out
- // for the reference implementation which cannot be implemented in secure hardware).
- if (hwInfo.credentialStoreName == "Identity Credential Reference Implementation" &&
- hwInfo.credentialStoreAuthorName == "Google") {
- EXPECT_LE(KM_SECURITY_LEVEL_SOFTWARE, certParser_.getKeymasterSecurityLevel());
- EXPECT_LE(KM_SECURITY_LEVEL_SOFTWARE, certParser_.getAttestationSecurityLevel());
-
- } else {
- // Actual devices should use TrustedEnvironment or StrongBox.
- EXPECT_LE(KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT, certParser_.getKeymasterSecurityLevel());
- EXPECT_LE(KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT, certParser_.getAttestationSecurityLevel());
- }
+ *outTime = t;
return true;
}
+void validateAttestationCertificate(const vector<Certificate>& credentialKeyCertChain,
+ const vector<uint8_t>& expectedChallenge,
+ const vector<uint8_t>& expectedAppId, bool isTestCredential) {
+ ASSERT_GE(credentialKeyCertChain.size(), 2);
+
+ vector<uint8_t> certBytes = credentialKeyCertChain[0].encodedCertificate;
+ const uint8_t* certData = certBytes.data();
+ X509_Ptr cert = X509_Ptr(d2i_X509(nullptr, &certData, certBytes.size()));
+
+ vector<uint8_t> batchCertBytes = credentialKeyCertChain[1].encodedCertificate;
+ const uint8_t* batchCertData = batchCertBytes.data();
+ X509_Ptr batchCert = X509_Ptr(d2i_X509(nullptr, &batchCertData, batchCertBytes.size()));
+
+ // First get some values from the batch certificate which is checked
+ // against the top-level certificate (subject, notAfter)
+ //
+
+ X509_NAME* batchSubject = X509_get_subject_name(batchCert.get());
+ ASSERT_NE(nullptr, batchSubject);
+ time_t batchNotAfter;
+ ASSERT_TRUE(parseAsn1Time(X509_get0_notAfter(batchCert.get()), &batchNotAfter));
+
+ // Check all the requirements from IWritableIdentityCredential::getAttestationCertificate()...
+ //
+
+ // - version: INTEGER 2 (means v3 certificate).
+ EXPECT_EQ(2, X509_get_version(cert.get()));
+
+ // - serialNumber: INTEGER 1 (fixed value: same on all certs).
+ EXPECT_EQ(1, ASN1_INTEGER_get(X509_get_serialNumber(cert.get())));
+
+ // - signature: must be set to ECDSA.
+ EXPECT_EQ(NID_ecdsa_with_SHA256, X509_get_signature_nid(cert.get()));
+
+ // - subject: CN shall be set to "Android Identity Credential Key". (fixed value:
+ // same on all certs)
+ X509_NAME* subject = X509_get_subject_name(cert.get());
+ ASSERT_NE(nullptr, subject);
+ EXPECT_EQ("CN=Android Identity Credential Key", x509NameToRfc2253String(subject));
+
+ // - issuer: Same as the subject field of the batch attestation key.
+ X509_NAME* issuer = X509_get_issuer_name(cert.get());
+ ASSERT_NE(nullptr, issuer);
+ EXPECT_EQ(x509NameToRfc2253String(batchSubject), x509NameToRfc2253String(issuer));
+
+ // - validity: Should be from current time and expire at the same time as the
+ // attestation batch certificate used.
+ //
+ // Allow for 10 seconds drift to account for the time drift between Secure HW
+ // and this environment plus the difference between when the certificate was
+ // created and until now
+ //
+ time_t notBefore;
+ ASSERT_TRUE(parseAsn1Time(X509_get0_notBefore(cert.get()), ¬Before));
+ uint64_t now = time(nullptr);
+ int64_t diffSecs = now - notBefore;
+ int64_t allowDriftSecs = 10;
+ EXPECT_LE(-allowDriftSecs, diffSecs);
+ EXPECT_GE(allowDriftSecs, diffSecs);
+
+ time_t notAfter;
+ ASSERT_TRUE(parseAsn1Time(X509_get0_notAfter(cert.get()), ¬After));
+ EXPECT_EQ(notAfter, batchNotAfter);
+
+ auto [err, attRec] = keymaster::V4_1::parse_attestation_record(certBytes);
+ ASSERT_EQ(keymaster::V4_1::ErrorCode::OK, err);
+
+ // - subjectPublicKeyInfo: must contain attested public key.
+
+ // - The attestationVersion field in the attestation extension must be at least 3.
+ EXPECT_GE(attRec.attestation_version, 3);
+
+ // - The attestationSecurityLevel field must be set to either Software (0),
+ // TrustedEnvironment (1), or StrongBox (2) depending on how attestation is
+ // implemented.
+ EXPECT_GE(attRec.attestation_security_level,
+ keymaster::V4_0::SecurityLevel::TRUSTED_ENVIRONMENT);
+
+ // - The keymasterVersion field in the attestation extension must be set to the.
+ // same value as used for Android Keystore keys.
+ //
+ // Nothing to check here...
+
+ // - The keymasterSecurityLevel field in the attestation extension must be set to
+ // either Software (0), TrustedEnvironment (1), or StrongBox (2) depending on how
+ // the Trusted Application backing the HAL implementation is implemented.
+ EXPECT_GE(attRec.keymaster_security_level, keymaster::V4_0::SecurityLevel::TRUSTED_ENVIRONMENT);
+
+ // - The attestationChallenge field must be set to the passed-in challenge.
+ EXPECT_EQ(expectedChallenge.size(), attRec.attestation_challenge.size());
+ EXPECT_TRUE(memcmp(expectedChallenge.data(), attRec.attestation_challenge.data(),
+ attRec.attestation_challenge.size()) == 0);
+
+ // - The uniqueId field must be empty.
+ EXPECT_EQ(attRec.unique_id.size(), 0);
+
+ // - The softwareEnforced field in the attestation extension must include
+ // Tag::ATTESTATION_APPLICATION_ID which must be set to the bytes of the passed-in
+ // attestationApplicationId.
+ EXPECT_TRUE(attRec.software_enforced.Contains(keymaster::V4_0::TAG_ATTESTATION_APPLICATION_ID,
+ expectedAppId));
+
+ // - The teeEnforced field in the attestation extension must include
+ //
+ // - Tag::IDENTITY_CREDENTIAL_KEY which indicates that the key is an Identity
+ // Credential key (which can only sign/MAC very specific messages) and not an Android
+ // Keystore key (which can be used to sign/MAC anything). This must not be set
+ // for test credentials.
+ bool hasIcKeyTag =
+ attRec.hardware_enforced.Contains(static_cast<android::hardware::keymaster::V4_0::Tag>(
+ keymaster::V4_1::Tag::IDENTITY_CREDENTIAL_KEY));
+ if (isTestCredential) {
+ EXPECT_FALSE(hasIcKeyTag);
+ } else {
+ EXPECT_TRUE(hasIcKeyTag);
+ }
+
+ // - Tag::PURPOSE must be set to SIGN
+ EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_PURPOSE,
+ keymaster::V4_0::KeyPurpose::SIGN));
+
+ // - Tag::KEY_SIZE must be set to the appropriate key size, in bits (e.g. 256)
+ EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_KEY_SIZE, 256));
+
+ // - Tag::ALGORITHM must be set to EC
+ EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_ALGORITHM,
+ keymaster::V4_0::Algorithm::EC));
+
+ // - Tag::NO_AUTH_REQUIRED must be set
+ EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_NO_AUTH_REQUIRED));
+
+ // - Tag::DIGEST must be include SHA_2_256
+ EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_DIGEST,
+ keymaster::V4_0::Digest::SHA_2_256));
+
+ // - Tag::EC_CURVE must be set to P_256
+ EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_EC_CURVE,
+ keymaster::V4_0::EcCurve::P_256));
+
+ // - Tag::ROOT_OF_TRUST must be set
+ //
+ EXPECT_GE(attRec.root_of_trust.security_level,
+ keymaster::V4_0::SecurityLevel::TRUSTED_ENVIRONMENT);
+
+ // - Tag::OS_VERSION and Tag::OS_PATCHLEVEL must be set
+ EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_OS_VERSION));
+ EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_OS_PATCHLEVEL));
+
+ // TODO: we could retrieve osVersion and osPatchLevel from Android itself and compare it
+ // with what was reported in the certificate.
+}
+
+void verifyAuthKeyCertificate(const vector<uint8_t>& authKeyCertChain) {
+ const uint8_t* data = authKeyCertChain.data();
+ auto cert = X509_Ptr(d2i_X509(nullptr, &data, authKeyCertChain.size()));
+
+ // - version: INTEGER 2 (means v3 certificate).
+ EXPECT_EQ(X509_get_version(cert.get()), 2);
+
+ // - serialNumber: INTEGER 1 (fixed value: same on all certs).
+ EXPECT_EQ(ASN1_INTEGER_get(X509_get_serialNumber(cert.get())), 1);
+
+ // - signature: must be set to ECDSA.
+ EXPECT_EQ(X509_get_signature_nid(cert.get()), NID_ecdsa_with_SHA256);
+
+ // - subject: CN shall be set to "Android Identity Credential Authentication Key". (fixed
+ // value: same on all certs)
+ X509_NAME* subject = X509_get_subject_name(cert.get());
+ ASSERT_NE(subject, nullptr);
+ EXPECT_EQ(x509NameToRfc2253String(subject),
+ "CN=Android Identity Credential Authentication Key");
+
+ // - issuer: CN shall be set to "Android Identity Credential Key". (fixed value:
+ // same on all certs)
+ X509_NAME* issuer = X509_get_issuer_name(cert.get());
+ ASSERT_NE(issuer, nullptr);
+ EXPECT_EQ(x509NameToRfc2253String(issuer), "CN=Android Identity Credential Key");
+
+ // - subjectPublicKeyInfo: must contain attested public key.
+
+ // - validity: should be from current time and one year in the future (365 days).
+ time_t notBefore, notAfter;
+ ASSERT_TRUE(parseAsn1Time(X509_get0_notAfter(cert.get()), ¬After));
+ ASSERT_TRUE(parseAsn1Time(X509_get0_notBefore(cert.get()), ¬Before));
+
+ // Allow for 10 seconds drift to account for the time drift between Secure HW
+ // and this environment plus the difference between when the certificate was
+ // created and until now
+ //
+ uint64_t now = time(nullptr);
+ int64_t diffSecs = now - notBefore;
+ int64_t allowDriftSecs = 10;
+ EXPECT_LE(-allowDriftSecs, diffSecs);
+ EXPECT_GE(allowDriftSecs, diffSecs);
+ constexpr uint64_t kSecsInOneYear = 365 * 24 * 60 * 60;
+ EXPECT_EQ(notBefore + kSecsInOneYear, notAfter);
+}
+
vector<RequestNamespace> buildRequestNamespaces(const vector<TestEntryData> entries) {
vector<RequestNamespace> ret;
RequestNamespace curNs;
diff --git a/identity/aidl/vts/VtsIdentityTestUtils.h b/identity/aidl/vts/VtsIdentityTestUtils.h
index 673b736..85c24f8 100644
--- a/identity/aidl/vts/VtsIdentityTestUtils.h
+++ b/identity/aidl/vts/VtsIdentityTestUtils.h
@@ -34,8 +34,8 @@
struct AttestationData {
AttestationData(sp<IWritableIdentityCredential>& writableCredential, string challenge,
- vector<uint8_t> applicationId)
- : attestationApplicationId(applicationId) {
+ vector<uint8_t> attestationAppId)
+ : attestationApplicationId(attestationAppId) {
// ASSERT_NE(writableCredential, nullptr);
if (!challenge.empty()) {
@@ -94,7 +94,7 @@
};
bool setupWritableCredential(sp<IWritableIdentityCredential>& writableCredential,
- sp<IIdentityCredentialStore>& credentialStore);
+ sp<IIdentityCredentialStore>& credentialStore, bool testCredential);
optional<vector<uint8_t>> generateReaderCertificate(string serialDecimal);
@@ -111,13 +111,17 @@
void setImageData(vector<uint8_t>& image);
-bool validateAttestationCertificate(const vector<Certificate>& inputCertificates,
+void validateAttestationCertificate(const vector<Certificate>& credentialKeyCertChain,
const vector<uint8_t>& expectedChallenge,
- const vector<uint8_t>& expectedAppId,
- const HardwareInformation& hwInfo);
+ const vector<uint8_t>& expectedAppId, bool isTestCredential);
vector<RequestNamespace> buildRequestNamespaces(const vector<TestEntryData> entries);
+// Verifies that the X.509 certificate for a just created authentication key
+// is valid.
+//
+void verifyAuthKeyCertificate(const vector<uint8_t>& authKeyCertChain);
+
} // namespace android::hardware::identity::test_utils
#endif // VTS_IDENTITY_TEST_UTILS_H
diff --git a/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h b/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h
index f7ec7c5..3aa5bb6 100644
--- a/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h
+++ b/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h
@@ -35,6 +35,9 @@
using ::std::vector;
using ::std::pair;
+// The semantic tag for a bstr which includes Encoded CBOR (RFC 7049, section 2.4)
+const int kSemanticTagEncodedCbor = 24;
+
// ---------------------------------------------------------------------------
// Miscellaneous utilities.
// ---------------------------------------------------------------------------
@@ -108,45 +111,47 @@
// ---------------------------------------------------------------------------
// EC crypto functionality / abstraction (only supports P-256).
// ---------------------------------------------------------------------------
+
// Creates an 256-bit EC key using the NID_X9_62_prime256v1 curve, returns the
-// PKCS#8 encoded key-pair. Also generates an attestation
-// certificate using the |challenge| and |applicationId|, and returns the generated
-// certificate in X.509 certificate chain format.
+// DER encoded private key. Also generates an attestation using the |challenge|
+// and |applicationId|, and returns the generated certificate chain.
//
-// The attestation time fields used will be the current time, and expires in one year.
+// The notBeffore field will be the current time and the notAfter will be the same
+// same time as the batch certificate.
//
// The first parameter of the return value is the keyPair generated, second return in
// the pair is the attestation certificate generated.
-optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> createEcKeyPairAndAttestation(
- const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId);
-
-// Like createEcKeyPairAndAttestation() but allows you to choose the public key.
//
+optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> createEcKeyPairAndAttestation(
+ const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId,
+ bool isTestCredential);
+
+// (TODO: remove when no longer used by 3rd party.)
optional<vector<vector<uint8_t>>> createAttestationForEcPublicKey(
const vector<uint8_t>& publicKey, const vector<uint8_t>& challenge,
const vector<uint8_t>& applicationId);
// Creates an 256-bit EC key using the NID_X9_62_prime256v1 curve, returns the
-// PKCS#8 encoded key-pair.
+// private key in DER format (as specified in RFC 5915).
//
optional<vector<uint8_t>> createEcKeyPair();
-// For an EC key |keyPair| encoded in PKCS#8 format, extracts the public key in
+// For an EC key |keyPair| encoded in DER format, extracts the public key in
// uncompressed point form.
//
optional<vector<uint8_t>> ecKeyPairGetPublicKey(const vector<uint8_t>& keyPair);
-// For an EC key |keyPair| encoded in PKCS#8 format, extracts the private key as
+// For an EC key |keyPair| encoded in DER format, extracts the private key as
// an EC uncompressed key.
//
optional<vector<uint8_t>> ecKeyPairGetPrivateKey(const vector<uint8_t>& keyPair);
-// Creates a PKCS#8 encoded key-pair from a private key (which must be uncompressed,
-// e.g. 32 bytes). The public key is derived from the given private key..
+// Creates a DER encoded representation from a private key (which must be uncompressed,
+// e.g. 32 bytes).
//
optional<vector<uint8_t>> ecPrivateKeyToKeyPair(const vector<uint8_t>& privateKey);
-// For an EC key |keyPair| encoded in PKCS#8 format, creates a PKCS#12 structure
+// For an EC key |keyPair| encoded in DER format, creates a PKCS#12 structure
// with the key-pair (not using a password to encrypt the data). The public key
// in the created structure is included as a certificate, using the given fields
// |serialDecimal|, |issuer|, |subject|, |validityNotBefore|, and
@@ -209,6 +214,13 @@
//
optional<pair<size_t, size_t>> certificateFindSignature(const vector<uint8_t>& x509Certificate);
+// Extracts notBefore and notAfter from the top-most certificate in |certificateChain
+// (which should be a concatenated chain of DER-encoded X.509 certificates).
+//
+// Returns notBefore and notAfter in that order.
+//
+optional<pair<time_t, time_t>> certificateGetValidity(const vector<uint8_t>& x509Certificate);
+
// Generates a X.509 certificate for |publicKey| (which must be in the format
// returned by ecKeyPairGetPublicKey()).
//
@@ -351,6 +363,15 @@
// Utility functions specific to IdentityCredential.
// ---------------------------------------------------------------------------
+optional<vector<uint8_t>> calcMac(const vector<uint8_t>& sessionTranscriptEncoded,
+ const string& docType,
+ const vector<uint8_t>& deviceNameSpacesEncoded,
+ const vector<uint8_t>& eMacKey);
+
+optional<vector<uint8_t>> calcEMacKey(const vector<uint8_t>& privateKey,
+ const vector<uint8_t>& publicKey,
+ const vector<uint8_t>& sessionTranscriptBytes);
+
// Returns the testing AES-128 key where all bits are set to 0.
const vector<uint8_t>& getTestHardwareBoundKey();
diff --git a/identity/support/src/IdentityCredentialSupport.cpp b/identity/support/src/IdentityCredentialSupport.cpp
index 8e099e7..08559c6 100644
--- a/identity/support/src/IdentityCredentialSupport.cpp
+++ b/identity/support/src/IdentityCredentialSupport.cpp
@@ -44,6 +44,7 @@
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
+#include <charconv>
#include <cppbor.h>
#include <cppbor_parse.h>
@@ -870,16 +871,97 @@
return hmac;
}
+int parseDigits(const char** s, int numDigits) {
+ int result;
+ auto [_, ec] = std::from_chars(*s, *s + numDigits, result);
+ if (ec != std::errc()) {
+ LOG(ERROR) << "Error parsing " << numDigits << " digits "
+ << " from " << s;
+ return 0;
+ }
+ *s += numDigits;
+ return result;
+}
+
+bool parseAsn1Time(const ASN1_TIME* asn1Time, time_t* outTime) {
+ struct tm tm;
+
+ memset(&tm, '\0', sizeof(tm));
+ const char* timeStr = (const char*)asn1Time->data;
+ const char* s = timeStr;
+ if (asn1Time->type == V_ASN1_UTCTIME) {
+ tm.tm_year = parseDigits(&s, 2);
+ if (tm.tm_year < 70) {
+ tm.tm_year += 100;
+ }
+ } else if (asn1Time->type == V_ASN1_GENERALIZEDTIME) {
+ tm.tm_year = parseDigits(&s, 4) - 1900;
+ tm.tm_year -= 1900;
+ } else {
+ LOG(ERROR) << "Unsupported ASN1_TIME type " << asn1Time->type;
+ return false;
+ }
+ tm.tm_mon = parseDigits(&s, 2) - 1;
+ tm.tm_mday = parseDigits(&s, 2);
+ tm.tm_hour = parseDigits(&s, 2);
+ tm.tm_min = parseDigits(&s, 2);
+ tm.tm_sec = parseDigits(&s, 2);
+ // This may need to be updated if someone create certificates using +/- instead of Z.
+ //
+ if (*s != 'Z') {
+ LOG(ERROR) << "Expected Z in string '" << timeStr << "' at offset " << (s - timeStr);
+ return false;
+ }
+
+ time_t t = timegm(&tm);
+ if (t == -1) {
+ LOG(ERROR) << "Error converting broken-down time to time_t";
+ return false;
+ }
+ *outTime = t;
+ return true;
+}
+
// Generates the attestation certificate with the parameters passed in. Note
// that the passed in |activeTimeMilliSeconds| |expireTimeMilliSeconds| are in
// milli seconds since epoch. We are setting them to milliseconds due to
// requirement in AuthorizationSet KM_DATE fields. The certificate created is
// actually in seconds.
-optional<vector<vector<uint8_t>>> createAttestation(const EVP_PKEY* key,
- const vector<uint8_t>& applicationId,
- const vector<uint8_t>& challenge,
- uint64_t activeTimeMilliSeconds,
- uint64_t expireTimeMilliSeconds) {
+//
+// If 0 is passed for expiration time, the expiration time from batch
+// certificate will be used.
+//
+optional<vector<vector<uint8_t>>> createAttestation(
+ const EVP_PKEY* key, const vector<uint8_t>& applicationId, const vector<uint8_t>& challenge,
+ uint64_t activeTimeMilliSeconds, uint64_t expireTimeMilliSeconds, bool isTestCredential) {
+ const keymaster_cert_chain_t* attestation_chain =
+ ::keymaster::getAttestationChain(KM_ALGORITHM_EC, nullptr);
+ if (attestation_chain == nullptr) {
+ LOG(ERROR) << "Error getting attestation chain";
+ return {};
+ }
+ if (expireTimeMilliSeconds == 0) {
+ if (attestation_chain->entry_count < 1) {
+ LOG(ERROR) << "Expected at least one entry in attestation chain";
+ return {};
+ }
+ keymaster_blob_t* bcBlob = &(attestation_chain->entries[0]);
+ const uint8_t* bcData = bcBlob->data;
+ auto bc = X509_Ptr(d2i_X509(nullptr, &bcData, bcBlob->data_length));
+ time_t bcNotAfter;
+ if (!parseAsn1Time(X509_get0_notAfter(bc.get()), &bcNotAfter)) {
+ LOG(ERROR) << "Error getting notAfter from batch certificate";
+ return {};
+ }
+ expireTimeMilliSeconds = bcNotAfter * 1000;
+ }
+ const keymaster_key_blob_t* attestation_signing_key =
+ ::keymaster::getAttestationKey(KM_ALGORITHM_EC, nullptr);
+ if (attestation_signing_key == nullptr) {
+ LOG(ERROR) << "Error getting attestation key";
+ return {};
+ }
+
::keymaster::AuthorizationSet auth_set(
::keymaster::AuthorizationSetBuilder()
.Authorization(::keymaster::TAG_ATTESTATION_CHALLENGE, challenge.data(),
@@ -901,7 +983,7 @@
::keymaster::AuthorizationSet swEnforced(::keymaster::AuthorizationSetBuilder().Authorization(
::keymaster::TAG_CREATION_DATETIME, activeTimeMilliSeconds));
- ::keymaster::AuthorizationSet hwEnforced(
+ ::keymaster::AuthorizationSetBuilder hwEnforcedBuilder =
::keymaster::AuthorizationSetBuilder()
.Authorization(::keymaster::TAG_PURPOSE, KM_PURPOSE_SIGN)
.Authorization(::keymaster::TAG_KEY_SIZE, 256)
@@ -909,34 +991,29 @@
.Authorization(::keymaster::TAG_NO_AUTH_REQUIRED)
.Authorization(::keymaster::TAG_DIGEST, KM_DIGEST_SHA_2_256)
.Authorization(::keymaster::TAG_EC_CURVE, KM_EC_CURVE_P_256)
- .Authorization(::keymaster::TAG_IDENTITY_CREDENTIAL_KEY));
+ .Authorization(::keymaster::TAG_OS_VERSION, 42)
+ .Authorization(::keymaster::TAG_OS_PATCHLEVEL, 43);
- const keymaster_cert_chain_t* attestation_chain =
- ::keymaster::getAttestationChain(KM_ALGORITHM_EC, nullptr);
-
- if (attestation_chain == nullptr) {
- LOG(ERROR) << "Error getting attestation chain";
- return {};
+ // Only include TAG_IDENTITY_CREDENTIAL_KEY if it's not a test credential
+ if (!isTestCredential) {
+ hwEnforcedBuilder.Authorization(::keymaster::TAG_IDENTITY_CREDENTIAL_KEY);
}
-
- const keymaster_key_blob_t* attestation_signing_key =
- ::keymaster::getAttestationKey(KM_ALGORITHM_EC, nullptr);
- if (attestation_signing_key == nullptr) {
- LOG(ERROR) << "Error getting attestation key";
- return {};
- }
+ ::keymaster::AuthorizationSet hwEnforced(hwEnforcedBuilder);
keymaster_error_t error;
::keymaster::CertChainPtr cert_chain_out;
- ::keymaster::PureSoftKeymasterContext context;
- // set identity version to 10 per hal requirements specified in IWriteableCredential.hal
- // For now, the identity version in the attestation is set in the keymaster
- // version field in the portable keymaster lib, which is a bit misleading.
- uint identity_version = 10;
+ // Pretend to be implemented in a trusted environment just so we can pass
+ // the VTS tests. Of course, this is a pretend-only game since hopefully no
+ // relying party is ever going to trust our batch key and those keys above
+ // it.
+ //
+ ::keymaster::PureSoftKeymasterContext context(KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT);
+
error = generate_attestation_from_EVP(key, swEnforced, hwEnforced, auth_set, context,
- identity_version, *attestation_chain,
- *attestation_signing_key, &cert_chain_out);
+ ::keymaster::kCurrentKeymasterVersion, *attestation_chain,
+ *attestation_signing_key,
+ "Android Identity Credential Key", &cert_chain_out);
if (KM_ERROR_OK != error || !cert_chain_out) {
LOG(ERROR) << "Error generate attestation from EVP key" << error;
@@ -957,7 +1034,8 @@
}
optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> createEcKeyPairAndAttestation(
- const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId) {
+ const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId,
+ bool isTestCredential) {
auto ec_key = ::keymaster::EC_KEY_Ptr(EC_KEY_new());
auto pkey = ::keymaster::EVP_PKEY_Ptr(EVP_PKEY_new());
auto group = ::keymaster::EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
@@ -978,12 +1056,11 @@
return {};
}
- uint64_t now = time(nullptr);
- uint64_t secondsInOneYear = 365 * 24 * 60 * 60;
- uint64_t expireTimeMs = (now + secondsInOneYear) * 1000;
+ uint64_t nowMs = time(nullptr) * 1000;
+ uint64_t expireTimeMs = 0; // Set to same as batch certificate
- optional<vector<vector<uint8_t>>> attestationCert =
- createAttestation(pkey.get(), applicationId, challenge, now * 1000, expireTimeMs);
+ optional<vector<vector<uint8_t>>> attestationCert = createAttestation(
+ pkey.get(), applicationId, challenge, nowMs, expireTimeMs, isTestCredential);
if (!attestationCert) {
LOG(ERROR) << "Error create attestation from key and challenge";
return {};
@@ -1031,14 +1108,12 @@
return {};
}
- uint64_t now = (std::chrono::duration_cast<std::chrono::nanoseconds>(
- std::chrono::system_clock::now().time_since_epoch()).
- count()/ 1000000000);
- uint64_t secondsInOneYear = 365 * 24 * 60 * 60;
- uint64_t expireTimeMs = (now + secondsInOneYear) * 1000;
+ uint64_t nowMs = time(nullptr) * 1000;
+ uint64_t expireTimeMs = 0; // Set to same as batch certificate
optional<vector<vector<uint8_t>>> attestationCert =
- createAttestation(pkey.get(), applicationId, challenge, now * 1000, expireTimeMs);
+ createAttestation(pkey.get(), applicationId, challenge, nowMs, expireTimeMs,
+ false /* isTestCredential */);
if (!attestationCert) {
LOG(ERROR) << "Error create attestation from key and challenge";
return {};
@@ -1652,6 +1727,32 @@
return std::make_pair(tbsCertificateOffset, tbsCertificateSize);
}
+optional<pair<time_t, time_t>> certificateGetValidity(const vector<uint8_t>& x509Certificate) {
+ vector<X509_Ptr> certs;
+ if (!parseX509Certificates(x509Certificate, certs)) {
+ LOG(ERROR) << "Error parsing certificates";
+ return {};
+ }
+ if (certs.size() < 1) {
+ LOG(ERROR) << "No certificates in chain";
+ return {};
+ }
+
+ time_t notBefore;
+ time_t notAfter;
+ if (!parseAsn1Time(X509_get0_notBefore(certs[0].get()), ¬Before)) {
+ LOG(ERROR) << "Error parsing notBefore";
+ return {};
+ }
+
+ if (!parseAsn1Time(X509_get0_notAfter(certs[0].get()), ¬After)) {
+ LOG(ERROR) << "Error parsing notAfter";
+ return {};
+ }
+
+ return std::make_pair(notBefore, notAfter);
+}
+
optional<pair<size_t, size_t>> certificateFindSignature(const vector<uint8_t>& x509Certificate) {
vector<X509_Ptr> certs;
if (!parseX509Certificates(x509Certificate, certs)) {
@@ -2224,6 +2325,49 @@
// Utility functions specific to IdentityCredential.
// ---------------------------------------------------------------------------
+optional<vector<uint8_t>> calcEMacKey(const vector<uint8_t>& privateKey,
+ const vector<uint8_t>& publicKey,
+ const vector<uint8_t>& sessionTranscriptBytes) {
+ optional<vector<uint8_t>> sharedSecret = support::ecdh(publicKey, privateKey);
+ if (!sharedSecret) {
+ LOG(ERROR) << "Error performing ECDH";
+ return {};
+ }
+ vector<uint8_t> salt = support::sha256(sessionTranscriptBytes);
+ vector<uint8_t> info = {'E', 'M', 'a', 'c', 'K', 'e', 'y'};
+ optional<vector<uint8_t>> derivedKey = support::hkdf(sharedSecret.value(), salt, info, 32);
+ if (!derivedKey) {
+ LOG(ERROR) << "Error performing HKDF";
+ return {};
+ }
+ return derivedKey.value();
+}
+
+optional<vector<uint8_t>> calcMac(const vector<uint8_t>& sessionTranscriptEncoded,
+ const string& docType,
+ const vector<uint8_t>& deviceNameSpacesEncoded,
+ const vector<uint8_t>& eMacKey) {
+ auto [sessionTranscriptItem, _, errMsg] = cppbor::parse(sessionTranscriptEncoded);
+ if (sessionTranscriptItem == nullptr) {
+ LOG(ERROR) << "Error parsing sessionTranscriptEncoded: " << errMsg;
+ return {};
+ }
+ // The data that is MACed is ["DeviceAuthentication", sessionTranscript, docType,
+ // deviceNameSpacesBytes] so build up that structure
+ cppbor::Array deviceAuthentication =
+ cppbor::Array()
+ .add("DeviceAuthentication")
+ .add(std::move(sessionTranscriptItem))
+ .add(docType)
+ .add(cppbor::Semantic(kSemanticTagEncodedCbor, deviceNameSpacesEncoded));
+ vector<uint8_t> deviceAuthenticationBytes =
+ cppbor::Semantic(kSemanticTagEncodedCbor, deviceAuthentication.encode()).encode();
+ optional<vector<uint8_t>> calculatedMac =
+ support::coseMac0(eMacKey, {}, // payload
+ deviceAuthenticationBytes); // detached content
+ return calculatedMac;
+}
+
vector<vector<uint8_t>> chunkVector(const vector<uint8_t>& content, size_t maxChunkSize) {
vector<vector<uint8_t>> ret;
diff --git a/identity/support/tests/IdentityCredentialSupportTest.cpp b/identity/support/tests/IdentityCredentialSupportTest.cpp
index c356549..266f263 100644
--- a/identity/support/tests/IdentityCredentialSupportTest.cpp
+++ b/identity/support/tests/IdentityCredentialSupportTest.cpp
@@ -436,6 +436,300 @@
support::cborPrettyPrint(mac.value()));
}
+// Generates a private key in DER format for a small value of 'd'.
+//
+// Used for test vectors.
+//
+vector<uint8_t> p256PrivateKeyFromD(uint8_t d) {
+ vector<uint8_t> privateUncompressed;
+ privateUncompressed.resize(32);
+ privateUncompressed[31] = d;
+ optional<vector<uint8_t>> privateKey = support::ecPrivateKeyToKeyPair(privateUncompressed);
+ return privateKey.value();
+}
+
+std::pair<vector<uint8_t>, vector<uint8_t>> p256PrivateKeyGetXandY(
+ const vector<uint8_t> privateKey) {
+ optional<vector<uint8_t>> publicUncompressed = support::ecKeyPairGetPublicKey(privateKey);
+ vector<uint8_t> x = vector<uint8_t>(publicUncompressed.value().begin() + 1,
+ publicUncompressed.value().begin() + 33);
+ vector<uint8_t> y = vector<uint8_t>(publicUncompressed.value().begin() + 33,
+ publicUncompressed.value().begin() + 65);
+ return std::make_pair(x, y);
+}
+
+const cppbor::Item* findValueForTstr(const cppbor::Map* map, const string& keyValue) {
+ // TODO: Need cast until libcppbor's Map::get() is marked as const
+ auto [item, found] = ((cppbor::Map*)map)->get(keyValue);
+ if (!found) {
+ return nullptr;
+ }
+ return item.get();
+}
+
+const cppbor::Array* findArrayValueForTstr(const cppbor::Map* map, const string& keyValue) {
+ const cppbor::Item* item = findValueForTstr(map, keyValue);
+ if (item == nullptr) {
+ return nullptr;
+ }
+ return item->asArray();
+}
+
+const cppbor::Map* findMapValueForTstr(const cppbor::Map* map, const string& keyValue) {
+ const cppbor::Item* item = findValueForTstr(map, keyValue);
+ if (item == nullptr) {
+ return nullptr;
+ }
+ return item->asMap();
+}
+
+const cppbor::Semantic* findSemanticValueForTstr(const cppbor::Map* map, const string& keyValue) {
+ const cppbor::Item* item = findValueForTstr(map, keyValue);
+ if (item == nullptr) {
+ return nullptr;
+ }
+ return item->asSemantic();
+}
+
+const std::string findStringValueForTstr(const cppbor::Map* map, const string& keyValue) {
+ const cppbor::Item* item = findValueForTstr(map, keyValue);
+ if (item == nullptr) {
+ return nullptr;
+ }
+ const cppbor::Tstr* tstr = item->asTstr();
+ if (tstr == nullptr) {
+ return "";
+ }
+ return tstr->value();
+}
+
+TEST(IdentityCredentialSupport, testVectors_18013_5) {
+ // This is a test against known vectors for ISO 18013-5.
+ //
+ // The objective of this test is to verify that support::calcEMacKey() and
+ // support::calcMac() agree with the given test vectors.
+ //
+
+ // We're given static device key:
+ //
+ // x: 28412803729898893058558238221310261427084375743576167377786533380249859400145
+ // y: 65403602826180996396520286939226973026599920614829401631985882360676038096704
+ // d: 11
+ //
+ vector<uint8_t> deviceKey = p256PrivateKeyFromD(11);
+ auto [deviceKeyX, deviceKeyY] = p256PrivateKeyGetXandY(deviceKey);
+ EXPECT_EQ(support::encodeHex(deviceKeyX),
+ "3ed113b7883b4c590638379db0c21cda16742ed0255048bf433391d374bc21d1");
+ EXPECT_EQ(support::encodeHex(deviceKeyY),
+ "9099209accc4c8a224c843afa4f4c68a090d04da5e9889dae2f8eefce82a3740");
+
+ // We're given Ephemeral reader key:
+ //
+ // x: 59535862115950685744176693329402396749019581632805653266809849538337418304154
+ // y: 53776829996815113213100700404832701936765102413212294632483274374518863708344
+ // d: 20
+ //
+ vector<uint8_t> ephemeralReaderKey = p256PrivateKeyFromD(20);
+ auto [ephemeralReaderKeyX, ephemeralReaderKeyY] = p256PrivateKeyGetXandY(ephemeralReaderKey);
+ EXPECT_EQ(support::encodeHex(ephemeralReaderKeyX),
+ "83a01a9378395bab9bcd6a0ad03cc56d56e6b19250465a94a234dc4c6b28da9a");
+ EXPECT_EQ(support::encodeHex(ephemeralReaderKeyY),
+ "76e49b6de2f73234ae6a5eb9d612b75c9f2202bb6923f54ff8240aaa86f640b8");
+ vector<uint8_t> ephemeralReaderKeyPublic =
+ support::ecKeyPairGetPublicKey(ephemeralReaderKey).value();
+
+ // We're given SessionEstablishment.
+ //
+ // SessionEstablishment = {
+ // "eReaderKey" : EReaderKeyBytes,
+ // "data" : bstr ; Encrypted mdoc request
+ // }
+ //
+ // Fish out EReaderKey from this.
+ //
+ // Note that the test vector below is incorrect insofar that it uses
+ // "eReaderKeyBytes" instead of just "eReaderKey". This will be corrected in
+ // the future.
+ //
+ optional<vector<uint8_t>> sessionEstablishmentEncoded = support::decodeHex(
+ "a26f655265616465724b65794279746573d818584ba40102200121582083a01a9378395bab9bcd6a0ad03c"
+ "c56d56e6b19250465a94a234dc4c6b28da9a22582076e49b6de2f73234ae6a5eb9d612b75c9f2202bb6923"
+ "f54ff8240aaa86f640b864646174615902d945b31040c57491acb6d46a71f6c1f67a0b837df1bda9089fd0"
+ "3d0b1fdac3eeb2874a4ef6f90c97d03397186ba00a91102faae7e992e15f761d5662c3c37e3c6c2cfd2ebc"
+ "0bf59dbb8795e377bd7dd353230a41ba2d82294b45871a39b42ca531f26b52f46e356fbaf5075c8fd5b8b0"
+ "8a0df4a1d2e1bdd2e5d69169c1efbb51e393e608d833d325bebfbccb2e15ec08f94b264582fa7b93f7cebc"
+ "aa69f4f0cac2744d4fe35b04df26b2ae69273eed33024949080c1c95a6ef046beede959e9494297dd770af"
+ "4ac6fdd56783aa012555c213dc05cf0f41d1c95119720fcfe1621027f80e2ddd56ea3c1fc596f7b2579333"
+ "5a887ec788092b4a69d23b6219e27d0249b50b3fdcb95b5227007689362e0416b3bae3dae7cb56b4394666"
+ "4e3a3f60dce8d0b678fcd754bebf87bd2b0278dd782d952488a46f2874e34c2dd97bb74084a62b850e9719"
+ "252cd1dca7dbf1858193f6cf093cb3735312bbe1138cf29d8f350e285923f8ef07065299926720b42264e8"
+ "fd5d4b133e72f47c4e999ea689c353f8b41e50a59838e1a0d09eca4a557f77a9c389a0591ad1639119ce86"
+ "edc3320130480ee5101effae6066e8c85aac9ead2ae83e49c1e508aab02f753decbb522ea2200d62fd5d26"
+ "094bd35100bffaa1cdc6af9f7e9cfe7b63da6b5671cd5ac2cf5da450c72addc64cde441f3b7f7fdaf930ad"
+ "1e13388e8a7308d8ca4607e59e082db431a232e7e12cb692baeb4b2127e110ff24cea322ffdbc2e4d9c4c6"
+ "bed27753137d07897c8613627a799a560cf1a2d1edb3de029442862940a5ed7785eea8b6ace93aa6af0792"
+ "fd82877f62d07b757d0179ecbb7347004ecc9c0690d41f75f188cb17ffd2cec2ad8c9675466bb33b737a2a"
+ "e7592b2dcb8132aced2e572266f3f5413a5f9d6d4339a1e4662622af2e7e157a4ea3bfd5c4247e2ec91d8c"
+ "5c3c17427d5edfae673d0e0f782a8d40fa805fd8bc82ae3cb21a65cdad863e02309f6b01d1753fa884b778"
+ "f6e019a2004d8964deeb11f1fd478fcb");
+ ASSERT_TRUE(sessionEstablishmentEncoded);
+ auto [sessionEstablishmentItem, _se, _se2] = cppbor::parse(sessionEstablishmentEncoded.value());
+ const cppbor::Map* sessionEstablishment = sessionEstablishmentItem->asMap();
+ ASSERT_NE(sessionEstablishment, nullptr);
+ const cppbor::Semantic* eReaderKeyBytes =
+ findSemanticValueForTstr(sessionEstablishment, "eReaderKeyBytes");
+ ASSERT_NE(eReaderKeyBytes, nullptr);
+ ASSERT_EQ(eReaderKeyBytes->value(), 24);
+ const cppbor::Bstr* eReaderKeyBstr = eReaderKeyBytes->child()->asBstr();
+ ASSERT_NE(eReaderKeyBstr, nullptr);
+ vector<uint8_t> eReaderKeyEncoded = eReaderKeyBstr->value();
+ // TODO: verify this agrees with ephemeralReaderKeyX and ephemeralReaderKeyY
+
+ // We're given DeviceEngagement.
+ //
+ vector<uint8_t> deviceEngagementEncoded =
+ support::decodeHex(
+ "a20063312e30018201d818584ba401022001215820cef66d6b2a3a993e591214d1ea223fb545ca"
+ "6c471c48306e4c36069404c5723f225820878662a229aaae906e123cdd9d3b4c10590ded29fe75"
+ "1eeeca34bbaa44af0773")
+ .value();
+
+ // Now calculate SessionTranscriptBytes. It is defined as
+ //
+ // SessionTranscript = [
+ // DeviceEngagementBytes,
+ // EReaderKeyBytes,
+ // Handover
+ // ]
+ //
+ // SessionTranscriptBytes = #6.24(bstr .cbor SessionTranscript)
+ //
+ cppbor::Array sessionTranscript;
+ sessionTranscript.add(cppbor::Semantic(24, deviceEngagementEncoded));
+ sessionTranscript.add(cppbor::Semantic(24, eReaderKeyEncoded));
+ sessionTranscript.add(cppbor::Null());
+ vector<uint8_t> sessionTranscriptEncoded = sessionTranscript.encode();
+ vector<uint8_t> sessionTranscriptBytes =
+ cppbor::Semantic(24, sessionTranscriptEncoded).encode();
+
+ // The expected EMacKey is 4c1ebb8aacc633465390fa44edfdb49cb57f2e079aaa771d812584699c0b97e2
+ //
+ // Verify that support::calcEMacKey() gets the same result.
+ //
+ optional<vector<uint8_t>> eMacKey =
+ support::calcEMacKey(support::ecKeyPairGetPrivateKey(deviceKey).value(), // private key
+ ephemeralReaderKeyPublic, // public key
+ sessionTranscriptBytes); // sessionTranscriptBytes
+ ASSERT_TRUE(eMacKey);
+ ASSERT_EQ(support::encodeHex(eMacKey.value()),
+ "4c1ebb8aacc633465390fa44edfdb49cb57f2e079aaa771d812584699c0b97e2");
+
+ // Also do it the other way around
+ //
+ optional<vector<uint8_t>> eMacKey2 = support::calcEMacKey(
+ support::ecKeyPairGetPrivateKey(ephemeralReaderKey).value(), // private key
+ support::ecKeyPairGetPublicKey(deviceKey).value(), // public key
+ sessionTranscriptBytes); // sessionTranscriptBytes
+ ASSERT_TRUE(eMacKey2);
+ ASSERT_EQ(support::encodeHex(eMacKey2.value()),
+ "4c1ebb8aacc633465390fa44edfdb49cb57f2e079aaa771d812584699c0b97e2");
+
+ // We're given DeviceResponse
+ //
+ vector<uint8_t> deviceResponseEncoded =
+ support::decodeHex(
+ "a36776657273696f6e63312e3069646f63756d656e747381a367646f6354797065756f72672e69"
+ "736f2e31383031332e352e312e6d444c6c6973737565725369676e6564a26a6e616d6553706163"
+ "6573a2716f72672e69736f2e31383031332e352e3181d8185863a4686469676573744944016672"
+ "616e646f6d58208798645b20ea200e19ffabac92624bee6aec63aceedecfb1b80077d22bfc20e9"
+ "71656c656d656e744964656e7469666965726b66616d696c795f6e616d656c656c656d656e7456"
+ "616c756563446f656b636f6d2e6578616d706c6581d8185864a468646967657374494401667261"
+ "6e646f6d5820218ecf13521b53f4b96abaebe56417afec0e4c91fc8fb26086cd1e5cdc1a94ff71"
+ "656c656d656e744964656e7469666965726f616e6f746865725f656c656d656e746c656c656d65"
+ "6e7456616c75650a6a697373756572417574688443a10126a118215901d2308201ce30820174a0"
+ "0302010202141f7d44f4f107c5ee3f566049cf5d72de294b0d23300a06082a8648ce3d04030230"
+ "233114301206035504030c0b75746f7069612069616361310b3009060355040613025553301e17"
+ "0d3230313030313030303030305a170d3231313030313030303030305a30213112301006035504"
+ "030c0975746f706961206473310b30090603550406130255533059301306072a8648ce3d020106"
+ "082a8648ce3d03010703420004301d9e502dc7e05da85da026a7ae9aa0fac9db7d52a95b3e3e3f"
+ "9aa0a1b45b8b6551b6f6b3061223e0d23c026b017d72298d9ae46887ca61d58db6aea17ee267a3"
+ "8187308184301e0603551d120417301581136578616d706c65406578616d706c652e636f6d301c"
+ "0603551d1f041530133011a00fa00d820b6578616d706c652e636f6d301d0603551d0e04160414"
+ "7bef4db59a1ffb07592bfc57f4743b8a73aea792300e0603551d0f0101ff040403020780301506"
+ "03551d250101ff040b3009060728818c5d050102300a06082a8648ce3d04030203480030450220"
+ "21d52fb1fbda80e5bfda1e8dfb1bc7bf0acb7261d5c9ff54425af76eb21571c602210082bf301f"
+ "89e0a2cb9ca9c9050352de80b47956764f7a3e07bf6a8cd87528a3b55901d2d8185901cda66776"
+ "657273696f6e63312e306f646967657374416c676f726974686d675348412d3235366c76616c75"
+ "6544696765737473a2716f72672e69736f2e31383031332e352e31a20058203b22af1126771f02"
+ "f0ea0d546d4ee3c5b51637381154f5211b79daf5f9facaa8015820f2cba0ce3cde5df901a3da75"
+ "13a4d7f7225fdfe5a306544529bf3dbcce655ca06b636f6d2e6578616d706c65a200582072636d"
+ "ddc282424a63499f4b3927aaa3b74da7b9c0134178bf735e949e4a761e01582006322d3cbe6603"
+ "876bdacc5b6679b51b0fc53d029c244fd5ea719d9028459c916d6465766963654b6579496e666f"
+ "a1696465766963654b6579a4010220012158203ed113b7883b4c590638379db0c21cda16742ed0"
+ "255048bf433391d374bc21d12258209099209accc4c8a224c843afa4f4c68a090d04da5e9889da"
+ "e2f8eefce82a374067646f6354797065756f72672e69736f2e31383031332e352e312e6d444c6c"
+ "76616c6964697479496e666fa3667369676e6564c074323032302d31302d30315431333a33303a"
+ "30325a6976616c696446726f6dc074323032302d31302d30315431333a33303a30325a6a76616c"
+ "6964556e74696cc074323032312d31302d30315431333a33303a30325a5840273ec1b59817d571"
+ "b5a2c5c0ab0ea213d42acb18547fd7097afcc888a22ecbb863c6461ce0e240880895b4aaa84308"
+ "784571c7be7aa3a2e7e3a2ea1a145ed1966c6465766963655369676e6564a26a6e616d65537061"
+ "636573d81841a06a64657669636541757468a1696465766963654d61638443a10105a0f6582009"
+ "da7c964ac004ec36ec64edd0c1abf50c03433c215c3ddb144768abcdf20a60667374617475730"
+ "0")
+ .value();
+ auto [deviceResponseItem, _, _2] = cppbor::parse(deviceResponseEncoded);
+ const cppbor::Map* deviceResponse = deviceResponseItem->asMap();
+ ASSERT_NE(deviceResponse, nullptr);
+ const cppbor::Array* documents = findArrayValueForTstr(deviceResponse, "documents");
+ ASSERT_NE(documents, nullptr);
+ ASSERT_EQ(documents->size(), 1);
+ const cppbor::Map* document = ((*documents)[0])->asMap();
+ ASSERT_NE(document, nullptr);
+
+ // Get docType
+ string docType = findStringValueForTstr(document, "docType");
+ ASSERT_EQ(docType, "org.iso.18013.5.1.mDL");
+
+ // Drill down...
+ const cppbor::Map* deviceSigned = findMapValueForTstr(document, "deviceSigned");
+ ASSERT_NE(deviceSigned, nullptr);
+
+ // Dig out the encoded form of DeviceNameSpaces
+ //
+ const cppbor::Semantic* deviceNameSpacesBytes =
+ findSemanticValueForTstr(deviceSigned, "nameSpaces");
+ ASSERT_NE(deviceNameSpacesBytes, nullptr);
+ ASSERT_EQ(deviceNameSpacesBytes->value(), 24);
+ const cppbor::Bstr* deviceNameSpacesBstr = deviceNameSpacesBytes->child()->asBstr();
+ ASSERT_NE(deviceNameSpacesBstr, nullptr);
+ vector<uint8_t> deviceNameSpacesEncoded = deviceNameSpacesBstr->value();
+
+ // (For this version of 18013-5, DeviceNameSpaces is always supposed to be empty, check that.)
+ EXPECT_EQ(deviceNameSpacesEncoded, cppbor::Map().encode());
+
+ const cppbor::Map* deviceAuth = findMapValueForTstr(deviceSigned, "deviceAuth");
+ ASSERT_NE(deviceAuth, nullptr);
+ // deviceMac is is the COSE_Mac0.. dig out the encoded form to check that
+ // support::calcMac() gives exactly the same bytes.
+ //
+ const cppbor::Array* deviceMac = findArrayValueForTstr(deviceAuth, "deviceMac");
+ ASSERT_NE(deviceMac, nullptr);
+ vector<uint8_t> deviceMacEncoded = deviceMac->encode();
+
+ // Now we calculate what it should be..
+ optional<vector<uint8_t>> calculatedMac =
+ support::calcMac(sessionTranscriptEncoded, // SessionTranscript
+ docType, // DocType
+ deviceNameSpacesEncoded, // DeviceNamespaces
+ eMacKey.value()); // EMacKey
+ ASSERT_TRUE(calculatedMac);
+
+ // ... and hopefully it's the same!
+ ASSERT_EQ(calculatedMac.value().size(), deviceMacEncoded.size());
+ EXPECT_TRUE(memcmp(calculatedMac.value().data(), deviceMacEncoded.data(),
+ deviceMacEncoded.size()) == 0);
+}
+
} // namespace identity
} // namespace hardware
} // namespace android
diff --git a/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h b/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h
index ff08066..3e29206 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h
@@ -17,6 +17,7 @@
#ifndef SYSTEM_SECURITY_KEYSTORE_KM4_AUTHORIZATION_SET_H_
#define SYSTEM_SECURITY_KEYSTORE_KM4_AUTHORIZATION_SET_H_
+#include <functional>
#include <vector>
#include <keymasterV4_0/keymaster_tags.h>
@@ -165,11 +166,12 @@
*/
bool Contains(Tag tag) const { return find(tag) != -1; }
- template <TagType tag_type, Tag tag, typename ValueT>
- bool Contains(TypedTag<tag_type, tag> ttag, const ValueT& value) const {
+ template <TagType tag_type, Tag tag, typename ValueT, typename Comparator = std::equal_to<>>
+ bool Contains(TypedTag<tag_type, tag> ttag, const ValueT& value,
+ Comparator cmp = Comparator()) const {
for (const auto& param : data_) {
auto entry = authorizationValue(ttag, param);
- if (entry.isOk() && static_cast<ValueT>(entry.value()) == value) return true;
+ if (entry.isOk() && cmp(static_cast<ValueT>(entry.value()), value)) return true;
}
return false;
}
diff --git a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
index bc7f311..befb7d3 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
@@ -73,6 +73,9 @@
static const int32_t KM_TAG_DIGEST_OLD = static_cast<int32_t>(TagType::ENUM) | 5;
static const int32_t KM_TAG_PADDING_OLD = static_cast<int32_t>(TagType::ENUM) | 7;
+static const int32_t KM_TAG_FBE_ICE = static_cast<int32_t>(TagType::BOOL) | 16201;
+static const int32_t KM_TAG_KEY_TYPE = static_cast<int32_t>(TagType::UINT) | 16202;
+
constexpr TagType typeFromTag(Tag tag) {
return static_cast<TagType>(static_cast<uint32_t>(tag) & static_cast<uint32_t>(0xf0000000));
}
diff --git a/keymaster/4.0/vts/functional/VerificationTokenTest.cpp b/keymaster/4.0/vts/functional/VerificationTokenTest.cpp
index bab1439..4f0a7a3 100644
--- a/keymaster/4.0/vts/functional/VerificationTokenTest.cpp
+++ b/keymaster/4.0/vts/functional/VerificationTokenTest.cpp
@@ -111,19 +111,19 @@
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 @@
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()));
diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
index aa2de2a..d669667 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -17,9 +17,12 @@
#define LOG_TAG "keymaster_hidl_hal_test"
#include <cutils/log.h>
-#include <iostream>
#include <signal.h>
+#include <functional>
+#include <iostream>
+#include <string>
+
#include <openssl/evp.h>
#include <openssl/mem.h>
#include <openssl/x509.h>
@@ -32,6 +35,8 @@
#include "KeymasterHidlTest.h"
+using namespace std::string_literals;
+
static bool arm_deleteAllKeys = false;
static bool dump_Attestations = false;
@@ -315,6 +320,12 @@
return property_get("ro.boot.vbmeta.device_state", value, "") != 0;
}
+bool is_gsi() {
+ char property_value[PROPERTY_VALUE_MAX] = {};
+ EXPECT_NE(property_get("ro.product.system.name", property_value, ""), 0);
+ return "mainline"s == property_value;
+}
+
} // namespace
bool verify_attestation_record(const string& challenge, const string& app_id,
@@ -512,9 +523,25 @@
EXPECT_TRUE(auths.Contains(TAG_OS_VERSION, os_version()))
<< "OS version is " << os_version() << " key reported "
<< auths.GetTagValue(TAG_OS_VERSION);
- EXPECT_TRUE(auths.Contains(TAG_OS_PATCHLEVEL, os_patch_level()))
- << "OS patch level is " << os_patch_level() << " key reported "
- << auths.GetTagValue(TAG_OS_PATCHLEVEL);
+
+ if (is_gsi()) {
+ // In general, TAG_OS_PATCHLEVEL should be equal to os_patch_level()
+ // reported from the system.img in use. But it is allowed to boot a
+ // GSI system.img with newer patch level, which means TAG_OS_PATCHLEVEL
+ // might be less than or equal to os_patch_level() in this case.
+ EXPECT_TRUE(auths.Contains(TAG_OS_PATCHLEVEL, // vbmeta.img patch level
+ os_patch_level(), // system.img patch level
+ std::less_equal<>()))
+ << "OS patch level is " << os_patch_level()
+ << ", which is less than key reported " << auths.GetTagValue(TAG_OS_PATCHLEVEL);
+ } else {
+ EXPECT_TRUE(auths.Contains(TAG_OS_PATCHLEVEL, // vbmeta.img patch level
+ os_patch_level(), // system.img patch level
+ std::equal_to<>()))
+ << "OS patch level is " << os_patch_level()
+ << ", which is not equal to key reported "
+ << auths.GetTagValue(TAG_OS_PATCHLEVEL);
+ }
}
void CheckCharacteristics(const HidlBuf& key_blob,
diff --git a/keymaster/4.1/support/attestation_record.cpp b/keymaster/4.1/support/attestation_record.cpp
index 598b6b5..207a7e8 100644
--- a/keymaster/4.1/support/attestation_record.cpp
+++ b/keymaster/4.1/support/attestation_record.cpp
@@ -102,6 +102,7 @@
ASN1_INTEGER* boot_patchlevel;
ASN1_NULL* early_boot_only;
ASN1_NULL* device_unique_attestation;
+ ASN1_NULL* identity_credential_key;
} KM_AUTH_LIST;
ASN1_SEQUENCE(KM_AUTH_LIST) = {
@@ -145,6 +146,8 @@
ASN1_EXP_OPT(KM_AUTH_LIST, early_boot_only, ASN1_NULL, TAG_EARLY_BOOT_ONLY.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, device_unique_attestation, ASN1_NULL,
TAG_DEVICE_UNIQUE_ATTESTATION.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, identity_credential_key, ASN1_NULL,
+ TAG_IDENTITY_CREDENTIAL_KEY.maskedTag()),
} ASN1_SEQUENCE_END(KM_AUTH_LIST);
IMPLEMENT_ASN1_FUNCTIONS(KM_AUTH_LIST);
@@ -285,6 +288,7 @@
copyAuthTag(record->unlocked_device_required, TAG_UNLOCKED_DEVICE_REQUIRED, auth_list);
copyAuthTag(record->early_boot_only, TAG_EARLY_BOOT_ONLY, auth_list);
copyAuthTag(record->device_unique_attestation, TAG_DEVICE_UNIQUE_ATTESTATION, auth_list);
+ copyAuthTag(record->identity_credential_key, TAG_IDENTITY_CREDENTIAL_KEY, auth_list);
return ErrorCode::OK;
}
@@ -327,7 +331,10 @@
p = attest_rec->data;
KM_KEY_DESCRIPTION_Ptr record(d2i_KM_KEY_DESCRIPTION(nullptr, &p, attest_rec->length));
- if (!record.get()) return {ErrorCode::UNKNOWN_ERROR, {}};
+ if (!record.get()) {
+ LOG(ERROR) << "Unable to get key description";
+ return {ErrorCode::UNKNOWN_ERROR, {}};
+ }
AttestationRecord result;
@@ -352,10 +359,12 @@
if (error != ErrorCode::OK) return {error, {}};
KM_ROOT_OF_TRUST* root_of_trust = nullptr;
+ SecurityLevel root_of_trust_security_level = SecurityLevel::TRUSTED_ENVIRONMENT;
if (record->tee_enforced && record->tee_enforced->root_of_trust) {
root_of_trust = record->tee_enforced->root_of_trust;
} else if (record->software_enforced && record->software_enforced->root_of_trust) {
root_of_trust = record->software_enforced->root_of_trust;
+ root_of_trust_security_level = SecurityLevel::SOFTWARE;
} else {
LOG(ERROR) << AT << " Failed root of trust parsing";
return {ErrorCode::INVALID_ARGUMENT, {}};
@@ -373,6 +382,7 @@
rot.verified_boot_state = static_cast<keymaster_verified_boot_t>(
ASN1_ENUMERATED_get(root_of_trust->verified_boot_state));
rot.device_locked = root_of_trust->device_locked;
+ rot.security_level = root_of_trust_security_level;
auto& vb_hash = root_of_trust->verified_boot_hash;
if (!vb_hash) {
diff --git a/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp b/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp
index 495de0f..728a523 100644
--- a/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp
+++ b/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp
@@ -212,9 +212,11 @@
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)));
+ CheckedDeleteKey();
}
TEST_P(DeviceUniqueAttestationTest, Rsa) {
diff --git a/light/2.0/default/Android.bp b/light/2.0/default/Android.bp
index ed48825..32fcaaf 100644
--- a/light/2.0/default/Android.bp
+++ b/light/2.0/default/Android.bp
@@ -41,10 +41,18 @@
"libbase",
"libdl",
"libutils",
+ "libhwbinder",
"libhardware",
"libhidlbase",
"android.hardware.light@2.0",
],
+ arch: {
+ arm: {
+ cflags: [
+ "-DARCH_ARM_32"
+ ],
+ },
+ },
}
cc_binary {
diff --git a/light/2.0/default/service.cpp b/light/2.0/default/service.cpp
index 20f0578..b50a203 100644
--- a/light/2.0/default/service.cpp
+++ b/light/2.0/default/service.cpp
@@ -16,10 +16,14 @@
#include <android/hardware/light/2.0/ILight.h>
#include <hidl/LegacySupport.h>
+#include <hwbinder/ProcessState.h>
using android::hardware::light::V2_0::ILight;
using android::hardware::defaultPassthroughServiceImplementation;
int main() {
+#ifdef ARCH_ARM_32
+ android::hardware::ProcessState::initWithMmapSize((size_t)(32768));
+#endif
return defaultPassthroughServiceImplementation<ILight>();
}
diff --git a/media/omx/1.0/vts/functional/common/Android.bp b/media/omx/1.0/vts/functional/common/Android.bp
index 720ea9f..064aaa5 100644
--- a/media/omx/1.0/vts/functional/common/Android.bp
+++ b/media/omx/1.0/vts/functional/common/Android.bp
@@ -22,28 +22,24 @@
export_header_lib_headers: ["media_plugin_headers"],
export_include_dirs: ["."],
+ shared_libs: [
+ "libui",
+ ],
+
static_libs: [
"libgtest",
"libhidlmemory",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
"android.hardware.media.omx@1.0",
- "android.hardware.graphics.allocator@2.0",
- "android.hardware.graphics.allocator@3.0",
"android.hardware.graphics.common@1.0",
"android.hardware.graphics.common@1.1",
"android.hardware.graphics.common@1.2",
- "android.hardware.graphics.mapper@2.0",
- "android.hardware.graphics.mapper@3.0",
],
export_static_lib_headers: [
- "android.hardware.graphics.allocator@2.0",
- "android.hardware.graphics.allocator@3.0",
"android.hardware.graphics.common@1.0",
"android.hardware.graphics.common@1.1",
"android.hardware.graphics.common@1.2",
- "android.hardware.graphics.mapper@2.0",
- "android.hardware.graphics.mapper@3.0",
],
}
@@ -54,15 +50,10 @@
// Link to these statically as they are not guaranteed to be on the device.
static_libs: [
"VtsHalMediaOmxV1_0CommonUtil",
- "android.hardware.graphics.allocator@2.0",
- "android.hardware.graphics.allocator@3.0",
"android.hardware.graphics.common@1.0",
"android.hardware.graphics.common@1.1",
"android.hardware.graphics.common@1.2",
- "android.hardware.graphics.mapper@2.0",
- "android.hardware.graphics.mapper@3.0",
"android.hardware.graphics.bufferqueue@1.0",
- "android.hardware.graphics.common@1.0",
"android.hardware.media.omx@1.0",
"android.hardware.media@1.0",
"android.hidl.allocator@1.0",
@@ -73,6 +64,7 @@
// TODO(b/64437680): Assume these libs are always available on the device.
shared_libs: [
+ "libui",
"libstagefright_foundation",
"libstagefright_omx_utils",
],
diff --git a/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp b/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
index d9d1157..64f27e8 100644
--- a/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
+++ b/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
@@ -21,12 +21,6 @@
#include <android-base/logging.h>
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <android/hardware/graphics/allocator/3.0/IAllocator.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <android/hardware/graphics/mapper/2.0/types.h>
-#include <android/hardware/graphics/mapper/3.0/IMapper.h>
-#include <android/hardware/graphics/mapper/3.0/types.h>
#include <android/hardware/media/omx/1.0/IOmx.h>
#include <android/hardware/media/omx/1.0/IOmxNode.h>
#include <android/hardware/media/omx/1.0/IOmxObserver.h>
@@ -199,42 +193,6 @@
BufferInfo* buffer, uint32_t nFrameWidth,
uint32_t nFrameHeight, int32_t* nStride,
int format) {
- struct AllocatorV2 : public GrallocV2 {
- sp<IAllocator> mAllocator;
- sp<IMapper> mMapper;
- AllocatorV2(sp<IAllocator>&& allocator, sp<IMapper>&& mapper)
- : mAllocator{std::move(allocator)}, mMapper{std::move(mapper)} {}
- AllocatorV2() = default;
- };
- struct AllocatorV3 : public GrallocV3 {
- sp<IAllocator> mAllocator;
- sp<IMapper> mMapper;
- AllocatorV3(sp<IAllocator>&& allocator, sp<IMapper>&& mapper)
- : mAllocator{std::move(allocator)}, mMapper{std::move(mapper)} {}
- AllocatorV3() = default;
- };
- std::variant<AllocatorV2, AllocatorV3> grallocVar;
-
- sp<android::hardware::graphics::mapper::V2_0::IMapper> mapper2{};
- sp<android::hardware::graphics::mapper::V3_0::IMapper> mapper3{};
- sp<android::hardware::graphics::allocator::V2_0::IAllocator> allocator2{};
- sp<android::hardware::graphics::allocator::V3_0::IAllocator> allocator3 =
- android::hardware::graphics::allocator::V3_0::IAllocator::getService();
- if (allocator3) {
- mapper3 =
- android::hardware::graphics::mapper::V3_0::IMapper::getService();
- ASSERT_NE(nullptr, mapper3.get());
- grallocVar.emplace<AllocatorV3>(std::move(allocator3), std::move(mapper3));
- } else {
- allocator2 =
- android::hardware::graphics::allocator::V2_0::IAllocator::getService();
- ASSERT_NE(nullptr, allocator2.get());
- mapper2 =
- android::hardware::graphics::mapper::V2_0::IMapper::getService();
- ASSERT_NE(nullptr, allocator2.get());
- grallocVar.emplace<AllocatorV2>(std::move(allocator2), std::move(mapper2));
- }
-
android::hardware::media::omx::V1_0::Status status{};
uint64_t usage{};
ASSERT_TRUE(omxNode->getGraphicBufferUsage(
@@ -246,57 +204,27 @@
}).isOk());
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
+ uint32_t stride;
+ buffer_handle_t handle = nullptr;
+ android::GraphicBufferAllocator& allocator = android::GraphicBufferAllocator::get();
+ android::status_t error = allocator.allocate(
+ nFrameWidth, nFrameHeight, static_cast<android::PixelFormat>(format), 1,
+ usage | BufferUsage::CPU_READ_OFTEN, &handle, &stride, "omx_vts_common");
+
+ ASSERT_EQ(error, android::NO_ERROR);
+ ASSERT_NE(handle, nullptr);
+
+ *nStride = static_cast<int32_t>(stride);
+ buffer->omxBuffer.nativeHandle = handle;
+ buffer->omxBuffer.attr.anwBuffer.width = nFrameWidth;
+ buffer->omxBuffer.attr.anwBuffer.height = nFrameHeight;
+ buffer->omxBuffer.attr.anwBuffer.stride = stride;
+ buffer->omxBuffer.attr.anwBuffer.format = static_cast<PixelFormat>(format);
+ buffer->omxBuffer.attr.anwBuffer.usage = usage | BufferUsage::CPU_READ_OFTEN;
+ buffer->omxBuffer.attr.anwBuffer.layerCount = 1;
static std::atomic_int32_t bufferIdCounter{0};
-
- std::visit([buffer, nFrameWidth, nFrameHeight, format, usage, nStride](auto&& gralloc) {
- using Gralloc = std::remove_reference_t<decltype(gralloc)>;
- using Descriptor = typename Gralloc::Descriptor;
- using DescriptorInfo = typename Gralloc::DescriptorInfo;
- using Error = typename Gralloc::Error;
- using Format = typename Gralloc::Format;
- using Usage = typename Gralloc::Usage;
-
- Error error{};
- Descriptor descriptor{};
-
- DescriptorInfo descriptorInfo{};
- descriptorInfo.width = nFrameWidth;
- descriptorInfo.height = nFrameHeight;
- descriptorInfo.layerCount = 1;
- descriptorInfo.format = static_cast<Format>(format);
- descriptorInfo.usage = usage | Usage(BufferUsage::CPU_READ_OFTEN);
-
- gralloc.mMapper->createDescriptor(descriptorInfo,
- [&error, &descriptor](
- Error _s,
- const Descriptor& _n1) {
- error = _s;
- descriptor = _n1;
- });
- ASSERT_EQ(error, Error::NONE);
-
- gralloc.mAllocator->allocate(
- descriptor, 1,
- [&](Error _s, uint32_t _n1,
- const ::android::hardware::hidl_vec<
- ::android::hardware::hidl_handle>& _n2) {
- ASSERT_EQ(Error::NONE, _s);
- *nStride = _n1;
- buffer->omxBuffer.nativeHandle = _n2[0];
- buffer->omxBuffer.attr.anwBuffer.width = nFrameWidth;
- buffer->omxBuffer.attr.anwBuffer.height = nFrameHeight;
- buffer->omxBuffer.attr.anwBuffer.stride = _n1;
- buffer->omxBuffer.attr.anwBuffer.format =
- static_cast<PixelFormat>(descriptorInfo.format);
- buffer->omxBuffer.attr.anwBuffer.usage =
- static_cast<uint32_t>(descriptorInfo.usage);
- buffer->omxBuffer.attr.anwBuffer.layerCount =
- descriptorInfo.layerCount;
- buffer->omxBuffer.attr.anwBuffer.id =
- (static_cast<uint64_t>(getpid()) << 32) |
- bufferIdCounter.fetch_add(1, std::memory_order_relaxed);
- });
- }, grallocVar);
+ buffer->omxBuffer.attr.anwBuffer.id = (static_cast<uint64_t>(getpid()) << 32) |
+ bufferIdCounter.fetch_add(1, std::memory_order_relaxed);
}
// allocate buffers needed on a component port
diff --git a/media/omx/1.0/vts/functional/common/media_hidl_test_common.h b/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
index bb03dd0..044408d 100644
--- a/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
+++ b/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
@@ -22,16 +22,6 @@
#endif
#include <getopt.h>
-
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <android/hardware/graphics/allocator/3.0/IAllocator.h>
-#include <android/hardware/graphics/common/1.0/types.h>
-#include <android/hardware/graphics/common/1.1/types.h>
-#include <android/hardware/graphics/common/1.2/types.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <android/hardware/graphics/mapper/2.0/types.h>
-#include <android/hardware/graphics/mapper/3.0/IMapper.h>
-#include <android/hardware/graphics/mapper/3.0/types.h>
#include <gtest/gtest.h>
#include <hidl/ServiceManagement.h>
#include <media/stagefright/foundation/ALooper.h>
@@ -46,6 +36,9 @@
#include <media/openmax/OMX_AudioExt.h>
#include <media/openmax/OMX_VideoExt.h>
+#include <ui/GraphicBufferAllocator.h>
+#include <ui/GraphicBufferMapper.h>
+
/* TIME OUTS (Wait time in dequeueMessage()) */
/* As component is switching states (loaded<->idle<->execute), dequeueMessage()
@@ -312,35 +305,6 @@
/*
* common functions declarations
*/
-struct GrallocV2 {
- using Format = android::hardware::graphics::common::V1_0::PixelFormat;
- using Usage = android::hardware::hidl_bitfield<
- android::hardware::graphics::common::V1_0::BufferUsage>;
-
- using IAllocator = android::hardware::graphics::allocator::V2_0::IAllocator;
-
- using IMapper = android::hardware::graphics::mapper::V2_0::IMapper;
- using Error = android::hardware::graphics::mapper::V2_0::Error;
- using Descriptor = android::hardware::graphics::mapper::V2_0::BufferDescriptor;
- using YCbCrLayout = android::hardware::graphics::mapper::V2_0::YCbCrLayout;
- using DescriptorInfo = IMapper::BufferDescriptorInfo;
- using Rect = IMapper::Rect;
-};
-
-struct GrallocV3 {
- using Format = android::hardware::graphics::common::V1_2::PixelFormat;
- using Usage = android::hardware::hidl_bitfield<
- android::hardware::graphics::common::V1_2::BufferUsage>;
-
- using IAllocator = android::hardware::graphics::allocator::V3_0::IAllocator;
-
- using IMapper = android::hardware::graphics::mapper::V3_0::IMapper;
- using Error = android::hardware::graphics::mapper::V3_0::Error;
- using Descriptor = android::hardware::graphics::mapper::V3_0::BufferDescriptor;
- using YCbCrLayout = android::hardware::graphics::mapper::V3_0::YCbCrLayout;
- using DescriptorInfo = IMapper::BufferDescriptorInfo;
- using Rect = IMapper::Rect;
-};
Return<android::hardware::media::omx::V1_0::Status> setRole(sp<IOmxNode> omxNode,
const std::string& role);
diff --git a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
index 4b469e6..7519f2f 100644
--- a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
+++ b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
@@ -23,8 +23,6 @@
#include <android/hardware/graphics/bufferqueue/1.0/IGraphicBufferProducer.h>
#include <android/hardware/graphics/bufferqueue/1.0/IProducerListener.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <android/hardware/graphics/mapper/2.0/types.h>
#include <android/hardware/media/omx/1.0/IGraphicBufferSource.h>
#include <android/hardware/media/omx/1.0/IOmx.h>
#include <android/hardware/media/omx/1.0/IOmxBufferSource.h>
@@ -364,61 +362,6 @@
return Void();
};
-// Variant of mappers
-struct MapperV2 : public GrallocV2 {
- sp<IMapper> mMapper;
- MapperV2(sp<IMapper>&& mapper): mMapper{std::move(mapper)} {}
- MapperV2() = default;
- android::hardware::Return<void> lock(
- void* buffer,
- Usage usage,
- const Rect& rect,
- const android::hardware::hidl_handle& handle,
- Error* error,
- void** data) {
- return mMapper->lock(buffer, usage, rect, handle,
- [error, data](Error e, void* d) {
- *error = e;
- *data = d;
- });
- }
-};
-struct MapperV3 : public GrallocV3 {
- sp<IMapper> mMapper;
- MapperV3(sp<IMapper>&& mapper): mMapper{std::move(mapper)} {}
- MapperV3() = default;
- android::hardware::Return<void> lock(
- void* buffer,
- Usage usage,
- const Rect& rect,
- const android::hardware::hidl_handle& handle,
- Error* error,
- void** data) {
- return mMapper->lock(buffer, usage, rect, handle,
- [error, data](Error e, void* d, int32_t, int32_t) {
- *error = e;
- *data = d;
- });
- }
-};
-using MapperVar = std::variant<MapperV2, MapperV3>;
-// Initializes the MapperVar by trying services of different versions.
-bool initialize(MapperVar& mapperVar) {
- sp<android::hardware::graphics::mapper::V3_0::IMapper> mapper3 =
- android::hardware::graphics::mapper::V3_0::IMapper::getService();
- if (mapper3) {
- mapperVar.emplace<MapperV3>(std::move(mapper3));
- return true;
- }
- sp<android::hardware::graphics::mapper::V2_0::IMapper> mapper2 =
- android::hardware::graphics::mapper::V2_0::IMapper::getService();
- if (mapper2) {
- mapperVar.emplace<MapperV2>(std::move(mapper2));
- return true;
- }
- return false;
-}
-
// request VOP refresh
void requestIDR(sp<IOmxNode> omxNode, OMX_U32 portIndex) {
android::hardware::media::omx::V1_0::Status status;
@@ -627,168 +570,113 @@
}
}
-int colorFormatConversion(BufferInfo* buffer, void* buff, PixelFormat format,
+int colorFormatConversion(BufferInfo* buffer, buffer_handle_t buff, PixelFormat format,
std::ifstream& eleStream) {
- MapperVar mapperVar;
- if (!initialize(mapperVar)) {
- EXPECT_TRUE(false) << "failed to obtain mapper service";
- return 1;
+ android::GraphicBufferMapper& gbmapper = android::GraphicBufferMapper::get();
+
+ android::Rect rect(0, 0, buffer->omxBuffer.attr.anwBuffer.width,
+ buffer->omxBuffer.attr.anwBuffer.height);
+ android_ycbcr ycbcrLayout;
+ android::status_t error = android::NO_ERROR;
+
+ if (format == PixelFormat::YV12 || format == PixelFormat::YCRCB_420_SP ||
+ format == PixelFormat::YCBCR_420_888) {
+ error = gbmapper.lockYCbCr(buff, buffer->omxBuffer.attr.anwBuffer.usage, rect,
+ &ycbcrLayout);
+ EXPECT_EQ(error, android::NO_ERROR);
+ if (error != android::NO_ERROR) return 1;
+
+ int size = ((rect.getWidth() * rect.getHeight() * 3) >> 1);
+ char* img = new char[size];
+ if (img == nullptr) return 1;
+ eleStream.read(img, size);
+ if (eleStream.gcount() != size) {
+ delete[] img;
+ return 1;
+ }
+
+ char* imgTmp = img;
+ char* ipBuffer = static_cast<char*>(ycbcrLayout.y);
+ for (size_t y = rect.getHeight(); y > 0; --y) {
+ memcpy(ipBuffer, imgTmp, rect.getWidth());
+ ipBuffer += ycbcrLayout.ystride;
+ imgTmp += rect.getWidth();
+ }
+
+ if (format == PixelFormat::YV12)
+ EXPECT_EQ(ycbcrLayout.chroma_step, 1U);
+ else if (format == PixelFormat::YCRCB_420_SP)
+ EXPECT_EQ(ycbcrLayout.chroma_step, 2U);
+
+ ipBuffer = static_cast<char*>(ycbcrLayout.cb);
+ for (size_t y = rect.getHeight() >> 1; y > 0; --y) {
+ for (int32_t x = 0; x < (rect.getWidth() >> 1); ++x) {
+ ipBuffer[ycbcrLayout.chroma_step * x] = *imgTmp++;
+ }
+ ipBuffer += ycbcrLayout.cstride;
+ }
+ ipBuffer = static_cast<char*>(ycbcrLayout.cr);
+ for (size_t y = rect.getHeight() >> 1; y > 0; --y) {
+ for (int32_t x = 0; x < (rect.getWidth() >> 1); ++x) {
+ ipBuffer[ycbcrLayout.chroma_step * x] = *imgTmp++;
+ }
+ ipBuffer += ycbcrLayout.cstride;
+ }
+
+ delete[] img;
+
+ error = gbmapper.unlock(buff);
+ EXPECT_EQ(error, android::NO_ERROR);
+ if (error != android::NO_ERROR) return 1;
+ } else {
+ void* data;
+ int32_t outBytesPerPixel;
+ int32_t outBytesPerStride;
+ error = gbmapper.lock(buff, buffer->omxBuffer.attr.anwBuffer.usage, rect, &data,
+ &outBytesPerPixel, &outBytesPerStride);
+ EXPECT_EQ(error, android::NO_ERROR);
+ if (error != android::NO_ERROR) return 1;
+
+ if (format == PixelFormat::BGRA_8888) {
+ char* ipBuffer = static_cast<char*>(data);
+ for (size_t y = rect.getHeight(); y > 0; --y) {
+ eleStream.read(ipBuffer, rect.getWidth() * 4);
+ if (eleStream.gcount() != rect.getWidth() * 4) return 1;
+ ipBuffer += buffer->omxBuffer.attr.anwBuffer.stride * 4;
+ }
+ } else {
+ EXPECT_TRUE(false) << "un expected pixel format";
+ return 1;
+ }
+
+ error = gbmapper.unlock(buff);
+ EXPECT_EQ(error, android::NO_ERROR);
+ if (error != android::NO_ERROR) return 1;
}
- return std::visit([buffer, buff, format, &eleStream](auto&& mapper) -> int {
- using Gralloc = std::remove_reference_t<decltype(mapper)>;
- using Error = typename Gralloc::Error;
- using Rect = typename Gralloc::Rect;
- using Usage = typename Gralloc::Usage;
- using YCbCrLayout = typename Gralloc::YCbCrLayout;
-
- android::hardware::hidl_handle fence;
- Rect rect;
- YCbCrLayout ycbcrLayout;
- Error error;
- rect.left = 0;
- rect.top = 0;
- rect.width = buffer->omxBuffer.attr.anwBuffer.width;
- rect.height = buffer->omxBuffer.attr.anwBuffer.height;
-
- if (format == PixelFormat::YV12 || format == PixelFormat::YCRCB_420_SP ||
- format == PixelFormat::YCBCR_420_888) {
- mapper.mMapper->lockYCbCr(
- buff,
- static_cast<Usage>(
- buffer->omxBuffer.attr.anwBuffer.usage),
- rect,
- fence,
- [&](Error _e,
- const YCbCrLayout& _n1) {
- error = _e;
- ycbcrLayout = _n1;
- });
- EXPECT_EQ(error, Error::NONE);
- if (error != Error::NONE)
- return 1;
-
- int size = ((rect.width * rect.height * 3) >> 1);
- char* img = new char[size];
- if (img == nullptr) return 1;
- eleStream.read(img, size);
- if (eleStream.gcount() != size) {
- delete[] img;
- return 1;
- }
-
- char* imgTmp = img;
- char* ipBuffer = static_cast<char*>(ycbcrLayout.y);
- for (size_t y = rect.height; y > 0; --y) {
- memcpy(ipBuffer, imgTmp, rect.width);
- ipBuffer += ycbcrLayout.yStride;
- imgTmp += rect.width;
- }
-
- if (format == PixelFormat::YV12)
- EXPECT_EQ(ycbcrLayout.chromaStep, 1U);
- else if (format == PixelFormat::YCRCB_420_SP)
- EXPECT_EQ(ycbcrLayout.chromaStep, 2U);
-
- ipBuffer = static_cast<char*>(ycbcrLayout.cb);
- for (size_t y = rect.height >> 1; y > 0; --y) {
- for (int32_t x = 0; x < (rect.width >> 1); ++x) {
- ipBuffer[ycbcrLayout.chromaStep * x] = *imgTmp++;
- }
- ipBuffer += ycbcrLayout.cStride;
- }
- ipBuffer = static_cast<char*>(ycbcrLayout.cr);
- for (size_t y = rect.height >> 1; y > 0; --y) {
- for (int32_t x = 0; x < (rect.width >> 1); ++x) {
- ipBuffer[ycbcrLayout.chromaStep * x] = *imgTmp++;
- }
- ipBuffer += ycbcrLayout.cStride;
- }
-
- delete[] img;
-
- mapper.mMapper->unlock(buff,
- [&](Error _e,
- const android::hardware::hidl_handle& _n1) {
- error = _e;
- fence = _n1;
- });
- EXPECT_EQ(error, Error::NONE);
- if (error != Error::NONE)
- return 1;
- } else {
- void* data;
- mapper.lock(
- buff,
- buffer->omxBuffer.attr.anwBuffer.usage,
- rect,
- fence,
- &error,
- &data);
- EXPECT_EQ(error, Error::NONE);
- if (error != Error::NONE)
- return 1;
-
- if (format == PixelFormat::BGRA_8888) {
- char* ipBuffer = static_cast<char*>(data);
- for (size_t y = rect.height; y > 0; --y) {
- eleStream.read(ipBuffer, rect.width * 4);
- if (eleStream.gcount() != rect.width * 4) return 1;
- ipBuffer += buffer->omxBuffer.attr.anwBuffer.stride * 4;
- }
- } else {
- EXPECT_TRUE(false) << "un expected pixel format";
- return 1;
- }
-
- mapper.mMapper->unlock(
- buff,
- [&](Error _e, const android::hardware::hidl_handle& _n1) {
- error = _e;
- fence = _n1;
- });
- EXPECT_EQ(error, Error::NONE);
- if (error != Error::NONE)
- return 1;
- }
-
- return 0;
- }, mapperVar);
+ return 0;
}
int fillGraphicBuffer(BufferInfo* buffer, PixelFormat format,
std::ifstream& eleStream) {
- MapperVar mapperVar;
- if (!initialize(mapperVar)) {
- EXPECT_TRUE(false) << "failed to obtain mapper service";
- return 1;
- }
+ android::GraphicBufferMapper& gbmapper = android::GraphicBufferMapper::get();
+ buffer_handle_t buff;
+ android::status_t error = android::NO_ERROR;
+ gbmapper.importBuffer(
+ buffer->omxBuffer.nativeHandle, buffer->omxBuffer.attr.anwBuffer.width,
+ buffer->omxBuffer.attr.anwBuffer.height, buffer->omxBuffer.attr.anwBuffer.layerCount,
+ static_cast<android::PixelFormat>(format), buffer->omxBuffer.attr.anwBuffer.usage,
+ buffer->omxBuffer.attr.anwBuffer.stride, &buff);
+ EXPECT_EQ(error, android::NO_ERROR);
+ if (error != android::NO_ERROR) return 1;
- return std::visit([buffer, format, &eleStream](auto&& mapper) -> int {
- using Gralloc = std::remove_reference_t<decltype(mapper)>;
- using Error = typename Gralloc::Error;
+ if (colorFormatConversion(buffer, buff, format, eleStream)) return 1;
- void* buff = nullptr;
- Error error;
- mapper.mMapper->importBuffer(
- buffer->omxBuffer.nativeHandle,
- [&](Error _e, void* _n1) {
- error = _e;
- buff = _n1;
- });
- EXPECT_EQ(error, Error::NONE);
- if (error != Error::NONE)
- return 1;
+ error = gbmapper.freeBuffer(buff);
+ EXPECT_EQ(error, android::NO_ERROR);
+ if (error != android::NO_ERROR) return 1;
- if (colorFormatConversion(buffer, buff, format, eleStream)) return 1;
-
- error = mapper.mMapper->freeBuffer(buff);
- EXPECT_EQ(error, Error::NONE);
- if (error != Error::NONE)
- return 1;
-
- return 0;
- }, mapperVar);
+ return 0;
}
int dispatchGraphicBuffer(sp<IOmxNode> omxNode,
diff --git a/power/1.0/default/Android.bp b/power/1.0/default/Android.bp
index 1d152ee..74fb13f 100644
--- a/power/1.0/default/Android.bp
+++ b/power/1.0/default/Android.bp
@@ -54,6 +54,12 @@
"libhardware",
"libhidlbase",
"android.hardware.power@1.0",
+ "libhwbinder"
],
+ arch: {
+ arm: {
+ cflags: ["-DARCH_ARM_32"],
+ },
+ },
}
diff --git a/power/1.0/default/service.cpp b/power/1.0/default/service.cpp
index e8618b8..d561919 100644
--- a/power/1.0/default/service.cpp
+++ b/power/1.0/default/service.cpp
@@ -18,10 +18,16 @@
#include <android/hardware/power/1.0/IPower.h>
#include <hidl/LegacySupport.h>
+#ifdef ARCH_ARM_32
+#include <hwbinder/ProcessState.h>
+#endif
using android::hardware::power::V1_0::IPower;
using android::hardware::defaultPassthroughServiceImplementation;
int main() {
+ #ifdef ARCH_ARM_32
+ android::hardware::ProcessState::initWithMmapSize((size_t)16384);
+ #endif
return defaultPassthroughServiceImplementation<IPower>();
}
diff --git a/radio/1.0/vts/functional/vts_test_util.cpp b/radio/1.0/vts/functional/vts_test_util.cpp
index 7a21a40..9a2d089 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 <vts_test_util.h>
#include <iostream>
+#include "VtsCoreUtil.h"
int GetRandomSerialNumber() {
return rand();
@@ -78,4 +79,24 @@
__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 df8dd77..1625f11 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 <gtest/gtest.h>
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 @@
* 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 3ba9b9d..1b254a1 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 @@
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 @@
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 @@
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 53a5845..8eee811 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 @@
// 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 d0aae47..3e93bf4 100644
--- a/radio/1.4/vts/functional/radio_response.cpp
+++ b/radio/1.4/vts/functional/radio_response.cpp
@@ -762,8 +762,9 @@
Return<void> 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();
}
diff --git a/sensors/1.0/default/Android.bp b/sensors/1.0/default/Android.bp
index d5c1b23..98f46ae 100644
--- a/sensors/1.0/default/Android.bp
+++ b/sensors/1.0/default/Android.bp
@@ -46,6 +46,7 @@
relative_install_path: "hw",
vendor: true,
init_rc: ["android.hardware.sensors@1.0-service.rc"],
+ defaults: ["hidl_defaults"],
srcs: ["service.cpp"],
shared_libs: [
@@ -56,5 +57,11 @@
"libutils",
"libhidlbase",
"android.hardware.sensors@1.0",
+ "libhwbinder",
],
+ arch: {
+ arm: {
+ cflags: ["-DARCH_ARM_32"],
+ },
+ },
}
diff --git a/sensors/1.0/default/android.hardware.sensors@1.0-service.rc b/sensors/1.0/default/android.hardware.sensors@1.0-service.rc
index 1af6d0b..e029bb8 100644
--- a/sensors/1.0/default/android.hardware.sensors@1.0-service.rc
+++ b/sensors/1.0/default/android.hardware.sensors@1.0-service.rc
@@ -2,6 +2,6 @@
interface android.hardware.sensors@1.0::ISensors default
class hal
user system
- group system wakelock uhid context_hub
+ group system wakelock uhid input context_hub
capabilities BLOCK_SUSPEND
rlimit rtprio 10 10
diff --git a/sensors/1.0/default/service.cpp b/sensors/1.0/default/service.cpp
index 65f6d81..c413d1a 100644
--- a/sensors/1.0/default/service.cpp
+++ b/sensors/1.0/default/service.cpp
@@ -19,10 +19,30 @@
#include <android/hardware/sensors/1.0/ISensors.h>
#include <hidl/LegacySupport.h>
+#ifdef ARCH_ARM_32
+#include <hwbinder/ProcessState.h>
+#include <cutils/properties.h>
+#endif
+
using android::hardware::sensors::V1_0::ISensors;
using android::hardware::defaultPassthroughServiceImplementation;
+#ifdef ARCH_ARM_32
+//default h/w binder memsize for sensors is 8 KB
+#define DEFAULT_SENSORS_HW_BINDER_MEM_SIZE_KB 8
+size_t getHWBinderMmapSize() {
+ int32_t value = DEFAULT_SENSORS_HW_BINDER_MEM_SIZE_KB;
+
+ value = property_get_int32("persist.vendor.sensor.hw.binder.size", value);
+ ALOGD("Init hw binder with mem size = %d", value);
+ return 1024 * value;
+}
+#endif
+
int main() {
+#ifdef ARCH_ARM_32
+ android::hardware::ProcessState::initWithMmapSize((size_t)getHWBinderMmapSize());
+#endif
/* Sensors framework service needs at least two threads.
* One thread blocks on a "poll"
* The second thread is needed for all other HAL methods.
diff --git a/sensors/common/default/2.X/multihal/HalProxy.cpp b/sensors/common/default/2.X/multihal/HalProxy.cpp
index 75ffc17..fe3fc84 100644
--- a/sensors/common/default/2.X/multihal/HalProxy.cpp
+++ b/sensors/common/default/2.X/multihal/HalProxy.cpp
@@ -693,6 +693,10 @@
int64_t timeoutStart /* = -1 */) {
if (!mThreadsRun.load()) return;
std::lock_guard<std::recursive_mutex> 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 bf2ad35..2a2baa2 100644
--- a/sensors/common/default/2.X/multihal/ScopedWakelock.cpp
+++ b/sensors/common/default/2.X/multihal/ScopedWakelock.cpp
@@ -28,6 +28,21 @@
.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 1cc5cd5..b3f398c 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 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 a15faed..1b60f4b 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 {
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 0000000..133d9e8
--- /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 <gtest/gtest.h>
+
+#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
diff --git a/tv/tuner/1.0/vts/functional/DescramblerTests.cpp b/tv/tuner/1.0/vts/functional/DescramblerTests.cpp
index d7440bc..2e27475 100644
--- a/tv/tuner/1.0/vts/functional/DescramblerTests.cpp
+++ b/tv/tuner/1.0/vts/functional/DescramblerTests.cpp
@@ -102,13 +102,13 @@
AssertionResult DescramblerTests::setKeyToken(TunerKeyToken token) {
Result status;
- if (mDescrambler) {
+ if (!mDescrambler) {
ALOGW("[vts] Descrambler is not opened yet.");
return failure();
}
status = mDescrambler->setKeyToken(token);
- if (status == Result::SUCCESS) {
+ if (status != Result::SUCCESS) {
ALOGW("[vts] setKeyToken failed.");
return failure();
}
@@ -118,13 +118,13 @@
AssertionResult DescramblerTests::addPid(DemuxPid pid, sp<IFilter> optionalSourceFilter) {
Result status;
- if (mDescrambler) {
+ if (!mDescrambler) {
ALOGW("[vts] Descrambler is not opened yet.");
return failure();
}
status = mDescrambler->addPid(pid, optionalSourceFilter);
- if (status == Result::SUCCESS) {
+ if (status != Result::SUCCESS) {
ALOGW("[vts] addPid failed.");
return failure();
}
@@ -134,13 +134,13 @@
AssertionResult DescramblerTests::removePid(DemuxPid pid, sp<IFilter> optionalSourceFilter) {
Result status;
- if (mDescrambler) {
+ if (!mDescrambler) {
ALOGW("[vts] Descrambler is not opened yet.");
return failure();
}
status = mDescrambler->removePid(pid, optionalSourceFilter);
- if (status == Result::SUCCESS) {
+ if (status != Result::SUCCESS) {
ALOGW("[vts] removePid failed.");
return failure();
}
@@ -150,14 +150,14 @@
AssertionResult DescramblerTests::closeDescrambler() {
Result status;
- if (mDescrambler) {
+ if (!mDescrambler) {
ALOGW("[vts] Descrambler is not opened yet.");
return failure();
}
status = mDescrambler->close();
mDescrambler = nullptr;
- if (status == Result::SUCCESS) {
+ if (status != Result::SUCCESS) {
ALOGW("[vts] close Descrambler failed.");
return failure();
}
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
index 6819659..2be68b8 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
@@ -292,18 +292,18 @@
ASSERT_TRUE(mFilterTests.configFilter((*config).settings, filterId));
filterIds.insert(filterId);
}
- mDescramblerTests.openDescrambler(demuxId);
+ ASSERT_TRUE(mDescramblerTests.openDescrambler(demuxId));
TunerKeyToken token;
ASSERT_TRUE(mDescramblerTests.getKeyToken(descConfig.casSystemId, descConfig.provisionStr,
descConfig.hidlPvtData, token));
- mDescramblerTests.setKeyToken(token);
+ ASSERT_TRUE(mDescramblerTests.setKeyToken(token));
vector<DemuxPid> pids;
DemuxPid pid;
for (config = mediaFilterConfs.begin(); config != mediaFilterConfs.end(); config++) {
ASSERT_TRUE(mDescramblerTests.getDemuxPidFromFilterSettings((*config).type,
(*config).settings, pid));
pids.push_back(pid);
- mDescramblerTests.addPid(pid, nullptr);
+ ASSERT_TRUE(mDescramblerTests.addPid(pid, nullptr));
}
for (id = filterIds.begin(); id != filterIds.end(); id++) {
ASSERT_TRUE(mFilterTests.startFilter(*id));
@@ -316,9 +316,9 @@
ASSERT_TRUE(mFilterTests.stopFilter(*id));
}
for (auto pid : pids) {
- mDescramblerTests.removePid(pid, nullptr);
+ ASSERT_TRUE(mDescramblerTests.removePid(pid, nullptr));
}
- mDescramblerTests.closeDescrambler();
+ ASSERT_TRUE(mDescramblerTests.closeDescrambler());
for (id = filterIds.begin(); id != filterIds.end(); id++) {
ASSERT_TRUE(mFilterTests.closeFilter(*id));
}
@@ -410,9 +410,9 @@
filterArray[TS_PCR0].bufferSize));
ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(pcrFilterId));
ASSERT_TRUE(mFilterTests.configFilter(filterArray[TS_PCR0].settings, pcrFilterId));
- mDemuxTests.getAvSyncId(mediaFilter, avSyncHwId);
+ ASSERT_TRUE(mDemuxTests.getAvSyncId(mediaFilter, avSyncHwId));
ASSERT_TRUE(pcrFilterId == avSyncHwId);
- mDemuxTests.getAvSyncTime(pcrFilterId);
+ ASSERT_TRUE(mDemuxTests.getAvSyncTime(pcrFilterId));
ASSERT_TRUE(mFilterTests.closeFilter(pcrFilterId));
ASSERT_TRUE(mFilterTests.closeFilter(mediaFilterId));
ASSERT_TRUE(mDemuxTests.closeDemux());
@@ -519,8 +519,8 @@
ASSERT_TRUE(mFrontendTests.setFrontendCallback());
ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
- mDescramblerTests.openDescrambler(demuxId);
- mDescramblerTests.closeDescrambler();
+ ASSERT_TRUE(mDescramblerTests.openDescrambler(demuxId));
+ ASSERT_TRUE(mDescramblerTests.closeDescrambler());
ASSERT_TRUE(mDemuxTests.closeDemux());
ASSERT_TRUE(mFrontendTests.closeFrontend());
}
diff --git a/usb/1.0/default/Usb.cpp b/usb/1.0/default/Usb.cpp
index 6eb8842..f72ab9c 100644
--- a/usb/1.0/default/Usb.cpp
+++ b/usb/1.0/default/Usb.cpp
@@ -206,6 +206,19 @@
bool canSwitchRoleHelper(const std::string portName, PortRoleType type) {
std::string filename = appendRoleNodeHelper(portName, type);
+
+ if (type == PortRoleType::DATA_ROLE || type == PortRoleType::POWER_ROLE) {
+ std::string pd_filename = "/sys/class/power_supply/usb/pd_active";
+ std::string pd_active;
+
+ if (!readFile(pd_filename, pd_active)) {
+ if (pd_active == "0")
+ return false;
+ } else {
+ ALOGE("canSwitchRoleHelper: couldn't read %s", pd_filename.c_str());
+ }
+ }
+
std::ofstream file(filename);
if (file.is_open()) {
@@ -396,7 +409,7 @@
for (int n = 0; n < nevents; ++n) {
if (events[n].data.ptr)
- (*(void (*)(int, struct data *payload))events[n].data.ptr)
+ (*(void (*)(uint32_t, struct data *payload))events[n].data.ptr)
(events[n].events, &payload);
}
}
diff --git a/vibrator/1.0/default/Android.bp b/vibrator/1.0/default/Android.bp
index b0d0986..1385eac 100644
--- a/vibrator/1.0/default/Android.bp
+++ b/vibrator/1.0/default/Android.bp
@@ -42,5 +42,13 @@
"libutils",
"libhardware",
"android.hardware.vibrator@1.0",
+ "libhwbinder",
],
+ arch: {
+ arm: {
+ cflags: [
+ "-DARCH_ARM_32"
+ ],
+ },
+ },
}
diff --git a/vibrator/1.0/default/service.cpp b/vibrator/1.0/default/service.cpp
index 7cc0744..b626056 100644
--- a/vibrator/1.0/default/service.cpp
+++ b/vibrator/1.0/default/service.cpp
@@ -17,10 +17,14 @@
#include <android/hardware/vibrator/1.0/IVibrator.h>
#include <hidl/LegacySupport.h>
+#include <hwbinder/ProcessState.h>
using android::hardware::vibrator::V1_0::IVibrator;
using android::hardware::defaultPassthroughServiceImplementation;
int main() {
+#ifdef ARCH_ARM_32
+ android::hardware::ProcessState::initWithMmapSize((size_t)8192);
+#endif
return defaultPassthroughServiceImplementation<IVibrator>();
}
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index 8340517..4967d71 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -95,7 +95,7 @@
}
TEST_P(VibratorAidl, OnWithCallback) {
- if (!(capabilities & IVibrator::CAP_PERFORM_CALLBACK)) return;
+ if (!(capabilities & IVibrator::CAP_ON_CALLBACK)) return;
std::promise<void> completionPromise;
std::future<void> completionFuture{completionPromise.get_future()};
@@ -109,7 +109,7 @@
}
TEST_P(VibratorAidl, OnCallbackNotSupported) {
- if (!(capabilities & IVibrator::CAP_PERFORM_CALLBACK)) {
+ if (!(capabilities & IVibrator::CAP_ON_CALLBACK)) {
sp<CompletionCallback> callback = new CompletionCallback([] {});
EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, vibrator->on(250, callback).exceptionCode());
}
diff --git a/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
index 3ff33a5..5b11dd3 100644
--- a/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
+++ b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
@@ -89,8 +89,12 @@
}
} // namespace
+sp<IWifi> getWifi(const std::string& instance_name) {
+ return IWifi::getService(instance_name);
+}
+
sp<IWifiChip> getWifiChip(const std::string& instance_name) {
- sp<IWifi> wifi = IWifi::getService(instance_name);
+ sp<IWifi> wifi = getWifi(instance_name);
if (!wifi.get()) {
return nullptr;
}
diff --git a/wifi/1.0/vts/functional/wifi_hidl_test_utils.h b/wifi/1.0/vts/functional/wifi_hidl_test_utils.h
index d22ed77..5c78637 100644
--- a/wifi/1.0/vts/functional/wifi_hidl_test_utils.h
+++ b/wifi/1.0/vts/functional/wifi_hidl_test_utils.h
@@ -31,6 +31,8 @@
// Note: We only have a single instance of each of these objects currently.
// These helper functions should be modified to return vectors if we support
// multiple instances.
+android::sp<android::hardware::wifi::V1_0::IWifi> getWifi(
+ const std::string& instance_name);
android::sp<android::hardware::wifi::V1_0::IWifiChip> getWifiChip(
const std::string& instance_name);
android::sp<android::hardware::wifi::V1_0::IWifiApIface> getWifiApIface(
diff --git a/wifi/1.4/default/Android.mk b/wifi/1.4/default/Android.mk
index 6be7dad..e7fde844 100644
--- a/wifi/1.4/default/Android.mk
+++ b/wifi/1.4/default/Android.mk
@@ -39,6 +39,12 @@
ifdef WIFI_AVOID_IFACE_RESET_MAC_CHANGE
LOCAL_CPPFLAGS += -DWIFI_AVOID_IFACE_RESET_MAC_CHANGE
endif
+ifdef QC_WIFI_HIDL_FEATURE_DUAL_AP
+LOCAL_CPPFLAGS += -DQC_WIFI_HIDL_FEATURE_DUAL_AP
+endif
+ifdef QC_WIFI_HIDL_FEATURE_DUAL_STA
+LOCAL_CPPFLAGS += -DQC_WIFI_HIDL_FEATURE_DUAL_STA
+endif
# Allow implicit fallthroughs in wifi_legacy_hal.cpp until they are fixed.
LOCAL_CFLAGS += -Wno-error=implicit-fallthrough
LOCAL_SRC_FILES := \
@@ -84,6 +90,10 @@
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_PROPRIETARY_MODULE := true
LOCAL_CPPFLAGS := -Wall -Werror -Wextra
+ifeq ($(TARGET_ARCH),arm)
+ LOCAL_CPPFLAGS += -DARCH_ARM_32
+endif
+
LOCAL_SRC_FILES := \
service.cpp
LOCAL_SHARED_LIBRARIES := \
@@ -93,6 +103,7 @@
liblog \
libnl \
libutils \
+ libhwbinder \
libwifi-hal \
libwifi-system-iface \
android.hardware.wifi@1.0 \
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 cf917b5..061689d 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
diff --git a/wifi/1.4/default/hidl_struct_util.cpp b/wifi/1.4/default/hidl_struct_util.cpp
index fd1d5b1..87c0708 100644
--- a/wifi/1.4/default/hidl_struct_util.cpp
+++ b/wifi/1.4/default/hidl_struct_util.cpp
@@ -52,7 +52,7 @@
case legacy_hal::WIFI_LOGGER_POWER_EVENT_SUPPORTED:
return HidlChipCaps::DEBUG_RING_BUFFER_POWER_EVENT;
case legacy_hal::WIFI_LOGGER_WAKE_LOCK_SUPPORTED:
- return HidlChipCaps::DEBUG_RING_BUFFER_WAKELOCK_EVENT;
+ return HidlChipCaps::DEBUG_HOST_WAKE_REASON_STATS;
};
CHECK(false) << "Unknown legacy feature: " << feature;
return {};
@@ -155,10 +155,8 @@
}
}
- // There are no flags for these 3 in the legacy feature set. Adding them to
+ // There are no flags for these in the legacy feature set. Adding this to
// the set because all the current devices support it.
- *hidl_caps |= HidlChipCaps::DEBUG_RING_BUFFER_VENDOR_DATA;
- *hidl_caps |= HidlChipCaps::DEBUG_HOST_WAKE_REASON_STATS;
*hidl_caps |= HidlChipCaps::DEBUG_ERROR_ALERTS;
return true;
}
diff --git a/wifi/1.4/default/service.cpp b/wifi/1.4/default/service.cpp
index 3f7f609..a959571 100644
--- a/wifi/1.4/default/service.cpp
+++ b/wifi/1.4/default/service.cpp
@@ -19,6 +19,9 @@
#include <hidl/HidlTransportSupport.h>
#include <utils/Looper.h>
#include <utils/StrongPointer.h>
+#include <hwbinder/ProcessState.h>
+#include <cutils/properties.h>
+#include <signal.h>
#include "wifi.h"
#include "wifi_feature_flags.h"
@@ -35,6 +38,17 @@
using android::hardware::wifi::V1_4::implementation::mode_controller::
WifiModeController;
+#ifdef ARCH_ARM_32
+#define DEFAULT_WIFIHAL_HW_BINDER_SIZE_KB 16
+size_t getHWBinderMmapSize() {
+ size_t value = 0;
+ value = property_get_int32("persist.vendor.wifi.wifihal.hw.binder.size", DEFAULT_WIFIHAL_HW_BINDER_SIZE_KB);
+ if (!value) value = DEFAULT_WIFIHAL_HW_BINDER_SIZE_KB; // deafult to 1 page of 4 Kb
+
+ return 1024 * value;
+}
+#endif /* ARCH_ARM_32 */
+
#ifdef LAZY_SERVICE
const bool kLazyService = true;
#else
@@ -42,6 +56,10 @@
#endif
int main(int /*argc*/, char** argv) {
+#ifdef ARCH_ARM_32
+ android::hardware::ProcessState::initWithMmapSize(getHWBinderMmapSize());
+#endif /* ARCH_ARM_32 */
+ signal(SIGPIPE, SIG_IGN);
android::base::InitLogging(
argv, android::base::LogdLogger(android::base::SYSTEM));
LOG(INFO) << "Wifi Hal is booting up...";
diff --git a/wifi/1.4/default/wifi_ap_iface.cpp b/wifi/1.4/default/wifi_ap_iface.cpp
index 8777a4c..6218d0f 100644
--- a/wifi/1.4/default/wifi_ap_iface.cpp
+++ b/wifi/1.4/default/wifi_ap_iface.cpp
@@ -113,7 +113,23 @@
WifiStatus WifiApIface::setMacAddressInternal(
const std::array<uint8_t, 6>& mac) {
+#ifndef WIFI_AVOID_IFACE_RESET_MAC_CHANGE
+ if (!iface_util_.lock()->setUpState(ifname_, false)) {
+ return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+ }
+#endif
bool status = iface_util_.lock()->setMacAddress(ifname_, mac);
+#ifndef WIFI_AVOID_IFACE_RESET_MAC_CHANGE
+ if (!iface_util_.lock()->setUpState(ifname_, true)) {
+ LOG(INFO) << "Wait for driver ready and try to set iface UP again";
+ if (legacy_hal_.lock()->waitForDriverReady() !=
+ legacy_hal::WIFI_SUCCESS ||
+ !iface_util_.lock()->setUpState(ifname_, true)) {
+ return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+ }
+ }
+ iface_util_.lock()->onStateToggleOffOn(ifname_);
+#endif
if (!status) {
return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
}
diff --git a/wifi/1.4/default/wifi_chip.cpp b/wifi/1.4/default/wifi_chip.cpp
old mode 100644
new mode 100755
index 8747e61..16f9f26
--- a/wifi/1.4/default/wifi_chip.cpp
+++ b/wifi/1.4/default/wifi_chip.cpp
@@ -21,6 +21,7 @@
#include <cutils/properties.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
+#include <net/if.h>
#include "hidl_return_util.h"
#include "hidl_struct_util.h"
@@ -624,6 +625,15 @@
Return<void> WifiChip::debug(const hidl_handle& handle,
const hidl_vec<hidl_string>&) {
if (handle != nullptr && handle->numFds >= 1) {
+ {
+ std::unique_lock<std::mutex> 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";
@@ -655,7 +665,36 @@
hidl_status_cb, event_callback);
}
+void WifiChip::QcRemoveAndClearDynamicIfaces() {
+ for (const auto& iface : created_ap_ifaces_) {
+ std::string ifname = iface->getName();
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->deleteVirtualInterface(ifname);
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ LOG(ERROR) << "Failed to remove interface: " << ifname << " "
+ << legacyErrorToString(legacy_status);
+ }
+ }
+
+ for (const auto& iface : created_sta_ifaces_) {
+ std::string ifname = iface->getName();
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->deleteVirtualInterface(ifname);
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ LOG(ERROR) << "Failed to remove interface: " << ifname << " "
+ << legacyErrorToString(legacy_status);
+ }
+ }
+
+ // created_ap/sta_ifaces are also part of sta/ap_ifaces.
+ // Do no invalidate here.
+
+ created_ap_ifaces_.clear();
+ created_sta_ifaces_.clear();
+}
+
void WifiChip::invalidateAndRemoveAllIfaces() {
+ QcRemoveAndClearDynamicIfaces();
invalidateAndClearAll(ap_ifaces_);
invalidateAndClearAll(nan_ifaces_);
invalidateAndClearAll(p2p_ifaces_);
@@ -815,18 +854,25 @@
if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::AP)) {
return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
}
+
+ bool iface_created = false;
std::string ifname = allocateApIfaceName();
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->createVirtualInterface(
- ifname,
- hidl_struct_util::convertHidlIfaceTypeToLegacy(IfaceType::AP));
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- LOG(ERROR) << "Failed to add interface: " << ifname << " "
- << legacyErrorToString(legacy_status);
- return {createWifiStatusFromLegacyError(legacy_status), {}};
+ if (!if_nametoindex(ifname.c_str())) {
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->createVirtualInterface(
+ ifname,
+ hidl_struct_util::convertHidlIfaceTypeToLegacy(IfaceType::AP));
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ LOG(ERROR) << "Failed to add interface: " << ifname << " "
+ << legacyErrorToString(legacy_status);
+ return {createWifiStatusFromLegacyError(legacy_status), {}};
+ }
+ iface_created = true;
}
+ iface_util_.lock()->setRandomMacAddressIndex(ap_ifaces_.size());
sp<WifiApIface> iface = new WifiApIface(ifname, legacy_hal_, iface_util_);
ap_ifaces_.push_back(iface);
+ if (iface_created) created_ap_ifaces_.push_back(iface);
for (const auto& callback : event_cb_handler_.getCallbacks()) {
if (!callback->onIfaceAdded(IfaceType::AP, ifname).isOk()) {
LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
@@ -863,11 +909,15 @@
// nan/rtt objects over AP iface. But, there is no harm to do it
// here and not make that assumption all over the place.
invalidateAndRemoveDependencies(ifname);
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->deleteVirtualInterface(ifname);
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- LOG(ERROR) << "Failed to remove interface: " << ifname << " "
- << legacyErrorToString(legacy_status);
+ if (findUsingName(created_ap_ifaces_, ifname) != nullptr) {
+ iface_util_.lock()->setUpState(ifname, false);
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->deleteVirtualInterface(ifname);
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ LOG(ERROR) << "Failed to remove interface: " << ifname << " "
+ << legacyErrorToString(legacy_status);
+ }
+ invalidateAndClear(created_ap_ifaces_, iface);
}
invalidateAndClear(ap_ifaces_, iface);
for (const auto& callback : event_cb_handler_.getCallbacks()) {
@@ -984,18 +1034,23 @@
if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::STA)) {
return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
}
+ bool iface_created = false;
std::string ifname = allocateStaIfaceName();
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->createVirtualInterface(
- ifname,
- hidl_struct_util::convertHidlIfaceTypeToLegacy(IfaceType::STA));
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- LOG(ERROR) << "Failed to add interface: " << ifname << " "
- << legacyErrorToString(legacy_status);
- return {createWifiStatusFromLegacyError(legacy_status), {}};
+ if (!if_nametoindex(ifname.c_str())) {
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->createVirtualInterface(
+ ifname,
+ hidl_struct_util::convertHidlIfaceTypeToLegacy(IfaceType::STA));
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ LOG(ERROR) << "Failed to add interface: " << ifname << " "
+ << legacyErrorToString(legacy_status);
+ return {createWifiStatusFromLegacyError(legacy_status), {}};
+ }
+ iface_created = true;
}
sp<WifiStaIface> iface = new WifiStaIface(ifname, legacy_hal_, iface_util_);
sta_ifaces_.push_back(iface);
+ if (iface_created) created_sta_ifaces_.push_back(iface);
for (const auto& callback : event_cb_handler_.getCallbacks()) {
if (!callback->onIfaceAdded(IfaceType::STA, ifname).isOk()) {
LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
@@ -1029,11 +1084,15 @@
}
// Invalidate & remove any dependent objects first.
invalidateAndRemoveDependencies(ifname);
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->deleteVirtualInterface(ifname);
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- LOG(ERROR) << "Failed to remove interface: " << ifname << " "
- << legacyErrorToString(legacy_status);
+ if (findUsingName(created_sta_ifaces_, ifname) != nullptr) {
+ iface_util_.lock()->setUpState(ifname, false);
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->deleteVirtualInterface(ifname);
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ LOG(ERROR) << "Failed to remove interface: " << ifname << " "
+ << legacyErrorToString(legacy_status);
+ }
+ invalidateAndClear(created_sta_ifaces_, iface);
}
invalidateAndClear(sta_ifaces_, iface);
for (const auto& callback : event_cb_handler_.getCallbacks()) {
@@ -1120,6 +1179,9 @@
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 +1397,7 @@
LOG(ERROR) << "Ringname " << name << " not found";
return;
}
- // unlock
+ // unique_lock unlocked here
}
};
legacy_hal::wifi_error legacy_status =
@@ -1558,13 +1620,6 @@
return canCurrentModeSupportIfaceCombo(req_iface_combo);
}
-bool WifiChip::isDualApAllowedInCurrentMode() {
- // Check if we can support atleast 1 STA & 1 AP concurrently.
- std::map<IfaceType, size_t> req_iface_combo;
- req_iface_combo[IfaceType::AP] = 2;
- return canCurrentModeSupportIfaceCombo(req_iface_combo);
-}
-
std::string WifiChip::getFirstActiveWlanIfaceName() {
if (sta_ifaces_.size() > 0) return sta_ifaces_[0]->getName();
if (ap_ifaces_.size() > 0) return ap_ifaces_[0]->getName();
@@ -1590,17 +1645,15 @@
}
// AP iface names start with idx 1 for modes supporting
-// concurrent STA and not dual AP, else start with idx 0.
+// concurrent STA, else start with idx 0.
std::string WifiChip::allocateApIfaceName() {
// Check if we have a dedicated iface for AP.
std::string ifname = getApIfaceName();
if (!ifname.empty()) {
return ifname;
}
- return allocateApOrStaIfaceName((isStaApConcurrencyAllowedInCurrentMode() &&
- !isDualApAllowedInCurrentMode())
- ? 1
- : 0);
+ return allocateApOrStaIfaceName(
+ isStaApConcurrencyAllowedInCurrentMode() ? 1 : 0);
}
// STA iface names start with idx 0.
@@ -1637,7 +1690,7 @@
}
}
}
- // unlock
+ // unique_lock unlocked here
}
return true;
}
diff --git a/wifi/1.4/default/wifi_chip.h b/wifi/1.4/default/wifi_chip.h
index 98e18bb..abe025c 100644
--- a/wifi/1.4/default/wifi_chip.h
+++ b/wifi/1.4/default/wifi_chip.h
@@ -253,12 +253,12 @@
bool canCurrentModeSupportIfaceOfType(IfaceType requested_type);
bool isValidModeId(ChipModeId mode_id);
bool isStaApConcurrencyAllowedInCurrentMode();
- bool isDualApAllowedInCurrentMode();
std::string getFirstActiveWlanIfaceName();
std::string allocateApOrStaIfaceName(uint32_t start_idx);
std::string allocateApIfaceName();
std::string allocateStaIfaceName();
bool writeRingbufferFilesInternal();
+ void QcRemoveAndClearDynamicIfaces();
ChipId chip_id_;
std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
@@ -282,6 +282,9 @@
hidl_callback_util::HidlCallbackHandler<IWifiChipEventCallback>
event_cb_handler_;
+ std::vector<sp<WifiApIface>> created_ap_ifaces_;
+ std::vector<sp<WifiStaIface>> created_sta_ifaces_;
+
DISALLOW_COPY_AND_ASSIGN(WifiChip);
};
diff --git a/wifi/1.4/default/wifi_feature_flags.cpp b/wifi/1.4/default/wifi_feature_flags.cpp
index 195b460..515386e 100644
--- a/wifi/1.4/default/wifi_feature_flags.cpp
+++ b/wifi/1.4/default/wifi_feature_flags.cpp
@@ -79,14 +79,44 @@
# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P}, 1}}
# endif
# else
-# ifdef WIFI_HIDL_FEATURE_AWARE
-// (1 STA + 1 AP) or (1 STA + 1 of (P2P or NAN))
-# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\
- {{{STA}, 1}, {{P2P, NAN}, 1}}
+# ifdef QC_WIFI_HIDL_FEATURE_DUAL_AP
+# ifdef QC_WIFI_HIDL_FEATURE_DUAL_STA
+# ifdef WIFI_HIDL_FEATURE_AWARE
+// (1 STA + 1 AP) or (1 STA + 1 of (P2P or NAN)) or (2 AP) or (2 STA)
+# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\
+ {{{STA}, 1}, {{P2P, NAN}, 1}},\
+ {{{AP}, 2}},\
+ {{{STA}, 2}}
+# else
+// (1 STA + 1 AP) or (1 STA + 1 P2P) or (2 AP) or (2 STA)
+# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\
+ {{{STA}, 1}, {{P2P}, 1}},\
+ {{{AP}, 2}},\
+ {{{STA}, 2}}
+# endif
+# else
+# ifdef WIFI_HIDL_FEATURE_AWARE
+// (1 STA + 1 AP) or (1 STA + 1 of (P2P or NAN)) or (2 AP)
+# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\
+ {{{STA}, 1}, {{P2P, NAN}, 1}},\
+ {{{AP}, 2}}
+# else
+// (1 STA + 1 AP) or (1 STA + 1 P2P) or (2 AP)
+# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\
+ {{{STA}, 1}, {{P2P}, 1}},\
+ {{{AP}, 2}}
+# endif
+# endif
# else
-// (1 STA + 1 AP) or (1 STA + 1 P2P)
-# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\
- {{{STA}, 1}, {{P2P}, 1}}
+# ifdef WIFI_HIDL_FEATURE_AWARE
+// (1 STA + 1 AP) or (1 STA + 1 of (P2P or NAN))
+# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\
+ {{{STA}, 1}, {{P2P, NAN}, 1}}
+# else
+// (1 STA + 1 AP) or (1 STA + 1 P2P)
+# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\
+ {{{STA}, 1}, {{P2P}, 1}}
+# endif
# endif
# endif
#else
diff --git a/wifi/1.4/default/wifi_iface_util.cpp b/wifi/1.4/default/wifi_iface_util.cpp
index 49b7674..97c2f6a 100644
--- a/wifi/1.4/default/wifi_iface_util.cpp
+++ b/wifi/1.4/default/wifi_iface_util.cpp
@@ -43,8 +43,11 @@
WifiIfaceUtil::WifiIfaceUtil(
const std::weak_ptr<wifi_system::InterfaceTool> iface_tool)
: iface_tool_(iface_tool),
- random_mac_address_(nullptr),
- event_handlers_map_() {}
+ random_mac_address_index_(0),
+ event_handlers_map_() {
+ for (int i=0; i < MAX_RANDOM_MAC_ADDR_INDEX; i++)
+ random_mac_address_[i] = nullptr;
+}
std::array<uint8_t, 6> WifiIfaceUtil::getFactoryMacAddress(
const std::string& iface_name) {
@@ -53,22 +56,15 @@
bool WifiIfaceUtil::setMacAddress(const std::string& iface_name,
const std::array<uint8_t, 6>& mac) {
-#ifndef WIFI_AVOID_IFACE_RESET_MAC_CHANGE
- if (!iface_tool_.lock()->SetUpState(iface_name.c_str(), false)) {
- LOG(ERROR) << "SetUpState(false) failed.";
- return false;
- }
-#endif
if (!iface_tool_.lock()->SetMacAddress(iface_name.c_str(), mac)) {
LOG(ERROR) << "SetMacAddress failed.";
return false;
}
-#ifndef WIFI_AVOID_IFACE_RESET_MAC_CHANGE
- if (!iface_tool_.lock()->SetUpState(iface_name.c_str(), true)) {
- LOG(ERROR) << "SetUpState(true) failed.";
- return false;
- }
-#endif
+ LOG(DEBUG) << "Successfully SetMacAddress.";
+ return true;
+}
+
+void WifiIfaceUtil::onStateToggleOffOn(const std::string& iface_name) {
IfaceEventHandlers event_handlers = {};
const auto it = event_handlers_map_.find(iface_name);
if (it != event_handlers_map_.end()) {
@@ -77,17 +73,24 @@
if (event_handlers.on_state_toggle_off_on != nullptr) {
event_handlers.on_state_toggle_off_on(iface_name);
}
- LOG(DEBUG) << "Successfully SetMacAddress.";
- return true;
+}
+
+void WifiIfaceUtil::setRandomMacAddressIndex(int idx) {
+ if (idx >= MAX_RANDOM_MAC_ADDR_INDEX) {
+ LOG(ERROR) << "Requested random mac address index crossed max limit!!";
+ return;
+ }
+
+ random_mac_address_index_ = idx;
}
std::array<uint8_t, 6> WifiIfaceUtil::getOrCreateRandomMacAddress() {
- if (random_mac_address_) {
- return *random_mac_address_.get();
+ if (random_mac_address_[random_mac_address_index_]) {
+ return *random_mac_address_[random_mac_address_index_].get();
}
- random_mac_address_ =
+ random_mac_address_[random_mac_address_index_] =
std::make_unique<std::array<uint8_t, 6>>(createRandomMacAddress());
- return *random_mac_address_.get();
+ return *random_mac_address_[random_mac_address_index_].get();
}
void WifiIfaceUtil::registerIfaceEventHandlers(const std::string& iface_name,
diff --git a/wifi/1.4/default/wifi_iface_util.h b/wifi/1.4/default/wifi_iface_util.h
index 126b6ca..a7274a1 100644
--- a/wifi/1.4/default/wifi_iface_util.h
+++ b/wifi/1.4/default/wifi_iface_util.h
@@ -17,6 +17,8 @@
#ifndef WIFI_IFACE_UTIL_H_
#define WIFI_IFACE_UTIL_H_
+#define MAX_RANDOM_MAC_ADDR_INDEX 5
+
#include <wifi_system/interface_tool.h>
#include <android/hardware/wifi/1.0/IWifi.h>
@@ -52,18 +54,22 @@
// daemon. (So, changes on every reboot)
virtual std::array<uint8_t, 6> getOrCreateRandomMacAddress();
+ virtual void setRandomMacAddressIndex(int idx);
// Register for any iface event callbacks for the provided interface.
virtual void registerIfaceEventHandlers(const std::string& iface_name,
IfaceEventHandlers handlers);
virtual void unregisterIfaceEventHandlers(const std::string& iface_name);
virtual bool setUpState(const std::string& iface_name, bool request_up);
virtual unsigned ifNameToIndex(const std::string& iface_name);
+ virtual void onStateToggleOffOn(const std::string& iface_name);
private:
std::array<uint8_t, 6> createRandomMacAddress();
std::weak_ptr<wifi_system::InterfaceTool> iface_tool_;
- std::unique_ptr<std::array<uint8_t, 6>> random_mac_address_;
+ std::unique_ptr<std::array<uint8_t, 6>> random_mac_address_[MAX_RANDOM_MAC_ADDR_INDEX];
+
+ int random_mac_address_index_;
std::map<std::string, IfaceEventHandlers> event_handlers_map_;
};
diff --git a/wifi/1.4/default/wifi_legacy_hal.cpp b/wifi/1.4/default/wifi_legacy_hal.cpp
index 29123bf..5678848 100644
--- a/wifi/1.4/default/wifi_legacy_hal.cpp
+++ b/wifi/1.4/default/wifi_legacy_hal.cpp
@@ -36,7 +36,7 @@
static constexpr uint32_t kLinkLayerStatsDataMpduSizeThreshold = 128;
static constexpr uint32_t kMaxWakeReasonStatsArraySize = 32;
static constexpr uint32_t kMaxRingBuffers = 10;
-static constexpr uint32_t kMaxStopCompleteWaitMs = 100;
+static constexpr uint32_t kMaxStopCompleteWaitMs = 2000;
static constexpr char kDriverPropName[] = "wlan.driver.status";
// Helper function to create a non-const char* for legacy Hal API's.
@@ -367,8 +367,8 @@
}
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");
@@ -402,7 +402,7 @@
on_stop_complete_user_callback();
return WIFI_SUCCESS;
}
- LOG(DEBUG) << "Stopping legacy HAL";
+ LOG(ERROR) << "Stopping legacy HAL";
on_stop_complete_internal_callback = [on_stop_complete_user_callback,
this](wifi_handle handle) {
CHECK_EQ(global_handle_, handle) << "Handle mismatch";
@@ -411,10 +411,12 @@
// stopped.
invalidate();
iface_tool_.lock()->SetWifiUpState(false);
+ LOG(ERROR) << "SetWifiUpState(false) completed";
on_stop_complete_user_callback();
is_started_ = false;
};
awaiting_event_loop_termination_ = true;
+ LOG(ERROR) << "Legacy HAL trigger wifi cleanup";
global_func_table_.wifi_cleanup(global_handle_, onAsyncStopComplete);
const auto status = stop_wait_cv_.wait_for(
*lock, std::chrono::milliseconds(kMaxStopCompleteWaitMs),
@@ -1390,12 +1392,13 @@
void WifiLegacyHal::runEventLoop() {
LOG(DEBUG) << "Starting legacy HAL event loop";
global_func_table_.wifi_event_loop(global_handle_);
+ LOG(ERROR) << "Legacy HAL Wifi event loop exited";
const auto lock = hidl_sync_util::acquireGlobalLock();
if (!awaiting_event_loop_termination_) {
LOG(FATAL)
<< "Legacy HAL event loop terminated, but HAL was not stopping";
}
- LOG(DEBUG) << "Legacy HAL event loop terminated";
+ LOG(ERROR) << "Legacy HAL event loop terminated";
awaiting_event_loop_termination_ = false;
stop_wait_cv_.notify_one();
}
@@ -1459,6 +1462,10 @@
return status;
}
+wifi_error WifiLegacyHal::waitForDriverReady() {
+ return global_func_table_.wifi_wait_for_driver_ready();
+}
+
void WifiLegacyHal::invalidate() {
global_handle_ = nullptr;
iface_name_to_handle_.clear();
diff --git a/wifi/1.4/default/wifi_legacy_hal.h b/wifi/1.4/default/wifi_legacy_hal.h
index 9964460..03035ec 100644
--- a/wifi/1.4/default/wifi_legacy_hal.h
+++ b/wifi/1.4/default/wifi_legacy_hal.h
@@ -375,6 +375,8 @@
wifi_interface_type iftype);
virtual wifi_error deleteVirtualInterface(const std::string& ifname);
+ virtual wifi_error waitForDriverReady();
+
private:
// Retrieve interface handles for all the available interfaces.
wifi_error retrieveIfaceHandles();
diff --git a/wifi/1.4/default/wifi_nan_iface.cpp b/wifi/1.4/default/wifi_nan_iface.cpp
index 5764d35..24ffb17 100644
--- a/wifi/1.4/default/wifi_nan_iface.cpp
+++ b/wifi/1.4/default/wifi_nan_iface.cpp
@@ -534,6 +534,9 @@
}
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");
diff --git a/wifi/1.4/default/wifi_sta_iface.cpp b/wifi/1.4/default/wifi_sta_iface.cpp
index 49f383a..ee70461 100644
--- a/wifi/1.4/default/wifi_sta_iface.cpp
+++ b/wifi/1.4/default/wifi_sta_iface.cpp
@@ -625,7 +625,23 @@
WifiStatus WifiStaIface::setMacAddressInternal(
const std::array<uint8_t, 6>& mac) {
+#ifndef WIFI_AVOID_IFACE_RESET_MAC_CHANGE
+ if (!iface_util_.lock()->setUpState(ifname_, false)) {
+ return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+ }
+#endif
bool status = iface_util_.lock()->setMacAddress(ifname_, mac);
+#ifndef WIFI_AVOID_IFACE_RESET_MAC_CHANGE
+ if (!iface_util_.lock()->setUpState(ifname_, true)) {
+ LOG(INFO) << "Wait for driver ready and try to set iface UP again";
+ if (legacy_hal_.lock()->waitForDriverReady() !=
+ legacy_hal::WIFI_SUCCESS ||
+ !iface_util_.lock()->setUpState(ifname_, true)) {
+ return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+ }
+ }
+ iface_util_.lock()->onStateToggleOffOn(ifname_);
+#endif
if (!status) {
return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
}
diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
index d4063fe..75d6252 100644
--- a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
+++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
@@ -17,7 +17,6 @@
#include <android-base/logging.h>
#include <android/hidl/manager/1.0/IServiceManager.h>
-#include <android/hidl/manager/1.0/IServiceNotification.h>
#include <hidl/HidlTransportSupport.h>
#include <wifi_system/hostapd_manager.h>
@@ -39,7 +38,6 @@
using ::android::hardware::wifi::hostapd::V1_0::IHostapd;
using ::android::hardware::wifi::V1_0::ChipModeId;
using ::android::hardware::wifi::V1_0::IWifiChip;
-using ::android::hidl::manager::V1_0::IServiceNotification;
using ::android::wifi_system::HostapdManager;
using ::android::wifi_system::SupplicantManager;
@@ -47,68 +45,27 @@
// Helper function to initialize the driver and firmware to AP mode
// using the vendor HAL HIDL interface.
void initilializeDriverAndFirmware(const std::string& wifi_instance_name) {
- sp<IWifiChip> wifi_chip = getWifiChip(wifi_instance_name);
- ChipModeId mode_id;
- EXPECT_TRUE(configureChipToSupportIfaceType(
- wifi_chip, ::android::hardware::wifi::V1_0::IfaceType::AP, &mode_id));
+ if (getWifi(wifi_instance_name) != nullptr) {
+ sp<IWifiChip> wifi_chip = getWifiChip(wifi_instance_name);
+ ChipModeId mode_id;
+ EXPECT_TRUE(configureChipToSupportIfaceType(
+ wifi_chip, ::android::hardware::wifi::V1_0::IfaceType::AP, &mode_id));
+ } else {
+ LOG(WARNING) << __func__ << ": Vendor HAL not supported";
+ }
}
// Helper function to deinitialize the driver and firmware
// using the vendor HAL HIDL interface.
void deInitilializeDriverAndFirmware(const std::string& wifi_instance_name) {
- stopWifi(wifi_instance_name);
+ if (getWifi(wifi_instance_name) != nullptr) {
+ stopWifi(wifi_instance_name);
+ } else {
+ LOG(WARNING) << __func__ << ": Vendor HAL not supported";
+ }
}
} // namespace
-// Utility class to wait for wpa_hostapd's HIDL service registration.
-class ServiceNotificationListener : public IServiceNotification {
- public:
- Return<void> onRegistration(const hidl_string& fully_qualified_name,
- const hidl_string& instance_name,
- bool pre_existing) override {
- if (pre_existing) {
- return Void();
- }
- std::unique_lock<std::mutex> lock(mutex_);
- registered_.push_back(std::string(fully_qualified_name.c_str()) + "/" +
- instance_name.c_str());
- lock.unlock();
- condition_.notify_one();
- return Void();
- }
-
- bool registerForHidlServiceNotifications(const std::string& instance_name) {
- if (!IHostapd::registerForNotifications(instance_name, this)) {
- return false;
- }
- configureRpcThreadpool(2, false);
- return true;
- }
-
- bool waitForHidlService(uint32_t timeout_in_millis,
- const std::string& instance_name) {
- std::unique_lock<std::mutex> lock(mutex_);
- condition_.wait_for(lock, std::chrono::milliseconds(timeout_in_millis),
- [&]() { return registered_.size() >= 1; });
- if (registered_.size() != 1) {
- return false;
- }
- std::string expected_registered =
- std::string(IHostapd::descriptor) + "/" + instance_name;
- if (registered_[0] != expected_registered) {
- LOG(ERROR) << "Expected: " << expected_registered
- << ", Got: " << registered_[0];
- return false;
- }
- return true;
- }
-
- private:
- std::vector<std::string> registered_{};
- std::mutex mutex_;
- std::condition_variable condition_;
-};
-
void stopSupplicantIfNeeded(const std::string& instance_name) {
SupplicantManager supplicant_manager;
if (supplicant_manager.IsSupplicantRunning()) {
@@ -131,16 +88,11 @@
const std::string& hostapd_instance_name) {
initilializeDriverAndFirmware(wifi_instance_name);
- android::sp<ServiceNotificationListener> notification_listener =
- new ServiceNotificationListener();
- ASSERT_TRUE(notification_listener->registerForHidlServiceNotifications(
- hostapd_instance_name));
-
HostapdManager hostapd_manager;
ASSERT_TRUE(hostapd_manager.StartHostapd());
- ASSERT_TRUE(
- notification_listener->waitForHidlService(500, hostapd_instance_name));
+ // Wait for hostapd service to come up.
+ IHostapd::getService(hostapd_instance_name);
}
bool is_1_1(const sp<IHostapd>& hostapd) {
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 2715891..a39f064 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 @@
"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;
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 4f25465..47f0394 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 @@
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_hidl_test_utils.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
index 3815323..5e7a371 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
@@ -18,7 +18,6 @@
#include <cutils/properties.h>
#include <android/hidl/manager/1.0/IServiceManager.h>
-#include <android/hidl/manager/1.0/IServiceNotification.h>
#include <hidl/HidlTransportSupport.h>
#include <wifi_system/interface_tool.h>
@@ -45,7 +44,6 @@
using ::android::hardware::wifi::supplicant::V1_0::IfaceType;
using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
using ::android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
-using ::android::hidl::manager::V1_0::IServiceNotification;
using ::android::wifi_system::InterfaceTool;
using ::android::wifi_system::SupplicantManager;
@@ -58,11 +56,14 @@
if (wifi_instance_name == "") {
return;
}
-
- sp<IWifiChip> wifi_chip = getWifiChip(wifi_instance_name);
- ChipModeId mode_id;
- EXPECT_TRUE(configureChipToSupportIfaceType(
- wifi_chip, ::android::hardware::wifi::V1_0::IfaceType::STA, &mode_id));
+ if (getWifi(wifi_instance_name) != nullptr) {
+ sp<IWifiChip> wifi_chip = getWifiChip(wifi_instance_name);
+ ChipModeId mode_id;
+ EXPECT_TRUE(configureChipToSupportIfaceType(
+ wifi_chip, ::android::hardware::wifi::V1_0::IfaceType::STA, &mode_id));
+ } else {
+ LOG(WARNING) << __func__ << ": Vendor HAL not supported";
+ }
}
// Helper function to deinitialize the driver and firmware
@@ -72,8 +73,11 @@
if (wifi_instance_name == "") {
return;
}
-
- stopWifi(wifi_instance_name);
+ if (getWifi(wifi_instance_name) != nullptr) {
+ stopWifi(wifi_instance_name);
+ } else {
+ LOG(WARNING) << __func__ << ": Vendor HAL not supported";
+ }
}
// Helper function to find any iface of the desired type exposed.
@@ -114,55 +118,6 @@
}
} // namespace
-// Utility class to wait for wpa_supplicant's HIDL service registration.
-class ServiceNotificationListener : public IServiceNotification {
- public:
- Return<void> onRegistration(const hidl_string& fully_qualified_name,
- const hidl_string& instance_name,
- bool pre_existing) override {
- if (pre_existing) {
- return Void();
- }
- std::unique_lock<std::mutex> lock(mutex_);
- registered_.push_back(std::string(fully_qualified_name.c_str()) + "/" +
- instance_name.c_str());
- lock.unlock();
- condition_.notify_one();
- return Void();
- }
-
- bool registerForHidlServiceNotifications(const std::string& instance_name) {
- if (!ISupplicant::registerForNotifications(instance_name, this)) {
- return false;
- }
- configureRpcThreadpool(2, false);
- return true;
- }
-
- bool waitForHidlService(uint32_t timeout_in_millis,
- const std::string& instance_name) {
- std::unique_lock<std::mutex> lock(mutex_);
- condition_.wait_for(lock, std::chrono::milliseconds(timeout_in_millis),
- [&]() { return registered_.size() >= 1; });
- if (registered_.size() != 1) {
- return false;
- }
- std::string exptected_registered =
- std::string(ISupplicant::descriptor) + "/" + instance_name;
- if (registered_[0] != exptected_registered) {
- LOG(ERROR) << "Expected: " << exptected_registered
- << ", Got: " << registered_[0];
- return false;
- }
- return true;
- }
-
- private:
- std::vector<std::string> registered_{};
- std::mutex mutex_;
- std::condition_variable condition_;
-};
-
void stopSupplicant() { stopSupplicant(""); }
void stopSupplicant(const std::string& wifi_instance_name) {
@@ -178,17 +133,12 @@
const std::string& supplicant_instance_name) {
initilializeDriverAndFirmware(wifi_instance_name);
- android::sp<ServiceNotificationListener> notification_listener =
- new ServiceNotificationListener();
- ASSERT_TRUE(notification_listener->registerForHidlServiceNotifications(
- supplicant_instance_name));
-
SupplicantManager supplicant_manager;
ASSERT_TRUE(supplicant_manager.StartSupplicant());
ASSERT_TRUE(supplicant_manager.IsSupplicantRunning());
- ASSERT_TRUE(notification_listener->waitForHidlService(
- 500, supplicant_instance_name));
+ // Wait for supplicant service to come up.
+ ISupplicant::getService(supplicant_instance_name);
}
bool is_1_1(const sp<ISupplicant>& supplicant) {
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 8d6f38d..c333c4f 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 @@
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 @@
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 089b3cd..ff28754 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 @@
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 @@
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 5467e02..295ebfb 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 @@
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 @@
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 3629882..2104794 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 @@
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 @@
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 5ecfdd4..2a432d0 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 @@
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 @@
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 1eb8eea..cab160b 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 @@
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.2/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp
index f38dda4..7377f78 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 @@
}
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 @@
}
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 @@
}
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 4020298..011a955 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 @@
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 @@
virtual void TearDown() override {
stopSupplicant(wifi_v1_0_instance_name_);
+ // Start Framework
+ std::system("/system/bin/start");
}
int64_t pmkCacheExpirationTimeInSec;
@@ -419,7 +423,8 @@
}
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 +475,8 @@
}
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_network_hidl_test.cpp b/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp
index 25091a5..5f60746 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 @@
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 @@
virtual void TearDown() override {
stopSupplicant(wifi_v1_0_instance_name_);
+ // Start Framework
+ std::system("/system/bin/start");
}
protected: