Merge "Merge ab/12162526 into stage-aosp-rvc-ts-dev" into stage-aosp-rvc-ts-dev

This commit is contained in:
TreeHugger Robot
2020-07-16 17:39:00 +00:00
committed by Android (Google) Code Review
130 changed files with 4412 additions and 893 deletions

View File

@@ -3,6 +3,8 @@
hidl_interface {
name: "android.hardware.audio@4.0",
root: "android.hardware",
// TODO(b/153609531): remove when no longer needed.
native_bridge_supported: true,
vndk: {
enabled: true,
},

View File

@@ -3,6 +3,8 @@
hidl_interface {
name: "android.hardware.audio.common@2.0",
root: "android.hardware",
// TODO(b/153609531): remove when no longer needed.
native_bridge_supported: true,
vndk: {
enabled: true,
},

View File

@@ -3,6 +3,8 @@
hidl_interface {
name: "android.hardware.audio.common@4.0",
root: "android.hardware",
// TODO(b/153609531): remove when no longer needed.
native_bridge_supported: true,
vndk: {
enabled: true,
},

View File

@@ -3,6 +3,8 @@
hidl_interface {
name: "android.hardware.audio.effect@2.0",
root: "android.hardware",
// TODO(b/153609531): remove when no longer needed.
native_bridge_supported: true,
vndk: {
enabled: true,
},

View File

@@ -3,6 +3,8 @@
hidl_interface {
name: "android.hardware.audio.effect@4.0",
root: "android.hardware",
// TODO(b/153609531): remove when no longer needed.
native_bridge_supported: true,
vndk: {
enabled: true,
},

View File

@@ -105,6 +105,10 @@ enum EvsEventType : uint32_t {
* Master role has become available
*/
MASTER_RELEASED,
/**
* Any other erroneous streaming events
*/
STREAM_ERROR,
};
/**

View File

@@ -2262,6 +2262,7 @@ TEST_P(EvsHidlTest, CameraStreamExternalBuffering) {
// Allocate buffers to use
hidl_vec<BufferDesc> buffers;
buffers.resize(kBuffersToHold);
for (auto i = 0; i < kBuffersToHold; ++i) {
unsigned pixelsPerLine;
buffer_handle_t memHandle = nullptr;

View File

@@ -15,12 +15,10 @@
cc_defaults {
name: "vhal_v2_0_defaults",
shared_libs: [
"libbinder_ndk",
"libhidlbase",
"liblog",
"libutils",
"android.hardware.automotive.vehicle@2.0",
"carwatchdog_aidl_interface-ndk_platform",
],
cflags: [
"-Wall",
@@ -29,6 +27,15 @@ cc_defaults {
],
}
cc_defaults {
name: "vhal_v2_0_target_defaults",
defaults: ["vhal_v2_0_defaults"],
shared_libs: [
"libbinder_ndk",
"carwatchdog_aidl_interface-ndk_platform",
],
}
cc_library_headers {
name: "vhal_v2_0_common_headers",
vendor: true,
@@ -39,7 +46,7 @@ cc_library_headers {
cc_library {
name: "android.hardware.automotive.vehicle@2.0-manager-lib",
vendor: true,
defaults: ["vhal_v2_0_defaults"],
defaults: ["vhal_v2_0_target_defaults"],
srcs: [
"common/src/Obd2SensorStore.cpp",
"common/src/SubscriptionManager.cpp",
@@ -61,7 +68,7 @@ cc_library {
cc_library_static {
name: "android.hardware.automotive.vehicle@2.0-default-impl-lib",
vendor: true,
defaults: ["vhal_v2_0_defaults"],
defaults: ["vhal_v2_0_target_defaults"],
srcs: [
"impl/vhal_v2_0/CommConn.cpp",
"impl/vhal_v2_0/EmulatedVehicleConnector.cpp",
@@ -97,16 +104,59 @@ cc_library_static {
cc_library_static {
name: "android.hardware.automotive.vehicle@2.0-emulated-user-hal-lib",
vendor: true,
defaults: ["vhal_v2_0_defaults"],
defaults: ["vhal_v2_0_target_defaults"],
srcs: [
"impl/vhal_v2_0/EmulatedUserHal.cpp",
],
}
// Vehicle HAL Server reference impl lib
cc_library_static {
name: "android.hardware.automotive.vehicle@2.0-server-common-lib",
vendor: true,
host_supported: true,
defaults: ["vhal_v2_0_defaults"],
local_include_dirs: ["common/include/vhal_v2_0"],
export_include_dirs: ["common/include"],
srcs: [
"common/src/Obd2SensorStore.cpp",
"common/src/VehicleObjectPool.cpp",
"common/src/VehicleUtils.cpp",
],
}
// Vehicle HAL Server default implementation
cc_library_static {
name: "android.hardware.automotive.vehicle@2.0-server-impl-lib",
vendor: true,
host_supported: true,
defaults: ["vhal_v2_0_defaults"],
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",
"impl/vhal_v2_0/ProtoMessageConverter.cpp",
"impl/vhal_v2_0/VehicleHalServer.cpp",
],
whole_static_libs: [
"android.hardware.automotive.vehicle@2.0-server-common-lib",
],
static_libs: [
"android.hardware.automotive.vehicle@2.0-libproto-native",
],
shared_libs: [
"libbase",
"libjsoncpp",
],
}
cc_test {
name: "android.hardware.automotive.vehicle@2.0-manager-unit-tests",
vendor: true,
defaults: ["vhal_v2_0_defaults"],
defaults: ["vhal_v2_0_target_defaults"],
whole_static_libs: ["android.hardware.automotive.vehicle@2.0-manager-lib"],
srcs: [
"tests/RecurrentTimer_test.cpp",
@@ -126,7 +176,7 @@ cc_test {
cc_test {
name: "android.hardware.automotive.vehicle@2.0-default-impl-unit-tests",
vendor: true,
defaults: ["vhal_v2_0_defaults"],
defaults: ["vhal_v2_0_target_defaults"],
srcs: [
"impl/vhal_v2_0/tests/ProtoMessageConverter_test.cpp",
],
@@ -140,7 +190,7 @@ cc_test {
cc_binary {
name: "android.hardware.automotive.vehicle@2.0-service",
defaults: ["vhal_v2_0_defaults"],
defaults: ["vhal_v2_0_target_defaults"],
vintf_fragments: [
"android.hardware.automotive.vehicle@2.0-service.xml",
],

View File

@@ -1036,6 +1036,22 @@ const ConfigDeclaration kVehicleProperties[]{
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
},
},
{
.config =
{
.prop = toInt(VehicleProperty::CREATE_USER),
.access = VehiclePropertyAccess::READ_WRITE,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
},
},
{
.config =
{
.prop = toInt(VehicleProperty::REMOVE_USER),
.access = VehiclePropertyAccess::READ_WRITE,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
},
},
{
.config =
{

View File

@@ -30,6 +30,8 @@ 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);
@@ -37,6 +39,8 @@ bool EmulatedUserHal::isSupported(int32_t prop) {
switch (prop) {
case INITIAL_USER_INFO:
case SWITCH_USER:
case CREATE_USER:
case REMOVE_USER:
case USER_IDENTIFICATION_ASSOCIATION:
return true;
default:
@@ -53,6 +57,11 @@ android::base::Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetP
return onSetInitialUserInfoResponse(value);
case SWITCH_USER:
return onSetSwitchUserResponse(value);
case CREATE_USER:
return onSetCreateUserResponse(value);
case REMOVE_USER:
ALOGI("REMOVE_USER is FYI only, nothing to do...");
return {};
case USER_IDENTIFICATION_ASSOCIATION:
return onSetUserIdentificationAssociation(value);
default:
@@ -62,32 +71,44 @@ android::base::Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetP
}
android::base::Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onGetProperty(
int32_t prop) {
ALOGV("onGetProperty(%d)", prop);
switch (prop) {
const VehiclePropValue& value) {
ALOGV("onGetProperty(%s)", toString(value).c_str());
switch (value.prop) {
case INITIAL_USER_INFO:
case SWITCH_USER:
ALOGE("onGetProperty(): %d is only supported on SET", prop);
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";
case USER_IDENTIFICATION_ASSOCIATION:
if (mSetUserIdentificationAssociationResponseFromCmd != nullptr) {
ALOGI("onGetProperty(%d): returning %s", prop,
toString(*mSetUserIdentificationAssociationResponseFromCmd).c_str());
auto value = std::unique_ptr<VehiclePropValue>(
new VehiclePropValue(*mSetUserIdentificationAssociationResponseFromCmd));
return value;
}
ALOGE("onGetProperty(%d): USER_IDENTIFICATION_ASSOCIATION not set by lshal", prop);
return android::base::Error(static_cast<int>(StatusCode::NOT_AVAILABLE))
<< "not set by lshal";
return onGetUserIdentificationAssociation(value);
default:
ALOGE("onGetProperty(): %d is not supported", prop);
ALOGE("onGetProperty(): %d is not supported", value.prop);
return android::base::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));
// Must use the same requestId
if (value.value.int32Values.size() > 0) {
newValue->value.int32Values[0] = value.value.int32Values[0];
} else {
ALOGE("get(USER_IDENTIFICATION_ASSOCIATION): no requestId on %s",
toString(value).c_str());
}
return newValue;
}
return defaultUserIdentificationAssociation(value);
}
android::base::Result<std::unique_ptr<VehiclePropValue>>
EmulatedUserHal::onSetInitialUserInfoResponse(const VehiclePropValue& value) {
if (value.value.int32Values.size() == 0) {
@@ -147,6 +168,20 @@ android::base::Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetS
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;
}
}
// Returns default response
auto updatedValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue);
updatedValue->prop = SWITCH_USER;
@@ -162,6 +197,41 @@ android::base::Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetS
return updatedValue;
}
android::base::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);
}
if (value.areaId != 0) {
ALOGD("set(CREATE_USER) called from lshal; storing it: %s", toString(value).c_str());
mCreateUserResponseFromCmd.reset(new VehiclePropValue(value));
return {};
}
ALOGD("set(CREATE_USER) called from Android: %s", toString(value).c_str());
int32_t requestId = value.value.int32Values[0];
if (mCreateUserResponseFromCmd != nullptr) {
ALOGI("replying CREATE_USER with lshal value: %s",
toString(*mCreateUserResponseFromCmd).c_str());
return sendUserHalResponse(std::move(mCreateUserResponseFromCmd), requestId);
}
// Returns default response
auto updatedValue = std::unique_ptr<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;
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) {
@@ -190,16 +260,14 @@ EmulatedUserHal::onSetUserIdentificationAssociation(const VehiclePropValue& valu
}
// Returns default response
auto updatedValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue);
updatedValue->prop = USER_IDENTIFICATION_ASSOCIATION;
updatedValue->timestamp = elapsedRealtimeNano();
updatedValue->value.int32Values.resize(1);
updatedValue->value.int32Values[0] = requestId;
updatedValue->value.stringValue = "Response not set by LSHAL";
return defaultUserIdentificationAssociation(value);
}
ALOGI("no lshal response; replying with an error message: %s", toString(*updatedValue).c_str());
return updatedValue;
android::base::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";
}
android::base::Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::sendUserHalResponse(
@@ -247,6 +315,12 @@ void EmulatedUserHal::dump(int fd, std::string indent) {
} else {
dprintf(fd, "%sNo SwitchUser response\n", indent.c_str());
}
if (mCreateUserResponseFromCmd != nullptr) {
dprintf(fd, "%sCreateUser response: %s\n", indent.c_str(),
toString(*mCreateUserResponseFromCmd).c_str());
} else {
dprintf(fd, "%sNo CreateUser response\n", indent.c_str());
}
if (mSetUserIdentificationAssociationResponseFromCmd != nullptr) {
dprintf(fd, "%sSetUserIdentificationAssociation response: %s\n", indent.c_str(),
toString(*mSetUserIdentificationAssociationResponseFromCmd).c_str());

View File

@@ -58,7 +58,8 @@ class EmulatedUserHal {
*
* @return property value and StatusCode
*/
android::base::Result<std::unique_ptr<VehiclePropValue>> onGetProperty(int32_t prop);
android::base::Result<std::unique_ptr<VehiclePropValue>> onGetProperty(
const VehiclePropValue& value);
/**
* Shows the User HAL emulation help.
@@ -105,17 +106,37 @@ class EmulatedUserHal {
const VehiclePropValue& value);
/**
* Used to emulate USER_IDENTIFICATION_ASSOCIATION - see onSetInitialUserInfoResponse() for
* Used to emulate CREATE_USER - see onSetInitialUserInfoResponse() for usage.
*/
android::base::Result<std::unique_ptr<VehiclePropValue>> onSetCreateUserResponse(
const VehiclePropValue& value);
/**
* Used to emulate set USER_IDENTIFICATION_ASSOCIATION - see onSetInitialUserInfoResponse() for
* usage.
*/
android::base::Result<std::unique_ptr<VehiclePropValue>> onSetUserIdentificationAssociation(
const VehiclePropValue& value);
/**
* Used to emulate get USER_IDENTIFICATION_ASSOCIATION - see onSetInitialUserInfoResponse() for
* usage.
*/
android::base::Result<std::unique_ptr<VehiclePropValue>> onGetUserIdentificationAssociation(
const VehiclePropValue& value);
/**
* Creates a default USER_IDENTIFICATION_ASSOCIATION when it was not set by lshal.
*/
android::base::Result<std::unique_ptr<VehiclePropValue>> defaultUserIdentificationAssociation(
const VehiclePropValue& request);
android::base::Result<std::unique_ptr<VehiclePropValue>> sendUserHalResponse(
std::unique_ptr<VehiclePropValue> response, int32_t requestId);
std::unique_ptr<VehiclePropValue> mInitialUserResponseFromCmd;
std::unique_ptr<VehiclePropValue> mSwitchUserResponseFromCmd;
std::unique_ptr<VehiclePropValue> mCreateUserResponseFromCmd;
std::unique_ptr<VehiclePropValue> mSetUserIdentificationAssociationResponseFromCmd;
};

View File

@@ -153,7 +153,7 @@ VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::get(
default:
if (mEmulatedUserHal != nullptr && mEmulatedUserHal->isSupported(propId)) {
ALOGI("get(): getting value for prop %d from User HAL", propId);
const auto& ret = mEmulatedUserHal->onGetProperty(propId);
const auto& ret = mEmulatedUserHal->onGetProperty(requestedPropValue);
if (!ret.ok()) {
ALOGE("get(): User HAL returned error: %s", ret.error().message().c_str());
*outStatus = StatusCode(ret.error().code());

View File

@@ -16,6 +16,7 @@
cc_library_static {
name: "android.hardware.automotive.vehicle@2.0-libproto-native",
vendor: true,
host_supported: true,
proto: {
export_proto_headers: true,
type: "lite",

View File

@@ -2532,23 +2532,23 @@ enum VehicleProperty : int32_t {
*
* int32[0]: 42 // must match the request id from the request
* int32[1]: 2 // action = InitialUserInfoResponseAction::CREATE
* int32[2]: -1 // userToSwitchOrCreate.userId (not used as user will be created)
* int32[2]: -10000 // userToSwitchOrCreate.userId (not used as user will be created)
* int32[3]: 8 // userToSwitchOrCreate.flags = ADMIN
* string: "||Owner" // userLocales + separator + userNameToCreate
* string: "||Owner" // userLocales + separator + userNameToCreate
*
* Notice the string value represents multiple values, separated by ||. The first value is the
* (optional) system locales for the user to be created (in this case, it's empty, meaning it
* will use Android's default value), while the second value is the (also optional) name of the
* to user to be created (when the type of response is InitialUserInfoResponseAction:CREATE).
* For example, to create the same "Owner" user with "en-US" and "pt-BR" locales, the string
* value of the response would be "en-US,pt-BR||Owner".
* value of the response would be "en-US,pt-BR||Owner". As such, neither the locale nor the
* name can have || on it, although a single | is fine.
*
* NOTE: if the HAL doesn't support user management, then it should not define this property,
* which in turn would disable the other user-related properties (for example, the Android
* system would never issue them and user-related requests from the HAL layer would be ignored
* by the Android System). But if it supports user management, then it must support all
* user-related properties (INITIAL_USER_INFO, SWITCH_USER, CREATE_USER, REMOVE_USER,
* and USER_IDENTIFICATION_ASSOCIATION).
* by the Android System). But if it supports user management, then it must support all core
* user-related properties (INITIAL_USER_INFO, SWITCH_USER, CREATE_USER, and REMOVE_USER).
*
* @change_mode VehiclePropertyChangeMode:ON_CHANGE
* @access VehiclePropertyAccess:READ_WRITE
@@ -2627,7 +2627,7 @@ enum VehicleProperty : int32_t {
* int32[5]: 0 // current user flags (none)
* int32[6]: 3 // number of users
* int32[7]: 0 // 1st user (user 0)
* int32[8]: 0 // 1st user flags (none)
* int32[8]: 1 // 1st user flags (SYSTEM)
* int32[9]: 10 // 2nd user (user 10)
* int32[10]: 0 // 2nd user flags (none)
* int32[11]: 11 // 3rd user (user 11)
@@ -2661,7 +2661,7 @@ enum VehicleProperty : int32_t {
* identified the user as A.
*
* The HAL makes this request by a property change event (passing a negative request id), and
* the Android system will response by issuye an ANDROID_POST_SWITCH call which the same
* the Android system will response by issue an ANDROID_POST_SWITCH call which the same
* request id.
*
* For example, if the current foreground Android user is 10 and the HAL asked it to switch to
@@ -2705,7 +2705,7 @@ enum VehicleProperty : int32_t {
* in the response are different (as the current user didn't change to the target).
* 3. If a new switch request is made before the HAL responded to the previous one or before
* the user was unlocked, then the ANDROID_POST_SWITCH request is not made. For example,
* the driver could accidentally switch to the wrong user which has lock crentials, then
* the driver could accidentally switch to the wrong user which has lock credentials, then
* switch to the right one before entering the credentials.
*
* The HAL can update its internal state once it receives this request, but it doesn't need to
@@ -2818,6 +2818,10 @@ enum VehicleProperty : int32_t {
* Property used to associate (or query the association) the current user with vehicle-specific
* identification mechanisms (such as key FOB).
*
* This is an optional user management property - the OEM could still support user management
* without defining it. In fact, this property could be used without supporting the core
* user-related functions described on INITIAL_USER_INFO.
*
* To query the association, the Android system gets the property, passing a VehiclePropValue
* containing the types of associations are being queried, as defined by
* UserIdentificationGetRequest. The HAL must return right away, returning a VehiclePropValue
@@ -4277,6 +4281,16 @@ enum UserFlags: int32_t {
* Admin users have additional privileges such as permission to create other users.
*/
ADMIN = 0x08,
/**
* Disabled users are marked for deletion.
*/
DISABLED = 0x10,
/**
* Profile user is a profile of another user.
*/
PROFILE = 0x20,
};
/**
@@ -4291,10 +4305,16 @@ struct UsersInfo {
/** The current foreground user. */
UserInfo currentUser;
/** Number of existing users (includes the current user). */
/**
* Number of existing users; includes the current user, recently removed users (with DISABLED
* flag), and profile users (with PROFILE flag).
*/
int32_t numberUsers;
/** List of existing users (includes the current user). */
/**
* List of existing users; includes the current user, recently removed users (with DISABLED
* flag), and profile users (with PROFILE flag).
*/
vec<UserInfo> existingUsers;
};
@@ -4370,16 +4390,16 @@ struct InitialUserInfoResponse {
*/
UserInfo userToSwitchOrCreate;
/**
* Name of the user that should be created.
*/
string userNameToCreate;
/**
* System locales of the initial user (value will be passed as-is to
* android.provider.Settings.System.SYSTEM_LOCALES)
*/
string userLocales;
/**
* Name of the user that should be created.
*/
string userNameToCreate;
};
/**

View File

@@ -28,6 +28,7 @@
#include <chrono>
#include <cstdint>
#include <random>
#include <thread>
using android::sp;
using android::hardware::hidl_vec;
@@ -144,7 +145,10 @@ class FaceHidlTest : public ::testing::TestWithParam<std::string> {
ASSERT_EQ(Status::OK, static_cast<Status>(ret2));
}
void TearDown() override {}
void TearDown() override {
// Hack to allow the asynchronous operations to finish on time.
std::this_thread::sleep_for(std::chrono::milliseconds(250));
}
sp<IBiometricsFace> mService;
sp<FaceCallback> mCallback;

View File

@@ -49,7 +49,7 @@ static const uint32_t kTimeout = 3;
static const std::chrono::seconds kTimeoutInSeconds = std::chrono::seconds(kTimeout);
static const uint32_t kGroupId = 99;
static std::string kTmpDir = "";
static const uint32_t kIterations = 1000;
static const uint32_t kIterations = 10;
// Wait for a callback to occur (signaled by the given future) up to the
// provided timeout. If the future is invalid or the callback does not come

View File

@@ -26,4 +26,5 @@ cc_test {
"general-tests",
"vts",
],
disable_framework: true,
}

View File

@@ -87,15 +87,19 @@ interface ICameraDeviceCallback {
* ERROR_RESULT message.
*
* If an output buffer cannot be filled, its status field must be set to
* STATUS_ERROR. In addition, notify() must be called with a ERROR_BUFFER
* message.
* STATUS_ERROR. In this case, notify() isn't required to be called with
* an ERROR_BUFFER message. The framework will simply treat the notify()
* call with ERROR_BUFFER as a no-op, and derive whether and when to notify
* the application of buffer loss based on the buffer status and whether or not
* the entire capture has failed.
*
* If the entire capture has failed, then this method still needs to be
* called to return the output buffers to the framework. All the buffer
* statuses must be STATUS_ERROR, and the result metadata must be an
* empty buffer. In addition, notify() must be called with a ERROR_REQUEST
* message. In this case, individual ERROR_RESULT/ERROR_BUFFER messages
* must not be sent.
* must not be sent. Note that valid partial results are still allowed
* as long as the final result metadata fails to be generated.
*
* Performance requirements:
*

View File

@@ -38,7 +38,7 @@ bool convertFromHidl(const CameraMetadata &src, const camera_metadata_t** dst) {
}
const uint8_t* data = src.data();
// sanity check the size of CameraMetadata match underlying camera_metadata_t
// check that the size of CameraMetadata match underlying camera_metadata_t
if (get_camera_metadata_size((camera_metadata_t*)data) != src.size()) {
ALOGE("%s: input CameraMetadata is corrupt!", __FUNCTION__);
return false;

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<configuration description="Runs VtsHalCameraProviderV2_4TargetTest.">
<option name="test-suite-tag" value="apct" />
<option name="test-suite-tag" value="apct-native" />
<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="VtsHalCameraProviderV2_4TargetTest->/data/local/tmp/VtsHalCameraProviderV2_4TargetTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="VtsHalCameraProviderV2_4TargetTest" />
<option name="native-test-timeout" value="1800000"/> <!-- 30 min -->
</test>
</configuration>

View File

@@ -843,7 +843,7 @@ public:
void verifyRequestTemplate(const camera_metadata_t* metadata, RequestTemplate requestTemplate);
bool isDepthOnly(camera_metadata_t* staticMeta);
static bool isDepthOnly(const camera_metadata_t* staticMeta);
static Status getAvailableOutputStreams(const camera_metadata_t *staticMeta,
std::vector<AvailableStream> &outputStreams,
@@ -1894,7 +1894,7 @@ TEST_P(CameraHidlTest, getCameraDeviceInterface) {
}
// Verify that the device resource cost can be retrieved and the values are
// sane.
// correct.
TEST_P(CameraHidlTest, getResourceCost) {
hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
@@ -2544,7 +2544,7 @@ TEST_P(CameraHidlTest, sendCommandSmoothZoom) {
}
}
// Basic sanity tests related to camera parameters.
// Basic correctness tests related to camera parameters.
TEST_P(CameraHidlTest, getSetParameters) {
hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
@@ -5537,9 +5537,22 @@ static Size getMinSize(Size a, Size b) {
// TODO: Add more combinations
Status CameraHidlTest::getMandatoryConcurrentStreams(const camera_metadata_t* staticMeta,
std::vector<AvailableStream>* outputStreams) {
if (nullptr == staticMeta) {
if (nullptr == staticMeta || nullptr == outputStreams) {
return Status::ILLEGAL_ARGUMENT;
}
if (isDepthOnly(staticMeta)) {
Size y16MaxSize(640, 480);
Size maxAvailableY16Size;
getMaxOutputSizeForFormat(staticMeta, PixelFormat::Y16, &maxAvailableY16Size);
Size y16ChosenSize = getMinSize(y16MaxSize, maxAvailableY16Size);
AvailableStream y16Stream = {.width = y16ChosenSize.width,
.height = y16ChosenSize.height,
.format = static_cast<int32_t>(PixelFormat::Y16)};
outputStreams->push_back(y16Stream);
return Status::OK;
}
Size yuvMaxSize(1280, 720);
Size jpegMaxSize(1920, 1440);
Size maxAvailableYuvSize;
@@ -6296,7 +6309,7 @@ void CameraHidlTest::configureOfflineStillStream(const std::string &name,
ASSERT_TRUE(ret.isOk());
}
bool CameraHidlTest::isDepthOnly(camera_metadata_t* staticMeta) {
bool CameraHidlTest::isDepthOnly(const camera_metadata_t* staticMeta) {
camera_metadata_ro_entry scalarEntry;
camera_metadata_ro_entry depthEntry;

View File

@@ -61,6 +61,12 @@ interface ICameraProvider extends @2.5::ICameraProvider {
* outputs, stream combinations mentioned above, where YUV is substituted by
* Y8 must be also supported.
*
* Devices whose capabilities do not include
* ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE, must support
* at least a single Y16 stream, Dataspace::DEPTH with sVGA resolution,
* during concurrent operation.
* Where sVGA - min (max output resolution for the given format, 640 X 480)
*
* The camera framework must call this method whenever it gets a
* cameraDeviceStatusChange callback adding a new camera device or removing
* a camera device known to it. This is so that the camera framework can get new combinations
@@ -76,12 +82,16 @@ interface ICameraProvider extends @2.5::ICameraProvider {
* configuration settings exposed through camera metadata), should the sum
* of resource costs for the combination be <= 100.
*
* The lists of camera id combinations returned by this method may contain
* hidden physical camera ids. If a combination does contain hidden physical
* camera ids, the camera framework must be able to open any logical cameras
* that contain these hidden physical camera ids in their
* ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS list, in addition to the other
* camera ids advertised in the combination, for concurrent operation.
* For guaranteed concurrent camera operation, the camera framework must call
* ICameraDevice.open() on all devices (intended for concurrent operation), before configuring
* any streams on them. This gives the camera HAL process an opportunity to potentially
* distribute hardware resources better before stream configuration.
*
* Due to potential hardware constraints around internal switching of physical camera devices,
* a device's complete ZOOM_RATIO_RANGE(if supported), may not apply during concurrent
* operation. If ZOOM_RATIO is supported, camera HALs must ensure ZOOM_RATIO_RANGE of
* [1.0, ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM] is supported by that device, during
* concurrent operation.
*
* @return status Status code for the operation
* @return cameraIds a list of camera id combinations that support

View File

@@ -588,6 +588,7 @@ c3ec182ce325862b7d79e526f3e170c02cfee1497ed309d7c60d0de4ca636b0b android.hardwar
578f640c653726d58f99c84a7e1bb63862e21ef7cbb4f7d95c3cc62de00dca35 android.hardware.automotive.evs@1.0::IEvsDisplay
f5bc6aa840db933cb9fd36668b06d3e2021cf5384bb70e459f22e2f2f921fba5 android.hardware.automotive.evs@1.0::IEvsEnumerator
d3a344b7bd4c0d2658ae7209f55a979b8f53f361fd00f4fca29d5baa56d11fd2 android.hardware.automotive.evs@1.0::types
2924c3e43858190ee3e2da4c2fb93bba8ae065fe314451f035a7ec52cb80c94a android.hardware.camera.device@3.2::ICameraDeviceCallback # b/155353799
2410dd02d67786a732d36e80b0f8ccf55086604ef37f9838e2013ff2c571e404 android.hardware.camera.device@3.5::types
cd06a7911b9acd4a653bbf7133888878fbcb3f84be177c7a3f1becaae3d8618f android.hardware.camera.metadata@3.2::types
5cf81b1001296fbb3c5b3d275a859244f61cec5fa858d7be9cca46c5b7dfa733 android.hardware.camera.metadata@3.2::types # b/150331548
@@ -657,7 +658,7 @@ ca515ff4b63c80cf5ad7b3395c997c57d6c56157361f6c367d1c96f23cc4860a android.hardwar
87958d728d7c0ee9b9391ab4a072b097914921a7b38f7dc3df427f933a5b528e android.hardware.automotive.evs@1.1::IEvsEnumerator
f53b4e8de6209c6d0fa9036005671b34a2f98328b51423d3a5137a43bf42c84d android.hardware.automotive.evs@1.1::IEvsUltrasonicsArray
0460bacbde906a846a3d71b2b7b33d6927cac3ff072e523ffac7853577464406 android.hardware.automotive.evs@1.1::IEvsUltrasonicsArrayStream
3e374b5c4777f959f62a320abb3b9edca8874e24e383dbb19c66d224f151b363 android.hardware.automotive.evs@1.1::types
f27cf8283e7b953d33dd258734749d2fca9cc63502ea41353060ffa78d8ce9f6 android.hardware.automotive.evs@1.1::types
4e4904c4067dadae974ddf90351f362331dcd04bba1d890d313cc8ba91f68c15 android.hardware.automotive.sv@1.0::ISurroundView2dSession
63336e9d03f545020ff2982ff76d9d8c44fa76ad476293b5ef6732cbbd71e61b android.hardware.automotive.sv@1.0::ISurroundView3dSession
b7015428cd52ce8192d13bfcbf2c4455cda3727d57f2aac80d65a1747104f5ac android.hardware.automotive.sv@1.0::ISurroundViewService
@@ -676,7 +677,7 @@ eb90c4d366f05a025d1d1a3672f8b4c3e33e420fa387f73f21b264645bfdf845 android.hardwar
a718c8a3acaa938de5a57923e8c4625ed7ca051e05a1d930ba6998557d7b57c8 android.hardware.camera.device@3.6::ICameraOfflineSession
a35d5151b48505f06a775b38c0e2e265f80a845d92802324c643565807f81c53 android.hardware.camera.device@3.6::types
02bdf82dba7dce273a554b4474468a8fb1fb4f61ab65da95eb16e080df63fff6 android.hardware.camera.metadata@3.5::types
21086e1c7a2acc0ebe0ff8561b11f3c2009be687a92d79b608a5f00b16c5f598 android.hardware.camera.provider@2.6::ICameraProvider
93cd94e47b22007bbf436c2f5c2703bb7b2859d1b714d6ae15520db55667ba6c android.hardware.camera.provider@2.6::ICameraProvider
8f8d9463508ff9cae88eb35c429fd0e2dbca0ca8f5de7fdf836cc0c4370becb6 android.hardware.camera.provider@2.6::ICameraProviderCallback
1edf7aef68ef3bd577a1175b1462fb82e3e39f01c6915dda61fba121028df283 android.hardware.camera.provider@2.6::types
c1aa508d00b66ed5feefea398fd5edf28fa651ac89773adad7dfda4e0a73a952 android.hardware.cas@1.2::ICas
@@ -721,6 +722,7 @@ ee9dc34b9925b8367b1111c72bd6d9d375432735e451572ca5a665d8516a7744 android.hardwar
eee3430cc86c97c7b407495863d8fb61da6f1a64b7721e77b9b4909b11b174e9 android.hardware.neuralnetworks@1.3::IPreparedModelCallback
acf84925f8ee0a651f2ec547ac334034de266479b93af5434f6c1f25e66aba96 android.hardware.neuralnetworks@1.3::types
e9080d04218e98512b63aace9ff3da52f0130238391f15cbbf7df396a3ec9072 android.hardware.neuralnetworks@1.3::types # b/155508675, b/155662254, b/155238914, b/155660285
583dc88b41e702e940fd954edda1beb8b4151eab55a5c6d7e69e2781bce84b59 android.hardware.neuralnetworks@1.3::types # b/156918813
b454df853441c12f6e425e8a60dd29fda20f5e6e39b93d1103e4b37495db38aa android.hardware.radio@1.5::IRadio
fcbb0742a88215ee7a6d7ce0825d253eb2b50391fc6c8c48667f9fd7f6d4549e android.hardware.radio@1.5::IRadioIndication
b809193970a91ca637a4b0184767315601d32e3ef3d5992ffbc7a8d14a14f015 android.hardware.radio@1.5::IRadioResponse

View File

@@ -25,6 +25,7 @@ cc_test {
static_libs: [
"android.hardware.gnss@1.0",
"android.hardware.gnss@1.1",
"android.hardware.gnss@2.0",
"android.hardware.gnss@common-vts-lib",
],
shared_libs: [

View File

@@ -247,3 +247,46 @@ Return<void> GnssHalTest::GnssMeasurementCorrectionsCallback::setCapabilitiesCb(
capabilities_cbq_.store(capabilities);
return Void();
}
GnssConstellationType_1_0 GnssHalTest::startLocationAndGetNonGpsConstellation() {
const int kLocationsToAwait = 3;
gnss_cb_->location_cbq_.reset();
StartAndCheckLocations(kLocationsToAwait);
const int location_called_count = gnss_cb_->location_cbq_.calledCount();
// Tolerate 1 less sv status to handle edge cases in reporting.
int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations (%d received)",
sv_info_list_cbq_size, kLocationsToAwait, location_called_count);
// Find first non-GPS constellation to blacklist. Exclude IRNSS in GnssConstellationType_2_0
// as blacklisting of this constellation is not supported in gnss@2.0.
const int kGnssSvStatusTimeout = 2;
GnssConstellationType_1_0 constellation_to_blacklist = GnssConstellationType_1_0::UNKNOWN;
for (int i = 0; i < sv_info_list_cbq_size; ++i) {
hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
if ((sv_info.v1_0.svFlag & IGnssCallback_2_0::GnssSvFlags::USED_IN_FIX) &&
(sv_info.constellation != GnssConstellationType_2_0::UNKNOWN) &&
(sv_info.constellation != GnssConstellationType_2_0::IRNSS) &&
(sv_info.constellation != GnssConstellationType_2_0::GPS)) {
// found a non-GPS V1_0 constellation
constellation_to_blacklist = Utils::mapConstellationType(sv_info.constellation);
break;
}
}
if (constellation_to_blacklist != GnssConstellationType_1_0::UNKNOWN) {
break;
}
}
if (constellation_to_blacklist == GnssConstellationType_1_0::UNKNOWN) {
ALOGI("No non-GPS constellations found, constellation blacklist test less effective.");
// Proceed functionally to blacklist something.
constellation_to_blacklist = GnssConstellationType_1_0::GLONASS;
}
return constellation_to_blacklist;
}

View File

@@ -31,6 +31,9 @@ using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrec
using android::hardware::gnss::V1_0::GnssLocationFlags;
using android::hardware::gnss::V2_0::IGnss;
using GnssConstellationType_1_0 = android::hardware::gnss::V1_0::GnssConstellationType;
using GnssConstellationType_2_0 = android::hardware::gnss::V2_0::GnssConstellationType;
using GnssLocation_1_0 = android::hardware::gnss::V1_0::GnssLocation;
using GnssLocation_2_0 = android::hardware::gnss::V2_0::GnssLocation;
@@ -194,6 +197,16 @@ class GnssHalTest : public testing::TestWithParam<std::string> {
*/
void SetPositionMode(const int min_interval_msec, const bool low_power_mode);
/*
* startLocationAndGetNonGpsConstellation:
* 1. Start location
* 2. Find and return first non-GPS constellation
*
* Note that location is not stopped in this method. The client should call
* StopAndClearLocations() after the call.
*/
GnssConstellationType_1_0 startLocationAndGetNonGpsConstellation();
sp<IGnss> gnss_hal_; // GNSS HAL to call into
sp<GnssCallback> gnss_cb_; // Primary callback interface
};

View File

@@ -24,8 +24,6 @@
using android::hardware::hidl_string;
using android::hardware::hidl_vec;
using GnssConstellationType_2_0 = android::hardware::gnss::V2_0::GnssConstellationType;
using GnssConstellationType_1_0 = android::hardware::gnss::V1_0::GnssConstellationType;
using IGnssConfiguration_2_0 = android::hardware::gnss::V2_0::IGnssConfiguration;
using IGnssConfiguration_1_1 = android::hardware::gnss::V1_1::IGnssConfiguration;
using IAGnssRil_2_0 = android::hardware::gnss::V2_0::IAGnssRil;
@@ -491,31 +489,6 @@ TEST_P(GnssHalTest, GetLocationLowPower) {
StopAndClearLocations();
}
/*
* MapConstellationType:
* Given a GnssConstellationType_2_0 type constellation, maps to its equivalent
* GnssConstellationType_1_0 type constellation. For constellations that do not have
* an equivalent value, maps to GnssConstellationType_1_0::UNKNOWN
*/
GnssConstellationType_1_0 MapConstellationType(GnssConstellationType_2_0 constellation) {
switch (constellation) {
case GnssConstellationType_2_0::GPS:
return GnssConstellationType_1_0::GPS;
case GnssConstellationType_2_0::SBAS:
return GnssConstellationType_1_0::SBAS;
case GnssConstellationType_2_0::GLONASS:
return GnssConstellationType_1_0::GLONASS;
case GnssConstellationType_2_0::QZSS:
return GnssConstellationType_1_0::QZSS;
case GnssConstellationType_2_0::BEIDOU:
return GnssConstellationType_1_0::BEIDOU;
case GnssConstellationType_2_0::GALILEO:
return GnssConstellationType_1_0::GALILEO;
default:
return GnssConstellationType_1_0::UNKNOWN;
}
}
/*
* FindStrongFrequentNonGpsSource:
*
@@ -555,7 +528,7 @@ IGnssConfiguration_1_1::BlacklistedSource FindStrongFrequentNonGpsSource(
(sv_info.constellation != GnssConstellationType_2_0::GPS)) {
ComparableBlacklistedSource source;
source.id.svid = sv_info.v1_0.svid;
source.id.constellation = MapConstellationType(sv_info.constellation);
source.id.constellation = Utils::mapConstellationType(sv_info.constellation);
const auto& itSignal = mapSignals.find(source);
if (itSignal == mapSignals.end()) {
@@ -694,7 +667,7 @@ TEST_P(GnssHalTest, BlacklistIndividualSatellites) {
hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
auto constellation = MapConstellationType(sv_info.constellation);
auto constellation = Utils::mapConstellationType(sv_info.constellation);
EXPECT_FALSE((sv_info.v1_0.svid == source_to_blacklist.svid) &&
(constellation == source_to_blacklist.constellation) &&
(sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX));
@@ -736,7 +709,7 @@ TEST_P(GnssHalTest, BlacklistIndividualSatellites) {
hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
auto constellation = MapConstellationType(sv_info.constellation);
auto constellation = Utils::mapConstellationType(sv_info.constellation);
if ((sv_info.v1_0.svid == source_to_blacklist.svid) &&
(constellation == source_to_blacklist.constellation) &&
(sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX)) {
@@ -752,7 +725,7 @@ TEST_P(GnssHalTest, BlacklistIndividualSatellites) {
}
/*
* BlacklistConstellation:
* BlacklistConstellationWithLocationOff:
*
* 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding
* GnssStatus for any non-GPS constellations.
@@ -761,12 +734,11 @@ TEST_P(GnssHalTest, BlacklistIndividualSatellites) {
* GnssStatus does not use any constellation but GPS.
* 4a & b) Clean up by turning off location, and send in empty blacklist.
*/
TEST_P(GnssHalTest, BlacklistConstellation) {
TEST_P(GnssHalTest, BlacklistConstellationWithLocationOff) {
if (!IsGnssHalVersion_2_0()) {
ALOGI("Test BlacklistConstellation skipped. GNSS HAL version is greater than 2.0.");
return;
}
if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::SATELLITE_BLACKLIST)) {
ALOGI("Test BlacklistConstellation skipped. SATELLITE_BLACKLIST capability not supported.");
return;
@@ -774,43 +746,12 @@ TEST_P(GnssHalTest, BlacklistConstellation) {
const int kLocationsToAwait = 3;
gnss_cb_->location_cbq_.reset();
StartAndCheckLocations(kLocationsToAwait);
const int location_called_count = gnss_cb_->location_cbq_.calledCount();
// Find first non-GPS constellation to blacklist
GnssConstellationType_1_0 constellation_to_blacklist = startLocationAndGetNonGpsConstellation();
// Tolerate 1 less sv status to handle edge cases in reporting.
int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations (%d received)",
sv_info_list_cbq_size, kLocationsToAwait, location_called_count);
// Turns off location
StopAndClearLocations();
// Find first non-GPS constellation to blacklist. Exclude IRNSS in GnssConstellationType_2_0
// as blacklisting of this constellation is not supported in gnss@2.0.
const int kGnssSvStatusTimeout = 2;
GnssConstellationType_1_0 constellation_to_blacklist = GnssConstellationType_1_0::UNKNOWN;
for (int i = 0; i < sv_info_list_cbq_size; ++i) {
hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
if ((sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX) &&
(sv_info.constellation != GnssConstellationType_2_0::UNKNOWN) &&
(sv_info.constellation != GnssConstellationType_2_0::IRNSS) &&
(sv_info.constellation != GnssConstellationType_2_0::GPS)) {
// found a non-GPS V1_0 constellation
constellation_to_blacklist = MapConstellationType(sv_info.constellation);
break;
}
}
if (constellation_to_blacklist != GnssConstellationType_1_0::UNKNOWN) {
break;
}
}
if (constellation_to_blacklist == GnssConstellationType_1_0::UNKNOWN) {
ALOGI("No non-GPS constellations found, constellation blacklist test less effective.");
// Proceed functionally to blacklist something.
constellation_to_blacklist = GnssConstellationType_1_0::GLONASS;
}
IGnssConfiguration_1_1::BlacklistedSource source_to_blacklist;
source_to_blacklist.constellation = constellation_to_blacklist;
source_to_blacklist.svid = 0; // documented wildcard for all satellites in this constellation
@@ -824,6 +765,7 @@ TEST_P(GnssHalTest, BlacklistConstellation) {
sources.resize(1);
sources[0] = source_to_blacklist;
// setBlacklist when location is off.
auto result = gnss_configuration_hal->setBlacklist(sources);
ASSERT_TRUE(result.isOk());
EXPECT_TRUE(result);
@@ -835,15 +777,93 @@ TEST_P(GnssHalTest, BlacklistConstellation) {
StartAndCheckLocations(kLocationsToAwait);
// Tolerate 1 less sv status to handle edge cases in reporting.
sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations", sv_info_list_cbq_size,
kLocationsToAwait);
const int kGnssSvStatusTimeout = 2;
for (int i = 0; i < sv_info_list_cbq_size; ++i) {
hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
auto constellation = MapConstellationType(sv_info.constellation);
auto constellation = Utils::mapConstellationType(sv_info.constellation);
EXPECT_FALSE((constellation == source_to_blacklist.constellation) &&
(sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX));
}
}
// clean up
StopAndClearLocations();
sources.resize(0);
result = gnss_configuration_hal->setBlacklist(sources);
ASSERT_TRUE(result.isOk());
EXPECT_TRUE(result);
}
/*
* BlacklistConstellationWithLocationOn:
*
* 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding
* GnssStatus for any non-GPS constellations.
* 2a & b) Blacklist first non-GPS constellations, and turns off location.
* 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
* GnssStatus does not use any constellation but GPS.
* 4a & b) Clean up by turning off location, and send in empty blacklist.
*/
TEST_P(GnssHalTest, BlacklistConstellationWithLocationOn) {
if (!IsGnssHalVersion_2_0()) {
ALOGI("Test BlacklistConstellation skipped. GNSS HAL version is greater than 2.0.");
return;
}
if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::SATELLITE_BLACKLIST)) {
ALOGI("Test BlacklistConstellation skipped. SATELLITE_BLACKLIST capability not supported.");
return;
}
const int kLocationsToAwait = 3;
// Find first non-GPS constellation to blacklist
GnssConstellationType_1_0 constellation_to_blacklist = startLocationAndGetNonGpsConstellation();
IGnssConfiguration_1_1::BlacklistedSource source_to_blacklist;
source_to_blacklist.constellation = constellation_to_blacklist;
source_to_blacklist.svid = 0; // documented wildcard for all satellites in this constellation
auto gnss_configuration_hal_return = gnss_hal_->getExtensionGnssConfiguration_1_1();
ASSERT_TRUE(gnss_configuration_hal_return.isOk());
sp<IGnssConfiguration_1_1> gnss_configuration_hal = gnss_configuration_hal_return;
ASSERT_NE(gnss_configuration_hal, nullptr);
hidl_vec<IGnssConfiguration_1_1::BlacklistedSource> sources;
sources.resize(1);
sources[0] = source_to_blacklist;
// setBlacklist when location is on.
auto result = gnss_configuration_hal->setBlacklist(sources);
ASSERT_TRUE(result.isOk());
EXPECT_TRUE(result);
// Turns off location
StopAndClearLocations();
// retry and ensure constellation not used
gnss_cb_->sv_info_list_cbq_.reset();
gnss_cb_->location_cbq_.reset();
StartAndCheckLocations(kLocationsToAwait);
// Tolerate 1 less sv status to handle edge cases in reporting.
int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations", sv_info_list_cbq_size,
kLocationsToAwait);
const int kGnssSvStatusTimeout = 2;
for (int i = 0; i < sv_info_list_cbq_size; ++i) {
hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
auto constellation = Utils::mapConstellationType(sv_info.constellation);
EXPECT_FALSE((constellation == source_to_blacklist.constellation) &&
(sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX));
}

View File

@@ -29,6 +29,7 @@ cc_library_static {
export_include_dirs: ["include"],
shared_libs: [
"android.hardware.gnss@1.0",
"android.hardware.gnss@2.0",
"android.hardware.gnss.measurement_corrections@1.0",
"android.hardware.gnss.measurement_corrections@1.1",
],

View File

@@ -169,6 +169,31 @@ const MeasurementCorrections_1_1 Utils::getMockMeasurementCorrections_1_1() {
return mockCorrections_1_1;
}
/*
* MapConstellationType:
* Given a GnssConstellationType_2_0 type constellation, maps to its equivalent
* GnssConstellationType_1_0 type constellation. For constellations that do not have
* an equivalent value, maps to GnssConstellationType_1_0::UNKNOWN
*/
GnssConstellationType_1_0 Utils::mapConstellationType(GnssConstellationType_2_0 constellation) {
switch (constellation) {
case GnssConstellationType_2_0::GPS:
return GnssConstellationType_1_0::GPS;
case GnssConstellationType_2_0::SBAS:
return GnssConstellationType_1_0::SBAS;
case GnssConstellationType_2_0::GLONASS:
return GnssConstellationType_1_0::GLONASS;
case GnssConstellationType_2_0::QZSS:
return GnssConstellationType_1_0::QZSS;
case GnssConstellationType_2_0::BEIDOU:
return GnssConstellationType_1_0::BEIDOU;
case GnssConstellationType_2_0::GALILEO:
return GnssConstellationType_1_0::GALILEO;
default:
return GnssConstellationType_1_0::UNKNOWN;
}
}
} // namespace common
} // namespace gnss
} // namespace hardware

View File

@@ -18,9 +18,12 @@
#define android_hardware_gnss_common_vts_Utils_H_
#include <android/hardware/gnss/1.0/IGnss.h>
#include <android/hardware/gnss/2.0/IGnss.h>
#include <android/hardware/gnss/measurement_corrections/1.0/IMeasurementCorrections.h>
#include <android/hardware/gnss/measurement_corrections/1.1/IMeasurementCorrections.h>
using GnssConstellationType_1_0 = android::hardware::gnss::V1_0::GnssConstellationType;
using GnssConstellationType_2_0 = android::hardware::gnss::V2_0::GnssConstellationType;
using GnssLocation = ::android::hardware::gnss::V1_0::GnssLocation;
using namespace android::hardware::gnss::measurement_corrections::V1_0;
@@ -44,6 +47,8 @@ struct Utils {
bool check_more_accuracies);
static const MeasurementCorrections_1_0 getMockMeasurementCorrections();
static const MeasurementCorrections_1_1 getMockMeasurementCorrections_1_1();
static GnssConstellationType_1_0 mapConstellationType(GnssConstellationType_2_0 constellation);
};
} // namespace common

View File

@@ -100,10 +100,11 @@ parcelable PlaneLayout {
long totalSizeInBytes;
/**
* Horizontal and vertical subsampling. Must be a positive power of 2.
* Horizontal and vertical subsampling. Must be a positive power of 2. A value of 1
* indicates no subsampling.
*
* These fields indicate the number of horizontally or vertically adjacent pixels that use
* the same pixel data. A value of 1 indicates no subsampling.
* the same pixel data.
*/
long horizontalSubsampling;
long verticalSubsampling;

View File

@@ -23,6 +23,10 @@ cc_test {
shared_libs: [
"libfmq",
"libsync",
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@2.1",
"android.hardware.graphics.mapper@3.0",
"android.hardware.graphics.mapper@4.0",
],
static_libs: [
"android.hardware.graphics.allocator@2.0",
@@ -30,13 +34,9 @@ cc_test {
"android.hardware.graphics.allocator@4.0",
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.composer@2.1-vts",
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@2.0-vts",
"android.hardware.graphics.mapper@2.1",
"android.hardware.graphics.mapper@2.1-vts",
"android.hardware.graphics.mapper@3.0",
"android.hardware.graphics.mapper@3.0-vts",
"android.hardware.graphics.mapper@4.0",
"android.hardware.graphics.mapper@4.0-vts",
],
header_libs: [

View File

@@ -33,6 +33,10 @@ cc_test {
"libprocessgroup",
"libsync",
"libui",
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@2.1",
"android.hardware.graphics.mapper@3.0",
"android.hardware.graphics.mapper@4.0",
],
static_libs: [
"android.hardware.graphics.allocator@2.0",
@@ -43,13 +47,9 @@ cc_test {
"android.hardware.graphics.composer@2.1-vts",
"android.hardware.graphics.composer@2.2",
"android.hardware.graphics.composer@2.2-vts",
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@2.0-vts",
"android.hardware.graphics.mapper@2.1",
"android.hardware.graphics.mapper@2.1-vts",
"android.hardware.graphics.mapper@3.0",
"android.hardware.graphics.mapper@3.0-vts",
"android.hardware.graphics.mapper@4.0",
"android.hardware.graphics.mapper@4.0-vts",
"libgtest",
"librenderengine",

View File

@@ -24,6 +24,10 @@ cc_test {
"libfmq",
"libhidlbase",
"libsync",
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@2.1",
"android.hardware.graphics.mapper@3.0",
"android.hardware.graphics.mapper@4.0",
],
static_libs: [
"android.hardware.graphics.allocator@2.0",
@@ -35,13 +39,9 @@ cc_test {
"android.hardware.graphics.composer@2.2-vts",
"android.hardware.graphics.composer@2.3",
"android.hardware.graphics.composer@2.3-vts",
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@2.0-vts",
"android.hardware.graphics.mapper@2.1",
"android.hardware.graphics.mapper@2.1-vts",
"android.hardware.graphics.mapper@3.0",
"android.hardware.graphics.mapper@3.0-vts",
"android.hardware.graphics.mapper@4.0",
"android.hardware.graphics.mapper@4.0-vts",
],
header_libs: [

View File

@@ -23,6 +23,10 @@ cc_test {
shared_libs: [
"libfmq",
"libsync",
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@2.1",
"android.hardware.graphics.mapper@3.0",
"android.hardware.graphics.mapper@4.0",
],
static_libs: [
"android.hardware.graphics.allocator@2.0",
@@ -36,13 +40,9 @@ cc_test {
"android.hardware.graphics.composer@2.3-vts",
"android.hardware.graphics.composer@2.4",
"android.hardware.graphics.composer@2.4-vts",
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@2.0-vts",
"android.hardware.graphics.mapper@2.1",
"android.hardware.graphics.mapper@2.1-vts",
"android.hardware.graphics.mapper@3.0",
"android.hardware.graphics.mapper@3.0-vts",
"android.hardware.graphics.mapper@4.0",
"android.hardware.graphics.mapper@4.0-vts",
],
header_libs: [

View File

@@ -414,12 +414,9 @@ void GraphicsComposerHidlCommandTest::sendRefreshFrame(const VsyncPeriodChangeTi
mWriter->validateDisplay();
execute();
if (mReader->mCompositionChanges.size() != 0) {
GTEST_SUCCEED() << "Composition change requested, skipping test";
return;
}
ASSERT_EQ(0, mReader->mErrors.size());
mReader->mCompositionChanges.clear();
mWriter->presentDisplay();
execute();
ASSERT_EQ(0, mReader->mErrors.size());
@@ -427,8 +424,14 @@ void GraphicsComposerHidlCommandTest::sendRefreshFrame(const VsyncPeriodChangeTi
mWriter->selectLayer(layer);
auto handle2 = allocate();
ASSERT_NE(nullptr, handle2);
mWriter->setLayerBuffer(0, handle2, -1);
mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, {0, 0, 10, 10}));
mWriter->validateDisplay();
execute();
ASSERT_EQ(0, mReader->mErrors.size());
mReader->mCompositionChanges.clear();
mWriter->presentDisplay();
execute();
}
@@ -490,16 +493,16 @@ void GraphicsComposerHidlCommandTest::Test_setActiveConfigWithConstraints(
// At this point the refresh rate should have changed already, however in rare
// cases the implementation might have missed the deadline. In this case a new
// timeline should have been provided.
auto newTimelime = mComposerCallback->takeLastVsyncPeriodChangeTimeline();
auto newTimeline = mComposerCallback->takeLastVsyncPeriodChangeTimeline();
if (timeline.refreshRequired && refreshMiss) {
EXPECT_TRUE(newTimelime.has_value());
EXPECT_TRUE(newTimeline.has_value());
}
if (newTimelime.has_value()) {
if (timeline.refreshRequired) {
sendRefreshFrame(&newTimelime.value());
if (newTimeline.has_value()) {
if (newTimeline->refreshRequired) {
sendRefreshFrame(&newTimeline.value());
}
waitForVsyncPeriodChange(display, newTimelime.value(), constraints.desiredTimeNanos,
waitForVsyncPeriodChange(display, newTimeline.value(), constraints.desiredTimeNanos,
vsyncPeriod1, vsyncPeriod2);
}

View File

@@ -587,8 +587,8 @@ TEST_P(GraphicsMapperHidlTest, LockUnlockBasic) {
static_cast<int32_t>(info.height)};
unique_fd fence;
uint8_t* data;
ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(
mGralloc->lock(bufferHandle, info.usage, region, fence.get())));
ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage,
region, fence.release())));
// RGBA_8888
fillRGBA8888(data, info.height, stride * 4, info.width * 4);
@@ -596,8 +596,8 @@ TEST_P(GraphicsMapperHidlTest, LockUnlockBasic) {
ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
// lock again for reading
ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(
mGralloc->lock(bufferHandle, info.usage, region, fence.get())));
ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage,
region, fence.release())));
ASSERT_NO_FATAL_FAILURE(
verifyRGBA8888(bufferHandle, data, info.height, stride * 4, info.width * 4));
@@ -605,6 +605,9 @@ TEST_P(GraphicsMapperHidlTest, LockUnlockBasic) {
ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
}
/**
* Test multiple operations associated with different color formats
*/
TEST_P(GraphicsMapperHidlTest, Lock_YCRCB_420_SP) {
auto info = mDummyDescriptorInfo;
info.format = PixelFormat::YCRCB_420_SP;
@@ -624,8 +627,8 @@ TEST_P(GraphicsMapperHidlTest, Lock_YCRCB_420_SP) {
unique_fd fence;
uint8_t* data;
ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(
mGralloc->lock(bufferHandle, info.usage, region, fence.get())));
ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage,
region, fence.release())));
android_ycbcr yCbCr;
int64_t hSubsampling = 0;
@@ -647,8 +650,8 @@ TEST_P(GraphicsMapperHidlTest, Lock_YCRCB_420_SP) {
ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
// lock again for reading
ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(
mGralloc->lock(bufferHandle, info.usage, region, fence.get())));
ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage,
region, fence.release())));
ASSERT_NO_FATAL_FAILURE(
getAndroidYCbCr(bufferHandle, data, &yCbCr, &hSubsampling, &vSubsampling));
@@ -658,6 +661,56 @@ TEST_P(GraphicsMapperHidlTest, Lock_YCRCB_420_SP) {
ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
}
TEST_P(GraphicsMapperHidlTest, YV12SubsampleMetadata) {
auto info = mDummyDescriptorInfo;
info.format = PixelFormat::YV12;
const native_handle_t* bufferHandle;
uint32_t stride;
ASSERT_NO_FATAL_FAILURE(
bufferHandle = mGralloc->allocate(info, true, Tolerance::kToleranceStrict, &stride));
const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
static_cast<int32_t>(info.height)};
unique_fd fence;
ASSERT_NO_FATAL_FAILURE(mGralloc->lock(bufferHandle, info.usage, region, fence.release()));
hidl_vec<uint8_t> vec;
ASSERT_EQ(Error::NONE, mGralloc->get(bufferHandle, gralloc4::MetadataType_PlaneLayouts, &vec));
std::vector<PlaneLayout> planeLayouts;
ASSERT_EQ(NO_ERROR, gralloc4::decodePlaneLayouts(vec, &planeLayouts));
ASSERT_EQ(3, planeLayouts.size());
auto yPlane = planeLayouts[0];
auto crPlane = planeLayouts[1];
auto cbPlane = planeLayouts[2];
constexpr uint32_t kCbCrSubSampleFactor = 2;
EXPECT_EQ(kCbCrSubSampleFactor, crPlane.horizontalSubsampling);
EXPECT_EQ(kCbCrSubSampleFactor, crPlane.verticalSubsampling);
EXPECT_EQ(kCbCrSubSampleFactor, cbPlane.horizontalSubsampling);
EXPECT_EQ(kCbCrSubSampleFactor, cbPlane.verticalSubsampling);
const long chromaSampleWidth = info.width / kCbCrSubSampleFactor;
const long chromaSampleHeight = info.height / kCbCrSubSampleFactor;
EXPECT_EQ(info.width, yPlane.widthInSamples);
EXPECT_EQ(info.height, yPlane.heightInSamples);
EXPECT_EQ(chromaSampleWidth, crPlane.widthInSamples);
EXPECT_EQ(chromaSampleHeight, crPlane.heightInSamples);
EXPECT_EQ(chromaSampleWidth, cbPlane.widthInSamples);
EXPECT_EQ(chromaSampleHeight, cbPlane.heightInSamples);
EXPECT_LE(crPlane.widthInSamples, crPlane.strideInBytes);
EXPECT_LE(cbPlane.widthInSamples, cbPlane.strideInBytes);
ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
}
TEST_P(GraphicsMapperHidlTest, Lock_YV12) {
auto info = mDummyDescriptorInfo;
info.format = PixelFormat::YV12;
@@ -673,8 +726,8 @@ TEST_P(GraphicsMapperHidlTest, Lock_YV12) {
unique_fd fence;
uint8_t* data;
ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(
mGralloc->lock(bufferHandle, info.usage, region, fence.get())));
ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage,
region, fence.release())));
android_ycbcr yCbCr;
int64_t hSubsampling = 0;
@@ -696,8 +749,8 @@ TEST_P(GraphicsMapperHidlTest, Lock_YV12) {
ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
// lock again for reading
ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(
mGralloc->lock(bufferHandle, info.usage, region, fence.get())));
ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage,
region, fence.release())));
ASSERT_NO_FATAL_FAILURE(
getAndroidYCbCr(bufferHandle, data, &yCbCr, &hSubsampling, &vSubsampling));
@@ -722,8 +775,8 @@ TEST_P(GraphicsMapperHidlTest, Lock_YCBCR_420_888) {
unique_fd fence;
uint8_t* data;
ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(
mGralloc->lock(bufferHandle, info.usage, region, fence.get())));
ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage,
region, fence.release())));
android_ycbcr yCbCr;
int64_t hSubsampling = 0;
@@ -740,8 +793,8 @@ TEST_P(GraphicsMapperHidlTest, Lock_YCBCR_420_888) {
ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
// lock again for reading
ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(
mGralloc->lock(bufferHandle, info.usage, region, fence.get())));
ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage,
region, fence.release())));
ASSERT_NO_FATAL_FAILURE(
getAndroidYCbCr(bufferHandle, data, &yCbCr, &hSubsampling, &vSubsampling));
@@ -751,6 +804,90 @@ TEST_P(GraphicsMapperHidlTest, Lock_YCBCR_420_888) {
ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
}
TEST_P(GraphicsMapperHidlTest, Lock_RAW10) {
auto info = mDummyDescriptorInfo;
info.format = PixelFormat::RAW10;
const native_handle_t* bufferHandle;
uint32_t stride;
ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(
info, true, Tolerance::kToleranceUnSupported, &stride));
if (bufferHandle == nullptr) {
GTEST_SUCCEED() << "RAW10 format is unsupported";
return;
}
const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
static_cast<int32_t>(info.height)};
unique_fd fence;
ASSERT_NO_FATAL_FAILURE(mGralloc->lock(bufferHandle, info.usage, region, fence.release()));
hidl_vec<uint8_t> vec;
ASSERT_EQ(Error::NONE, mGralloc->get(bufferHandle, gralloc4::MetadataType_PlaneLayouts, &vec));
std::vector<PlaneLayout> planeLayouts;
ASSERT_EQ(NO_ERROR, gralloc4::decodePlaneLayouts(vec, &planeLayouts));
ASSERT_EQ(1, planeLayouts.size());
auto planeLayout = planeLayouts[0];
EXPECT_EQ(0, planeLayout.sampleIncrementInBits);
EXPECT_EQ(1, planeLayout.horizontalSubsampling);
EXPECT_EQ(1, planeLayout.verticalSubsampling);
ASSERT_EQ(1, planeLayout.components.size());
auto planeLayoutComponent = planeLayout.components[0];
EXPECT_EQ(PlaneLayoutComponentType::RAW,
static_cast<PlaneLayoutComponentType>(planeLayoutComponent.type.value));
EXPECT_EQ(0, planeLayoutComponent.offsetInBits % 8);
EXPECT_EQ(-1, planeLayoutComponent.sizeInBits);
ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
}
TEST_P(GraphicsMapperHidlTest, Lock_RAW12) {
auto info = mDummyDescriptorInfo;
info.format = PixelFormat::RAW12;
const native_handle_t* bufferHandle;
uint32_t stride;
ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(
info, true, Tolerance::kToleranceUnSupported, &stride));
if (bufferHandle == nullptr) {
GTEST_SUCCEED() << "RAW12 format is unsupported";
return;
}
const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
static_cast<int32_t>(info.height)};
unique_fd fence;
ASSERT_NO_FATAL_FAILURE(mGralloc->lock(bufferHandle, info.usage, region, fence.release()));
hidl_vec<uint8_t> vec;
ASSERT_EQ(Error::NONE, mGralloc->get(bufferHandle, gralloc4::MetadataType_PlaneLayouts, &vec));
std::vector<PlaneLayout> planeLayouts;
ASSERT_EQ(NO_ERROR, gralloc4::decodePlaneLayouts(vec, &planeLayouts));
ASSERT_EQ(1, planeLayouts.size());
auto planeLayout = planeLayouts[0];
EXPECT_EQ(0, planeLayout.sampleIncrementInBits);
EXPECT_EQ(1, planeLayout.horizontalSubsampling);
EXPECT_EQ(1, planeLayout.verticalSubsampling);
ASSERT_EQ(1, planeLayout.components.size());
auto planeLayoutComponent = planeLayout.components[0];
EXPECT_EQ(PlaneLayoutComponentType::RAW,
static_cast<PlaneLayoutComponentType>(planeLayoutComponent.type.value));
EXPECT_EQ(0, planeLayoutComponent.offsetInBits % 8);
EXPECT_EQ(-1, planeLayoutComponent.sizeInBits);
ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
}
/**
* Test IMapper::unlock with bad access region
*/
@@ -1706,6 +1843,84 @@ TEST_P(GraphicsMapperHidlTest, SetMetadataNullBuffer) {
mGralloc->set(bufferHandle, gralloc4::MetadataType_Smpte2094_40, vec));
}
/**
* Test get::metadata with cloned native_handle
*/
TEST_P(GraphicsMapperHidlTest, GetMetadataClonedHandle) {
const native_handle_t* bufferHandle = nullptr;
ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true));
const auto dataspace = Dataspace::SRGB_LINEAR;
{
hidl_vec<uint8_t> metadata;
ASSERT_EQ(NO_ERROR, gralloc4::encodeDataspace(dataspace, &metadata));
Error err = mGralloc->set(bufferHandle, gralloc4::MetadataType_Dataspace, metadata);
if (err == Error::UNSUPPORTED) {
GTEST_SUCCEED() << "setting this metadata is unsupported";
return;
}
ASSERT_EQ(Error::NONE, err);
}
const native_handle_t* importedHandle;
{
auto clonedHandle = native_handle_clone(bufferHandle);
ASSERT_NO_FATAL_FAILURE(importedHandle = mGralloc->importBuffer(clonedHandle));
native_handle_close(clonedHandle);
native_handle_delete(clonedHandle);
}
Dataspace realSpace = Dataspace::UNKNOWN;
{
hidl_vec<uint8_t> metadata;
ASSERT_EQ(Error::NONE,
mGralloc->get(importedHandle, gralloc4::MetadataType_Dataspace, &metadata));
ASSERT_NO_FATAL_FAILURE(gralloc4::decodeDataspace(metadata, &realSpace));
}
EXPECT_EQ(dataspace, realSpace);
}
/**
* Test set::metadata with cloned native_handle
*/
TEST_P(GraphicsMapperHidlTest, SetMetadataClonedHandle) {
const native_handle_t* bufferHandle = nullptr;
ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true));
const native_handle_t* importedHandle;
{
auto clonedHandle = native_handle_clone(bufferHandle);
ASSERT_NO_FATAL_FAILURE(importedHandle = mGralloc->importBuffer(clonedHandle));
native_handle_close(clonedHandle);
native_handle_delete(clonedHandle);
}
const auto dataspace = Dataspace::SRGB_LINEAR;
{
hidl_vec<uint8_t> metadata;
ASSERT_EQ(NO_ERROR, gralloc4::encodeDataspace(dataspace, &metadata));
Error err = mGralloc->set(importedHandle, gralloc4::MetadataType_Dataspace, metadata);
if (err == Error::UNSUPPORTED) {
GTEST_SUCCEED() << "setting this metadata is unsupported";
return;
}
ASSERT_EQ(Error::NONE, err);
}
Dataspace realSpace = Dataspace::UNKNOWN;
{
hidl_vec<uint8_t> metadata;
ASSERT_EQ(Error::NONE,
mGralloc->get(bufferHandle, gralloc4::MetadataType_Dataspace, &metadata));
ASSERT_NO_FATAL_FAILURE(gralloc4::decodeDataspace(metadata, &realSpace));
}
EXPECT_EQ(dataspace, realSpace);
}
/**
* Test IMapper::set(metadata) for constant metadata
*/

View File

@@ -151,8 +151,8 @@ interface IIdentityCredential {
* IntentToRetain = bool
*
* For the readerSignature parameter, this can either be empty or if non-empty it
* must be a COSE_Sign1 structure with an ECDSA signature over the content of the
* CBOR conforming to the following CDDL:
* must be a COSE_Sign1 where the payload is the bytes of the
* ReaderAuthenticationBytes CBOR defined below:
*
* ReaderAuthentication = [
* "ReaderAuthentication",
@@ -160,16 +160,11 @@ interface IIdentityCredential {
* ItemsRequestBytes
* ]
*
* SessionTranscript = [
* DeviceEngagementBytes,
* EReaderKeyBytes
* ]
* SessionTranscript = any
*
* DeviceEngagementBytes = #6.24(bstr .cbor DeviceEngagement)
* EReaderKeyBytes = #6.24(bstr .cbor EReaderKey.Pub)
* ItemsRequestBytes = #6.24(bstr .cbor ItemsRequest)
*
* EReaderKey.Pub = COSE_Key ; Ephemeral public key provided by reader
* ReaderAuthenticationBytes = #6.24(bstr .cbor ReaderAuthentication)
*
* The public key corresponding to the key used to made signature, can be found in the
* 'x5chain' unprotected header element of the COSE_Sign1 structure (as as described
@@ -184,8 +179,12 @@ interface IIdentityCredential {
*
* If the SessionTranscript CBOR is not empty, the X and Y coordinates of the public
* part of the key-pair previously generated by createEphemeralKeyPair() must appear
* somewhere in the bytes of DeviceEngagement structure. Both X and Y should be in
* uncompressed form. If this is not satisfied, the call fails with
* somewhere in the bytes of the CBOR. Each of these coordinates must appear encoded
* with the most significant bits first and use the exact amount of bits indicated by
* the key size of the ephemeral keys. For example, if the ephemeral key is using the
* P-256 curve then the 32 bytes for the X coordinate encoded with the most significant
* bits first must appear somewhere in the CBOR and ditto for the 32 bytes for the Y
* coordinate. If this is not satisfied, the call fails with
* STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND.
*
* @param accessControlProfiles
@@ -281,7 +280,7 @@ interface IIdentityCredential {
*
* @param out mac is empty if signingKeyBlob or the sessionTranscript passed to
* startRetrieval() is empty. Otherwise it is a COSE_Mac0 with empty payload
* and the detached content is set to DeviceAuthentication as defined below.
* and the detached content is set to DeviceAuthenticationBytes as defined below.
* This code is produced by using the key agreement and key derivation function
* from the ciphersuite with the authentication private key and the reader
* ephemeral public key to compute a shared message authentication code (MAC)
@@ -298,15 +297,12 @@ interface IIdentityCredential {
*
* DocType = tstr
*
* SessionTranscript = [
* DeviceEngagementBytes,
* EReaderKeyBytes
* ]
* SessionTranscript = any
*
* DeviceEngagementBytes = #6.24(bstr .cbor DeviceEngagement)
* EReaderKeyBytes = #6.24(bstr .cbor EReaderKey.Pub)
* DeviceNameSpacesBytes = #6.24(bstr .cbor DeviceNameSpaces)
*
* DeviceAuthenticationBytes = #6.24(bstr .cbor DeviceAuthentication)
*
* where
*
* DeviceNameSpaces = {
@@ -356,8 +352,9 @@ interface IIdentityCredential {
*
* - subjectPublicKeyInfo: must contain attested public key.
*
* @param out signingKeyBlob contains an encrypted copy of the newly-generated private
* signing key.
* @param out signingKeyBlob contains an AES-GCM-ENC(storageKey, R, signingKey, docType)
* where signingKey is an EC private key in uncompressed form. That is, the returned
* blob is an encrypted copy of the newly-generated private signing key.
*
* @return an X.509 certificate for the new signing key, signed by the credential key.
*/

View File

@@ -99,7 +99,7 @@ import android.hardware.identity.CipherSuite;
* Various fields need to be encoded as precisely-specified byte arrays. Where existing standards
* define appropriate encodings, those are used. For example, X.509 certificates. Where new
* encodings are needed, CBOR is used. CBOR maps are described in CDDL notation
* (https://tools.ietf.org/html/draft-ietf-cbor-cddl-06).
* (https://tools.ietf.org/html/rfc8610).
*
* All binder calls in the HAL may return a ServiceSpecificException with statuses from the
* STATUS_* integers defined in this interface. Each method states which status can be returned

View File

@@ -29,9 +29,27 @@ interface IWritableIdentityCredential {
* Gets the certificate chain for credentialKey which can be used to prove the hardware
* characteristics to an issuing authority. Must not be called more than once.
*
* The following non-optional fields for the X.509 certificate shall be set as follows:
*
* - version: INTEGER 2 (means v3 certificate).
*
* - serialNumber: INTEGER 1 (fixed value: same on all certs).
*
* - signature: must be set to ECDSA.
*
* - subject: CN shall be set to "Android Identity Credential Key".
*
* - issuer: shall be set to "credentialStoreName (credentialStoreAuthorName)" using the
* values returned in HardwareInformation.
*
* - validity: should be from current time and expire at the same time as the
* attestation batch certificate used.
*
* - subjectPublicKeyInfo: must contain attested public key.
*
* The certificate chain must be generated using Keymaster Attestation
* (see https://source.android.com/security/keystore/attestation) with the
* following additional requirements:
* following additional requirements on the data in the attestation extension:
*
* - The attestationVersion field in the attestation extension must be at least 3.
*
@@ -109,7 +127,8 @@ interface IWritableIdentityCredential {
* in Tag::ATTESTATION_APPLICATION_ID. This schema is described in
* https://developer.android.com/training/articles/security-key-attestation#certificate_schema_attestationid
*
* @param attestationChallenge a challenge set by the issuer to ensure freshness.
* @param attestationChallenge a challenge set by the issuer to ensure freshness. If
* this is empty, the call fails with STATUS_INVALID_DATA.
*
* @return the X.509 certificate chain for the credentialKey
*/
@@ -250,6 +269,7 @@ interface IWritableIdentityCredential {
* CredentialKeys = [
* bstr, ; storageKey, a 128-bit AES key
* bstr ; credentialPrivKey, the private key for credentialKey
* ; in uncompressed form
* ]
*
* @param out proofOfProvisioningSignature proves to the IA that the credential was imported

View File

@@ -39,6 +39,10 @@ using ::std::optional;
using namespace ::android::hardware::identity;
int IdentityCredential::initialize() {
if (credentialData_.size() == 0) {
LOG(ERROR) << "CredentialData is empty";
return IIdentityCredentialStore::STATUS_INVALID_DATA;
}
auto [item, _, message] = cppbor::parse(credentialData_);
if (item == nullptr) {
LOG(ERROR) << "CredentialData is not valid CBOR: " << message;
@@ -164,6 +168,7 @@ ndk::ScopedAStatus IdentityCredential::createAuthChallenge(int64_t* outChallenge
}
*outChallenge = challenge;
authChallenge_ = challenge;
return ndk::ScopedAStatus::ok();
}
@@ -223,7 +228,8 @@ bool checkUserAuthentication(const SecureAccessControlProfile& profile,
}
if (authToken.challenge != int64_t(authChallenge)) {
LOG(ERROR) << "Challenge in authToken doesn't match the challenge we created";
LOG(ERROR) << "Challenge in authToken (" << uint64_t(authToken.challenge) << ") "
<< "doesn't match the challenge we created (" << authChallenge << ")";
return false;
}
return true;
@@ -314,13 +320,16 @@ ndk::ScopedAStatus IdentityCredential::startRetrieval(
}
const vector<uint8_t>& itemsRequestBytes = itemsRequest;
vector<uint8_t> dataThatWasSigned = cppbor::Array()
.add("ReaderAuthentication")
.add(sessionTranscriptItem_->clone())
.add(cppbor::Semantic(24, itemsRequestBytes))
.encode();
vector<uint8_t> encodedReaderAuthentication =
cppbor::Array()
.add("ReaderAuthentication")
.add(sessionTranscriptItem_->clone())
.add(cppbor::Semantic(24, itemsRequestBytes))
.encode();
vector<uint8_t> encodedReaderAuthenticationBytes =
cppbor::Semantic(24, encodedReaderAuthentication).encode();
if (!support::coseCheckEcDsaSignature(readerSignature,
dataThatWasSigned, // detached content
encodedReaderAuthenticationBytes, // detached content
readerPublicKey.value())) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_READER_SIGNATURE_CHECK_FAILED,
@@ -341,28 +350,6 @@ ndk::ScopedAStatus IdentityCredential::startRetrieval(
//
// We do this by just searching for the X and Y coordinates.
if (sessionTranscript.size() > 0) {
const cppbor::Array* array = sessionTranscriptItem_->asArray();
if (array == nullptr || array->size() != 2) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND,
"SessionTranscript is not an array with two items"));
}
const cppbor::Semantic* taggedEncodedDE = (*array)[0]->asSemantic();
if (taggedEncodedDE == nullptr || taggedEncodedDE->value() != 24) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND,
"First item in SessionTranscript array is not a "
"semantic with value 24"));
}
const cppbor::Bstr* encodedDE = (taggedEncodedDE->child())->asBstr();
if (encodedDE == nullptr) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND,
"Child of semantic in first item in SessionTranscript "
"array is not a bstr"));
}
const vector<uint8_t>& bytesDE = encodedDE->value();
auto [getXYSuccess, ePubX, ePubY] = support::ecPublicKeyGetXandY(ephemeralPublicKey_);
if (!getXYSuccess) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
@@ -370,8 +357,10 @@ ndk::ScopedAStatus IdentityCredential::startRetrieval(
"Error extracting X and Y from ePub"));
}
if (sessionTranscript.size() > 0 &&
!(memmem(bytesDE.data(), bytesDE.size(), ePubX.data(), ePubX.size()) != nullptr &&
memmem(bytesDE.data(), bytesDE.size(), ePubY.data(), ePubY.size()) != nullptr)) {
!(memmem(sessionTranscript.data(), sessionTranscript.size(), ePubX.data(),
ePubX.size()) != nullptr &&
memmem(sessionTranscript.data(), sessionTranscript.size(), ePubY.data(),
ePubY.size()) != nullptr)) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND,
"Did not find ephemeral public key's X and Y coordinates in "
@@ -478,9 +467,10 @@ ndk::ScopedAStatus IdentityCredential::startRetrieval(
}
// Validate all the access control profiles in the requestData.
bool haveAuthToken = (authToken.mac.size() > 0);
bool haveAuthToken = (authToken.timestamp.milliSeconds != int64_t(0));
for (const auto& profile : accessControlProfiles) {
if (!secureAccessControlProfileCheckMac(profile, storageKey_)) {
LOG(ERROR) << "Error checking MAC for profile";
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_INVALID_DATA,
"Error checking MAC for profile"));
@@ -796,7 +786,7 @@ ndk::ScopedAStatus IdentityCredential::finishRetrieval(vector<int8_t>* outMac,
array.add(sessionTranscriptItem_->clone());
array.add(docType_);
array.add(cppbor::Semantic(24, encodedDeviceNameSpaces));
vector<uint8_t> encodedDeviceAuthentication = array.encode();
vector<uint8_t> deviceAuthenticationBytes = cppbor::Semantic(24, array.encode()).encode();
vector<uint8_t> docTypeAsBlob(docType_.begin(), docType_.end());
optional<vector<uint8_t>> signingKey =
@@ -814,17 +804,24 @@ ndk::ScopedAStatus IdentityCredential::finishRetrieval(vector<int8_t>* outMac,
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(sharedSecret.value(), salt, info, 32);
optional<vector<uint8_t>> derivedKey =
support::hkdf(sharedSecretWithSessionTranscriptBytes, salt, info, 32);
if (!derivedKey) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_FAILED,
"Error deriving key from shared secret"));
}
mac = support::coseMac0(derivedKey.value(), {}, // payload
encodedDeviceAuthentication); // additionalData
mac = support::coseMac0(derivedKey.value(), {}, // payload
deviceAuthenticationBytes); // detached content
if (!mac) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_FAILED, "Error MACing data"));

View File

@@ -65,6 +65,10 @@ ndk::ScopedAStatus WritableIdentityCredential::getAttestationCertificate(
IIdentityCredentialStore::STATUS_FAILED,
"Error attestation certificate previously generated"));
}
if (attestationChallenge.empty()) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_INVALID_DATA, "Challenge can not be empty"));
}
vector<uint8_t> challenge(attestationChallenge.begin(), attestationChallenge.end());
vector<uint8_t> appId(attestationApplicationId.begin(), attestationApplicationId.end());
@@ -165,6 +169,13 @@ ndk::ScopedAStatus WritableIdentityCredential::addAccessControlProfile(
"userAuthenticationRequired is false but timeout is non-zero"));
}
// If |userAuthenticationRequired| is true, then |secureUserId| must be non-zero.
if (userAuthenticationRequired && secureUserId == 0) {
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
IIdentityCredentialStore::STATUS_INVALID_DATA,
"userAuthenticationRequired is true but secureUserId is zero"));
}
profile.id = id;
profile.readerCertificate = readerCertificate;
profile.userAuthenticationRequired = userAuthenticationRequired;

View File

@@ -10,20 +10,23 @@ cc_test {
"VtsIdentityTestUtils.cpp",
"VtsAttestationTests.cpp",
"VtsAttestationParserSupport.cpp",
"UserAuthTests.cpp",
"ReaderAuthTests.cpp",
],
shared_libs: [
"android.hardware.keymaster@4.0",
"libbinder",
"libcrypto",
"libkeymaster_portable",
"libsoft_attestation_cert",
"libpuresoftkeymasterdevice",
],
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",
],
test_suites: [
"general-tests",

View File

@@ -0,0 +1,602 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "ReaderAuthTests"
#include <aidl/Gtest.h>
#include <aidl/Vintf.h>
#include <aidl/android/hardware/keymaster/HardwareAuthToken.h>
#include <aidl/android/hardware/keymaster/VerificationToken.h>
#include <android-base/logging.h>
#include <android/hardware/identity/IIdentityCredentialStore.h>
#include <android/hardware/identity/support/IdentityCredentialSupport.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <cppbor.h>
#include <cppbor_parse.h>
#include <gtest/gtest.h>
#include <future>
#include <map>
#include <utility>
#include "VtsIdentityTestUtils.h"
namespace android::hardware::identity {
using std::endl;
using std::make_pair;
using std::map;
using std::optional;
using std::pair;
using std::string;
using std::tie;
using std::vector;
using ::android::sp;
using ::android::String16;
using ::android::binder::Status;
using ::android::hardware::keymaster::HardwareAuthToken;
using ::android::hardware::keymaster::VerificationToken;
class ReaderAuthTests : public testing::TestWithParam<string> {
public:
virtual void SetUp() override {
credentialStore_ = android::waitForDeclaredService<IIdentityCredentialStore>(
String16(GetParam().c_str()));
ASSERT_NE(credentialStore_, nullptr);
}
void provisionData();
void retrieveData(const vector<uint8_t>& readerPrivateKey,
const vector<vector<uint8_t>>& readerCertChain, bool expectSuccess,
bool leaveOutAccessibleToAllFromRequestMessage);
// Set by provisionData
vector<uint8_t> readerPublicKey_;
vector<uint8_t> readerPrivateKey_;
vector<uint8_t> intermediateAPublicKey_;
vector<uint8_t> intermediateAPrivateKey_;
vector<uint8_t> intermediateBPublicKey_;
vector<uint8_t> intermediateBPrivateKey_;
vector<uint8_t> intermediateCPublicKey_;
vector<uint8_t> intermediateCPrivateKey_;
vector<uint8_t> cert_A_SelfSigned_;
vector<uint8_t> cert_B_SelfSigned_;
vector<uint8_t> cert_B_SignedBy_C_;
vector<uint8_t> cert_C_SelfSigned_;
vector<uint8_t> cert_reader_SelfSigned_;
vector<uint8_t> cert_reader_SignedBy_A_;
vector<uint8_t> cert_reader_SignedBy_B_;
SecureAccessControlProfile sacp0_;
SecureAccessControlProfile sacp1_;
SecureAccessControlProfile sacp2_;
SecureAccessControlProfile sacp3_;
vector<uint8_t> encContentAccessibleByA_;
vector<uint8_t> encContentAccessibleByAorB_;
vector<uint8_t> encContentAccessibleByB_;
vector<uint8_t> encContentAccessibleByC_;
vector<uint8_t> encContentAccessibleByAll_;
vector<uint8_t> encContentAccessibleByNone_;
vector<uint8_t> credentialData_;
// Set by retrieveData()
bool canGetAccessibleByA_;
bool canGetAccessibleByAorB_;
bool canGetAccessibleByB_;
bool canGetAccessibleByC_;
bool canGetAccessibleByAll_;
bool canGetAccessibleByNone_;
sp<IIdentityCredentialStore> credentialStore_;
};
pair<vector<uint8_t>, vector<uint8_t>> generateReaderKey() {
optional<vector<uint8_t>> keyPKCS8 = support::createEcKeyPair();
optional<vector<uint8_t>> publicKey = support::ecKeyPairGetPublicKey(keyPKCS8.value());
optional<vector<uint8_t>> privateKey = support::ecKeyPairGetPrivateKey(keyPKCS8.value());
return make_pair(publicKey.value(), privateKey.value());
}
vector<uint8_t> generateReaderCert(const vector<uint8_t>& publicKey,
const vector<uint8_t>& signingKey) {
time_t validityNotBefore = 0;
time_t validityNotAfter = 0xffffffff;
optional<vector<uint8_t>> cert =
support::ecPublicKeyGenerateCertificate(publicKey, signingKey, "24601", "Issuer",
"Subject", validityNotBefore, validityNotAfter);
return cert.value();
}
void ReaderAuthTests::provisionData() {
// Keys and certificates for intermediates.
tie(intermediateAPublicKey_, intermediateAPrivateKey_) = generateReaderKey();
tie(intermediateBPublicKey_, intermediateBPrivateKey_) = generateReaderKey();
tie(intermediateCPublicKey_, intermediateCPrivateKey_) = generateReaderKey();
cert_A_SelfSigned_ = generateReaderCert(intermediateAPublicKey_, intermediateAPrivateKey_);
cert_B_SelfSigned_ = generateReaderCert(intermediateBPublicKey_, intermediateBPrivateKey_);
cert_B_SignedBy_C_ = generateReaderCert(intermediateBPublicKey_, intermediateCPrivateKey_);
cert_C_SelfSigned_ = generateReaderCert(intermediateCPublicKey_, intermediateCPrivateKey_);
// Key and self-signed certificate reader
tie(readerPublicKey_, readerPrivateKey_) = generateReaderKey();
cert_reader_SelfSigned_ = generateReaderCert(readerPublicKey_, readerPrivateKey_);
// Certificate for reader signed by intermediates
cert_reader_SignedBy_A_ = generateReaderCert(readerPublicKey_, intermediateAPrivateKey_);
cert_reader_SignedBy_B_ = generateReaderCert(readerPublicKey_, intermediateBPrivateKey_);
string docType = "org.iso.18013-5.2019.mdl";
bool testCredential = true;
sp<IWritableIdentityCredential> wc;
ASSERT_TRUE(credentialStore_->createCredential(docType, testCredential, &wc).isOk());
vector<uint8_t> attestationApplicationId = {};
vector<uint8_t> attestationChallenge = {1};
vector<Certificate> certChain;
ASSERT_TRUE(wc->getAttestationCertificate(attestationApplicationId, attestationChallenge,
&certChain)
.isOk());
size_t proofOfProvisioningSize =
465 + cert_A_SelfSigned_.size() + cert_B_SelfSigned_.size() + cert_C_SelfSigned_.size();
ASSERT_TRUE(wc->setExpectedProofOfProvisioningSize(proofOfProvisioningSize).isOk());
// Not in v1 HAL, may fail
wc->startPersonalization(4 /* numAccessControlProfiles */,
{6} /* numDataElementsPerNamespace */);
// AIDL expects certificates wrapped in the Certificate type...
Certificate cert_A;
Certificate cert_B;
Certificate cert_C;
cert_A.encodedCertificate = cert_A_SelfSigned_;
cert_B.encodedCertificate = cert_B_SelfSigned_;
cert_C.encodedCertificate = cert_C_SelfSigned_;
// Access control profile 0: accessible by A
ASSERT_TRUE(wc->addAccessControlProfile(0, cert_A, false, 0, 0, &sacp0_).isOk());
// Access control profile 1: accessible by B
ASSERT_TRUE(wc->addAccessControlProfile(1, cert_B, false, 0, 0, &sacp1_).isOk());
// Access control profile 2: accessible by C
ASSERT_TRUE(wc->addAccessControlProfile(2, cert_C, false, 0, 0, &sacp2_).isOk());
// Access control profile 3: open access
ASSERT_TRUE(wc->addAccessControlProfile(3, {}, false, 0, 0, &sacp3_).isOk());
// Data Element: "Accessible by A"
ASSERT_TRUE(wc->beginAddEntry({0}, "ns", "Accessible by A", 1).isOk());
ASSERT_TRUE(wc->addEntryValue({9}, &encContentAccessibleByA_).isOk());
// Data Element: "Accessible by A or B"
ASSERT_TRUE(wc->beginAddEntry({0, 1}, "ns", "Accessible by A or B", 1).isOk());
ASSERT_TRUE(wc->addEntryValue({9}, &encContentAccessibleByAorB_).isOk());
// Data Element: "Accessible by B"
ASSERT_TRUE(wc->beginAddEntry({1}, "ns", "Accessible by B", 1).isOk());
ASSERT_TRUE(wc->addEntryValue({9}, &encContentAccessibleByB_).isOk());
// Data Element: "Accessible by C"
ASSERT_TRUE(wc->beginAddEntry({2}, "ns", "Accessible by C", 1).isOk());
ASSERT_TRUE(wc->addEntryValue({9}, &encContentAccessibleByC_).isOk());
// Data Element: "Accessible by All"
ASSERT_TRUE(wc->beginAddEntry({3}, "ns", "Accessible by All", 1).isOk());
ASSERT_TRUE(wc->addEntryValue({9}, &encContentAccessibleByAll_).isOk());
// Data Element: "Accessible by None"
ASSERT_TRUE(wc->beginAddEntry({}, "ns", "Accessible by None", 1).isOk());
ASSERT_TRUE(wc->addEntryValue({9}, &encContentAccessibleByNone_).isOk());
vector<uint8_t> proofOfProvisioningSignature;
ASSERT_TRUE(wc->finishAddingEntries(&credentialData_, &proofOfProvisioningSignature).isOk());
}
RequestDataItem buildRequestDataItem(const string& name, size_t size,
vector<int32_t> accessControlProfileIds) {
RequestDataItem item;
item.name = name;
item.size = size;
item.accessControlProfileIds = accessControlProfileIds;
return item;
}
void ReaderAuthTests::retrieveData(const vector<uint8_t>& readerPrivateKey,
const vector<vector<uint8_t>>& readerCertChain,
bool expectSuccess,
bool leaveOutAccessibleToAllFromRequestMessage) {
canGetAccessibleByA_ = false;
canGetAccessibleByAorB_ = false;
canGetAccessibleByB_ = false;
canGetAccessibleByC_ = false;
canGetAccessibleByAll_ = false;
canGetAccessibleByNone_ = false;
sp<IIdentityCredential> c;
ASSERT_TRUE(credentialStore_
->getCredential(
CipherSuite::CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256,
credentialData_, &c)
.isOk());
optional<vector<uint8_t>> readerEKeyPair = support::createEcKeyPair();
optional<vector<uint8_t>> readerEPublicKey =
support::ecKeyPairGetPublicKey(readerEKeyPair.value());
ASSERT_TRUE(c->setReaderEphemeralPublicKey(readerEPublicKey.value()).isOk());
vector<uint8_t> eKeyPair;
ASSERT_TRUE(c->createEphemeralKeyPair(&eKeyPair).isOk());
optional<vector<uint8_t>> ePublicKey = support::ecKeyPairGetPublicKey(eKeyPair);
// Calculate requestData field and sign it with the reader key.
auto [getXYSuccess, ephX, ephY] = support::ecPublicKeyGetXandY(ePublicKey.value());
ASSERT_TRUE(getXYSuccess);
cppbor::Map deviceEngagement = cppbor::Map().add("ephX", ephX).add("ephY", ephY);
vector<uint8_t> deviceEngagementBytes = deviceEngagement.encode();
vector<uint8_t> eReaderPubBytes = cppbor::Tstr("ignored").encode();
cppbor::Array sessionTranscript = cppbor::Array()
.add(cppbor::Semantic(24, deviceEngagementBytes))
.add(cppbor::Semantic(24, eReaderPubBytes));
vector<uint8_t> sessionTranscriptBytes = sessionTranscript.encode();
vector<uint8_t> itemsRequestBytes;
if (leaveOutAccessibleToAllFromRequestMessage) {
itemsRequestBytes =
cppbor::Map("nameSpaces",
cppbor::Map().add("ns", cppbor::Map()
.add("Accessible by A", false)
.add("Accessible by A or B", false)
.add("Accessible by B", false)
.add("Accessible by C", false)
.add("Accessible by None", false)))
.encode();
} else {
itemsRequestBytes =
cppbor::Map("nameSpaces",
cppbor::Map().add("ns", cppbor::Map()
.add("Accessible by A", false)
.add("Accessible by A or B", false)
.add("Accessible by B", false)
.add("Accessible by C", false)
.add("Accessible by All", false)
.add("Accessible by None", false)))
.encode();
}
vector<uint8_t> encodedReaderAuthentication =
cppbor::Array()
.add("ReaderAuthentication")
.add(sessionTranscript.clone())
.add(cppbor::Semantic(24, itemsRequestBytes))
.encode();
vector<uint8_t> encodedReaderAuthenticationBytes =
cppbor::Semantic(24, encodedReaderAuthentication).encode();
optional<vector<uint8_t>> readerSignature =
support::coseSignEcDsa(readerPrivateKey, // private key for reader
{}, // content
encodedReaderAuthenticationBytes, // detached content
support::certificateChainJoin(readerCertChain));
ASSERT_TRUE(readerSignature);
// Generate the key that will be used to sign AuthenticatedData.
vector<uint8_t> signingKeyBlob;
Certificate signingKeyCertificate;
ASSERT_TRUE(c->generateSigningKeyPair(&signingKeyBlob, &signingKeyCertificate).isOk());
RequestNamespace rns;
rns.namespaceName = "ns";
rns.items.push_back(buildRequestDataItem("Accessible by A", 1, {0}));
rns.items.push_back(buildRequestDataItem("Accessible by A or B", 1, {0, 1}));
rns.items.push_back(buildRequestDataItem("Accessible by B", 1, {1}));
rns.items.push_back(buildRequestDataItem("Accessible by C", 1, {2}));
rns.items.push_back(buildRequestDataItem("Accessible by All", 1, {3}));
rns.items.push_back(buildRequestDataItem("Accessible by None", 1, {}));
// OK to fail, not available in v1 HAL
c->setRequestedNamespaces({rns}).isOk();
// It doesn't matter since no user auth is needed in this particular test,
// but for good measure, clear out the tokens we pass to the HAL.
HardwareAuthToken authToken;
VerificationToken verificationToken;
authToken.challenge = 0;
authToken.userId = 0;
authToken.authenticatorId = 0;
authToken.authenticatorType = ::android::hardware::keymaster::HardwareAuthenticatorType::NONE;
authToken.timestamp.milliSeconds = 0;
authToken.mac.clear();
verificationToken.challenge = 0;
verificationToken.timestamp.milliSeconds = 0;
verificationToken.securityLevel = ::android::hardware::keymaster::SecurityLevel::SOFTWARE;
verificationToken.mac.clear();
// OK to fail, not available in v1 HAL
c->setVerificationToken(verificationToken);
Status status = c->startRetrieval(
{sacp0_, sacp1_, sacp2_, sacp3_}, authToken, itemsRequestBytes, signingKeyBlob,
sessionTranscriptBytes, readerSignature.value(), {6 /* numDataElementsPerNamespace */});
if (expectSuccess) {
ASSERT_TRUE(status.isOk());
} else {
ASSERT_FALSE(status.isOk());
return;
}
vector<uint8_t> decrypted;
status = c->startRetrieveEntryValue("ns", "Accessible by A", 1, {0});
if (status.isOk()) {
canGetAccessibleByA_ = true;
ASSERT_TRUE(c->retrieveEntryValue(encContentAccessibleByA_, &decrypted).isOk());
}
status = c->startRetrieveEntryValue("ns", "Accessible by A or B", 1, {0, 1});
if (status.isOk()) {
canGetAccessibleByAorB_ = true;
ASSERT_TRUE(c->retrieveEntryValue(encContentAccessibleByAorB_, &decrypted).isOk());
}
status = c->startRetrieveEntryValue("ns", "Accessible by B", 1, {1});
if (status.isOk()) {
canGetAccessibleByB_ = true;
ASSERT_TRUE(c->retrieveEntryValue(encContentAccessibleByB_, &decrypted).isOk());
}
status = c->startRetrieveEntryValue("ns", "Accessible by C", 1, {2});
if (status.isOk()) {
canGetAccessibleByC_ = true;
ASSERT_TRUE(c->retrieveEntryValue(encContentAccessibleByC_, &decrypted).isOk());
}
status = c->startRetrieveEntryValue("ns", "Accessible by All", 1, {3});
if (status.isOk()) {
canGetAccessibleByAll_ = true;
ASSERT_TRUE(c->retrieveEntryValue(encContentAccessibleByAll_, &decrypted).isOk());
}
status = c->startRetrieveEntryValue("ns", "Accessible by None", 1, {});
if (status.isOk()) {
canGetAccessibleByNone_ = true;
ASSERT_TRUE(c->retrieveEntryValue(encContentAccessibleByNone_, &decrypted).isOk());
}
vector<uint8_t> mac;
vector<uint8_t> deviceNameSpaces;
ASSERT_TRUE(c->finishRetrieval(&mac, &deviceNameSpaces).isOk());
}
TEST_P(ReaderAuthTests, presentingChain_Reader) {
provisionData();
retrieveData(readerPrivateKey_, {cert_reader_SelfSigned_}, true /* expectSuccess */,
false /* leaveOutAccessibleToAllFromRequestMessage */);
EXPECT_FALSE(canGetAccessibleByA_);
EXPECT_FALSE(canGetAccessibleByAorB_);
EXPECT_FALSE(canGetAccessibleByB_);
EXPECT_FALSE(canGetAccessibleByC_);
EXPECT_TRUE(canGetAccessibleByAll_);
EXPECT_FALSE(canGetAccessibleByNone_);
}
TEST_P(ReaderAuthTests, presentingChain_Reader_A) {
provisionData();
retrieveData(readerPrivateKey_, {cert_reader_SignedBy_A_, cert_A_SelfSigned_},
true /* expectSuccess */, false /* leaveOutAccessibleToAllFromRequestMessage */);
EXPECT_TRUE(canGetAccessibleByA_);
EXPECT_TRUE(canGetAccessibleByAorB_);
EXPECT_FALSE(canGetAccessibleByB_);
EXPECT_FALSE(canGetAccessibleByC_);
EXPECT_TRUE(canGetAccessibleByAll_);
EXPECT_FALSE(canGetAccessibleByNone_);
}
TEST_P(ReaderAuthTests, presentingChain_Reader_B) {
provisionData();
retrieveData(readerPrivateKey_, {cert_reader_SignedBy_B_, cert_B_SelfSigned_},
true /* expectSuccess */, false /* leaveOutAccessibleToAllFromRequestMessage */);
EXPECT_FALSE(canGetAccessibleByA_);
EXPECT_TRUE(canGetAccessibleByAorB_);
EXPECT_TRUE(canGetAccessibleByB_);
EXPECT_FALSE(canGetAccessibleByC_);
EXPECT_TRUE(canGetAccessibleByAll_);
EXPECT_FALSE(canGetAccessibleByNone_);
}
// This test proves that for the purpose of determining inclusion of an ACP certificate
// in a presented reader chain, certificate equality is done by comparing public keys,
// not bitwise comparison of the certificates.
//
// Specifically for this test, the ACP is configured with cert_B_SelfSigned_ and the
// reader is presenting cert_B_SignedBy_C_. Both certificates have the same public
// key - intermediateBPublicKey_ - but they are signed by different keys.
//
TEST_P(ReaderAuthTests, presentingChain_Reader_B_C) {
provisionData();
retrieveData(readerPrivateKey_,
{cert_reader_SignedBy_B_, cert_B_SignedBy_C_, cert_C_SelfSigned_},
true /* expectSuccess */, false /* leaveOutAccessibleToAllFromRequestMessage */);
EXPECT_FALSE(canGetAccessibleByA_);
EXPECT_TRUE(canGetAccessibleByAorB_);
EXPECT_TRUE(canGetAccessibleByB_);
EXPECT_TRUE(canGetAccessibleByC_);
EXPECT_TRUE(canGetAccessibleByAll_);
EXPECT_FALSE(canGetAccessibleByNone_);
}
// This test presents a reader chain where the chain is invalid because
// the 2nd certificate in the chain isn't signed by the 3rd one.
//
TEST_P(ReaderAuthTests, presentingInvalidChain) {
provisionData();
retrieveData(readerPrivateKey_,
{cert_reader_SignedBy_B_, cert_B_SelfSigned_, cert_C_SelfSigned_},
false /* expectSuccess */, false /* leaveOutAccessibleToAllFromRequestMessage */);
}
// This tests presents a valid reader chain but where requestMessage isn't
// signed by the private key corresponding to the public key in the top-level
// certificate.
//
TEST_P(ReaderAuthTests, presentingMessageSignedNotByTopLevel) {
provisionData();
retrieveData(intermediateBPrivateKey_,
{cert_reader_SignedBy_B_, cert_B_SignedBy_C_, cert_C_SelfSigned_},
false /* expectSuccess */, false /* leaveOutAccessibleToAllFromRequestMessage */);
}
// This test leaves out "Accessible by All" data element from the signed request
// message (the CBOR from the reader) while still including this data element at
// the API level. The call on the API level for said element will fail with
// STATUS_NOT_IN_REQUEST_MESSAGE but this doesn't prevent the other elements
// from being returned (if authorized, of course).
//
// This test verifies that.
//
TEST_P(ReaderAuthTests, limitedMessage) {
provisionData();
retrieveData(readerPrivateKey_, {cert_reader_SelfSigned_}, true /* expectSuccess */,
true /* leaveOutAccessibleToAllFromRequestMessage */);
EXPECT_FALSE(canGetAccessibleByA_);
EXPECT_FALSE(canGetAccessibleByAorB_);
EXPECT_FALSE(canGetAccessibleByB_);
EXPECT_FALSE(canGetAccessibleByC_);
EXPECT_FALSE(canGetAccessibleByAll_);
EXPECT_FALSE(canGetAccessibleByNone_);
}
TEST_P(ReaderAuthTests, ephemeralKeyNotInSessionTranscript) {
provisionData();
sp<IIdentityCredential> c;
ASSERT_TRUE(credentialStore_
->getCredential(
CipherSuite::CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256,
credentialData_, &c)
.isOk());
optional<vector<uint8_t>> readerEKeyPair = support::createEcKeyPair();
optional<vector<uint8_t>> readerEPublicKey =
support::ecKeyPairGetPublicKey(readerEKeyPair.value());
ASSERT_TRUE(c->setReaderEphemeralPublicKey(readerEPublicKey.value()).isOk());
vector<uint8_t> eKeyPair;
ASSERT_TRUE(c->createEphemeralKeyPair(&eKeyPair).isOk());
optional<vector<uint8_t>> ePublicKey = support::ecKeyPairGetPublicKey(eKeyPair);
// Calculate requestData field and sign it with the reader key.
auto [getXYSuccess, ephX, ephY] = support::ecPublicKeyGetXandY(ePublicKey.value());
ASSERT_TRUE(getXYSuccess);
// Instead of include the X and Y coordinates (|ephX| and |ephY|), add NUL bytes instead.
vector<uint8_t> nulls(32);
cppbor::Map deviceEngagement = cppbor::Map().add("ephX", nulls).add("ephY", nulls);
vector<uint8_t> deviceEngagementBytes = deviceEngagement.encode();
vector<uint8_t> eReaderPubBytes = cppbor::Tstr("ignored").encode();
cppbor::Array sessionTranscript = cppbor::Array()
.add(cppbor::Semantic(24, deviceEngagementBytes))
.add(cppbor::Semantic(24, eReaderPubBytes));
vector<uint8_t> sessionTranscriptBytes = sessionTranscript.encode();
vector<uint8_t> itemsRequestBytes;
itemsRequestBytes =
cppbor::Map("nameSpaces",
cppbor::Map().add("ns", cppbor::Map()
.add("Accessible by A", false)
.add("Accessible by A or B", false)
.add("Accessible by B", false)
.add("Accessible by C", false)
.add("Accessible by None", false)))
.encode();
vector<uint8_t> encodedReaderAuthentication =
cppbor::Array()
.add("ReaderAuthentication")
.add(sessionTranscript.clone())
.add(cppbor::Semantic(24, itemsRequestBytes))
.encode();
vector<uint8_t> encodedReaderAuthenticationBytes =
cppbor::Semantic(24, encodedReaderAuthentication).encode();
vector<vector<uint8_t>> readerCertChain = {cert_reader_SelfSigned_};
optional<vector<uint8_t>> readerSignature =
support::coseSignEcDsa(readerPrivateKey_, // private key for reader
{}, // content
encodedReaderAuthenticationBytes, // detached content
support::certificateChainJoin(readerCertChain));
ASSERT_TRUE(readerSignature);
// Generate the key that will be used to sign AuthenticatedData.
vector<uint8_t> signingKeyBlob;
Certificate signingKeyCertificate;
ASSERT_TRUE(c->generateSigningKeyPair(&signingKeyBlob, &signingKeyCertificate).isOk());
RequestNamespace rns;
rns.namespaceName = "ns";
rns.items.push_back(buildRequestDataItem("Accessible by A", 1, {0}));
rns.items.push_back(buildRequestDataItem("Accessible by A or B", 1, {0, 1}));
rns.items.push_back(buildRequestDataItem("Accessible by B", 1, {1}));
rns.items.push_back(buildRequestDataItem("Accessible by C", 1, {2}));
rns.items.push_back(buildRequestDataItem("Accessible by All", 1, {3}));
rns.items.push_back(buildRequestDataItem("Accessible by None", 1, {}));
// OK to fail, not available in v1 HAL
c->setRequestedNamespaces({rns}).isOk();
// It doesn't matter since no user auth is needed in this particular test,
// but for good measure, clear out the tokens we pass to the HAL.
HardwareAuthToken authToken;
VerificationToken verificationToken;
authToken.challenge = 0;
authToken.userId = 0;
authToken.authenticatorId = 0;
authToken.authenticatorType = ::android::hardware::keymaster::HardwareAuthenticatorType::NONE;
authToken.timestamp.milliSeconds = 0;
authToken.mac.clear();
verificationToken.challenge = 0;
verificationToken.timestamp.milliSeconds = 0;
verificationToken.securityLevel =
::android::hardware::keymaster::SecurityLevel::TRUSTED_ENVIRONMENT;
verificationToken.mac.clear();
// OK to fail, not available in v1 HAL
c->setVerificationToken(verificationToken);
// Finally check that STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND is returned.
// This proves that the TA checked for X and Y coordinatets and didn't find
// them.
Status status = c->startRetrieval(
{sacp0_, sacp1_, sacp2_, sacp3_}, authToken, itemsRequestBytes, signingKeyBlob,
sessionTranscriptBytes, readerSignature.value(), {6 /* numDataElementsPerNamespace */});
ASSERT_FALSE(status.isOk());
ASSERT_EQ(binder::Status::EX_SERVICE_SPECIFIC, status.exceptionCode());
ASSERT_EQ(IIdentityCredentialStore::STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND,
status.serviceSpecificErrorCode());
}
INSTANTIATE_TEST_SUITE_P(
Identity, ReaderAuthTests,
testing::ValuesIn(android::getAidlHalInstanceNames(IIdentityCredentialStore::descriptor)),
android::PrintInstanceNameToString);
} // namespace android::hardware::identity

View File

@@ -0,0 +1,473 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "UserAuthTests"
#include <aidl/Gtest.h>
#include <aidl/Vintf.h>
#include <aidl/android/hardware/keymaster/HardwareAuthToken.h>
#include <aidl/android/hardware/keymaster/VerificationToken.h>
#include <android-base/logging.h>
#include <android/hardware/identity/IIdentityCredentialStore.h>
#include <android/hardware/identity/support/IdentityCredentialSupport.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <cppbor.h>
#include <cppbor_parse.h>
#include <gtest/gtest.h>
#include <future>
#include <map>
#include <utility>
#include "VtsIdentityTestUtils.h"
namespace android::hardware::identity {
using std::endl;
using std::make_pair;
using std::map;
using std::optional;
using std::pair;
using std::string;
using std::tie;
using std::vector;
using ::android::sp;
using ::android::String16;
using ::android::binder::Status;
using ::android::hardware::keymaster::HardwareAuthToken;
using ::android::hardware::keymaster::VerificationToken;
class UserAuthTests : public testing::TestWithParam<string> {
public:
virtual void SetUp() override {
credentialStore_ = android::waitForDeclaredService<IIdentityCredentialStore>(
String16(GetParam().c_str()));
ASSERT_NE(credentialStore_, nullptr);
}
void provisionData();
void setupRetrieveData();
pair<HardwareAuthToken, VerificationToken> mintTokens(uint64_t challengeForAuthToken,
int64_t ageOfAuthTokenMilliSeconds);
void retrieveData(HardwareAuthToken authToken, VerificationToken verificationToken,
bool expectSuccess, bool useSessionTranscript);
// Set by provisionData
SecureAccessControlProfile sacp0_;
SecureAccessControlProfile sacp1_;
SecureAccessControlProfile sacp2_;
vector<uint8_t> encContentUserAuthPerSession_;
vector<uint8_t> encContentUserAuthTimeout_;
vector<uint8_t> encContentAccessibleByAll_;
vector<uint8_t> encContentAccessibleByNone_;
vector<uint8_t> credentialData_;
// Set by setupRetrieveData().
int64_t authChallenge_;
cppbor::Map sessionTranscript_;
sp<IIdentityCredential> credential_;
// Set by retrieveData()
bool canGetUserAuthPerSession_;
bool canGetUserAuthTimeout_;
bool canGetAccessibleByAll_;
bool canGetAccessibleByNone_;
sp<IIdentityCredentialStore> credentialStore_;
};
void UserAuthTests::provisionData() {
string docType = "org.iso.18013-5.2019.mdl";
bool testCredential = true;
sp<IWritableIdentityCredential> wc;
ASSERT_TRUE(credentialStore_->createCredential(docType, testCredential, &wc).isOk());
vector<uint8_t> attestationApplicationId = {};
vector<uint8_t> attestationChallenge = {1};
vector<Certificate> certChain;
ASSERT_TRUE(wc->getAttestationCertificate(attestationApplicationId, attestationChallenge,
&certChain)
.isOk());
size_t proofOfProvisioningSize = 381;
// Not in v1 HAL, may fail
wc->setExpectedProofOfProvisioningSize(proofOfProvisioningSize);
ASSERT_TRUE(wc->startPersonalization(3 /* numAccessControlProfiles */,
{4} /* numDataElementsPerNamespace */)
.isOk());
// Access control profile 0: user auth every session (timeout = 0)
ASSERT_TRUE(wc->addAccessControlProfile(0, {}, true, 0, 65 /* secureUserId */, &sacp0_).isOk());
// Access control profile 1: user auth, 60 seconds timeout
ASSERT_TRUE(
wc->addAccessControlProfile(1, {}, true, 60000, 65 /* secureUserId */, &sacp1_).isOk());
// Access control profile 2: open access
ASSERT_TRUE(wc->addAccessControlProfile(2, {}, false, 0, 0, &sacp2_).isOk());
// Data Element: "UserAuth Per Session"
ASSERT_TRUE(wc->beginAddEntry({0}, "ns", "UserAuth Per Session", 1).isOk());
ASSERT_TRUE(wc->addEntryValue({9}, &encContentUserAuthPerSession_).isOk());
// Data Element: "UserAuth Timeout"
ASSERT_TRUE(wc->beginAddEntry({1}, "ns", "UserAuth Timeout", 1).isOk());
ASSERT_TRUE(wc->addEntryValue({9}, &encContentUserAuthTimeout_).isOk());
// Data Element: "Accessible by All"
ASSERT_TRUE(wc->beginAddEntry({2}, "ns", "Accessible by All", 1).isOk());
ASSERT_TRUE(wc->addEntryValue({9}, &encContentAccessibleByAll_).isOk());
// Data Element: "Accessible by None"
ASSERT_TRUE(wc->beginAddEntry({}, "ns", "Accessible by None", 1).isOk());
ASSERT_TRUE(wc->addEntryValue({9}, &encContentAccessibleByNone_).isOk());
vector<uint8_t> proofOfProvisioningSignature;
Status status = wc->finishAddingEntries(&credentialData_, &proofOfProvisioningSignature);
EXPECT_TRUE(status.isOk()) << status.exceptionCode() << ": " << status.exceptionMessage();
}
// From ReaderAuthTest.cpp - TODO: consolidate with VtsIdentityTestUtils.h
pair<vector<uint8_t>, vector<uint8_t>> generateReaderKey();
vector<uint8_t> generateReaderCert(const vector<uint8_t>& publicKey,
const vector<uint8_t>& signingKey);
RequestDataItem buildRequestDataItem(const string& name, size_t size,
vector<int32_t> accessControlProfileIds);
cppbor::Map calcSessionTranscript(const vector<uint8_t>& ePublicKey) {
auto [getXYSuccess, ephX, ephY] = support::ecPublicKeyGetXandY(ePublicKey);
cppbor::Map deviceEngagement = cppbor::Map().add("ephX", ephX).add("ephY", ephY);
vector<uint8_t> deviceEngagementBytes = deviceEngagement.encode();
vector<uint8_t> eReaderPubBytes = cppbor::Tstr("ignored").encode();
// Let SessionTranscript be a map here (it's an array in EndToEndTest) just
// to check that the implementation can deal with either.
cppbor::Map sessionTranscript;
sessionTranscript.add(42, cppbor::Semantic(24, deviceEngagementBytes));
sessionTranscript.add(43, cppbor::Semantic(24, eReaderPubBytes));
return sessionTranscript;
}
void UserAuthTests::setupRetrieveData() {
ASSERT_TRUE(credentialStore_
->getCredential(
CipherSuite::CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256,
credentialData_, &credential_)
.isOk());
optional<vector<uint8_t>> readerEKeyPair = support::createEcKeyPair();
optional<vector<uint8_t>> readerEPublicKey =
support::ecKeyPairGetPublicKey(readerEKeyPair.value());
ASSERT_TRUE(credential_->setReaderEphemeralPublicKey(readerEPublicKey.value()).isOk());
vector<uint8_t> eKeyPair;
ASSERT_TRUE(credential_->createEphemeralKeyPair(&eKeyPair).isOk());
optional<vector<uint8_t>> ePublicKey = support::ecKeyPairGetPublicKey(eKeyPair);
sessionTranscript_ = calcSessionTranscript(ePublicKey.value());
Status status = credential_->createAuthChallenge(&authChallenge_);
EXPECT_TRUE(status.isOk()) << status.exceptionCode() << ": " << status.exceptionMessage();
}
void UserAuthTests::retrieveData(HardwareAuthToken authToken, VerificationToken verificationToken,
bool expectSuccess, bool useSessionTranscript) {
canGetUserAuthPerSession_ = false;
canGetUserAuthTimeout_ = false;
canGetAccessibleByAll_ = false;
canGetAccessibleByNone_ = false;
vector<uint8_t> itemsRequestBytes;
vector<uint8_t> sessionTranscriptBytes;
if (useSessionTranscript) {
sessionTranscriptBytes = sessionTranscript_.encode();
itemsRequestBytes =
cppbor::Map("nameSpaces",
cppbor::Map().add("ns", cppbor::Map()
.add("UserAuth Per Session", false)
.add("UserAuth Timeout", false)
.add("Accessible by All", false)
.add("Accessible by None", false)))
.encode();
vector<uint8_t> dataToSign = cppbor::Array()
.add("ReaderAuthentication")
.add(sessionTranscript_.clone())
.add(cppbor::Semantic(24, itemsRequestBytes))
.encode();
}
// Generate the key that will be used to sign AuthenticatedData.
vector<uint8_t> signingKeyBlob;
Certificate signingKeyCertificate;
ASSERT_TRUE(
credential_->generateSigningKeyPair(&signingKeyBlob, &signingKeyCertificate).isOk());
RequestNamespace rns;
rns.namespaceName = "ns";
rns.items.push_back(buildRequestDataItem("UserAuth Per Session", 1, {0}));
rns.items.push_back(buildRequestDataItem("UserAuth Timeout", 1, {1}));
rns.items.push_back(buildRequestDataItem("Accessible by All", 1, {2}));
rns.items.push_back(buildRequestDataItem("Accessible by None", 1, {}));
// OK to fail, not available in v1 HAL
credential_->setRequestedNamespaces({rns}).isOk();
// OK to fail, not available in v1 HAL
credential_->setVerificationToken(verificationToken);
Status status = credential_->startRetrieval({sacp0_, sacp1_, sacp2_}, authToken,
itemsRequestBytes, signingKeyBlob,
sessionTranscriptBytes, {} /* readerSignature */,
{4 /* numDataElementsPerNamespace */});
if (expectSuccess) {
ASSERT_TRUE(status.isOk());
} else {
ASSERT_FALSE(status.isOk());
return;
}
vector<uint8_t> decrypted;
status = credential_->startRetrieveEntryValue("ns", "UserAuth Per Session", 1, {0});
if (status.isOk()) {
canGetUserAuthPerSession_ = true;
ASSERT_TRUE(
credential_->retrieveEntryValue(encContentUserAuthPerSession_, &decrypted).isOk());
}
status = credential_->startRetrieveEntryValue("ns", "UserAuth Timeout", 1, {1});
if (status.isOk()) {
canGetUserAuthTimeout_ = true;
ASSERT_TRUE(credential_->retrieveEntryValue(encContentUserAuthTimeout_, &decrypted).isOk());
}
status = credential_->startRetrieveEntryValue("ns", "Accessible by All", 1, {2});
if (status.isOk()) {
canGetAccessibleByAll_ = true;
ASSERT_TRUE(credential_->retrieveEntryValue(encContentAccessibleByAll_, &decrypted).isOk());
}
status = credential_->startRetrieveEntryValue("ns", "Accessible by None", 1, {});
if (status.isOk()) {
canGetAccessibleByNone_ = true;
ASSERT_TRUE(
credential_->retrieveEntryValue(encContentAccessibleByNone_, &decrypted).isOk());
}
vector<uint8_t> mac;
vector<uint8_t> deviceNameSpaces;
ASSERT_TRUE(credential_->finishRetrieval(&mac, &deviceNameSpaces).isOk());
}
pair<HardwareAuthToken, VerificationToken> UserAuthTests::mintTokens(
uint64_t challengeForAuthToken, int64_t ageOfAuthTokenMilliSeconds) {
HardwareAuthToken authToken;
VerificationToken verificationToken;
uint64_t epochMilliseconds = 1000ULL * 1000ULL * 1000ULL * 1000ULL;
authToken.challenge = challengeForAuthToken;
authToken.userId = 65;
authToken.authenticatorId = 0;
authToken.authenticatorType = ::android::hardware::keymaster::HardwareAuthenticatorType::NONE;
authToken.timestamp.milliSeconds = epochMilliseconds - ageOfAuthTokenMilliSeconds;
authToken.mac.clear();
verificationToken.challenge = authChallenge_;
verificationToken.timestamp.milliSeconds = epochMilliseconds;
verificationToken.securityLevel =
::android::hardware::keymaster::SecurityLevel::TRUSTED_ENVIRONMENT;
verificationToken.mac.clear();
return make_pair(authToken, verificationToken);
}
TEST_P(UserAuthTests, GoodChallenge) {
provisionData();
setupRetrieveData();
auto [authToken, verificationToken] = mintTokens(authChallenge_, // challengeForAuthToken
0); // ageOfAuthTokenMilliSeconds
retrieveData(authToken, verificationToken, true /* expectSuccess */,
true /* useSessionTranscript */);
EXPECT_TRUE(canGetUserAuthPerSession_);
EXPECT_TRUE(canGetUserAuthTimeout_);
EXPECT_TRUE(canGetAccessibleByAll_);
EXPECT_FALSE(canGetAccessibleByNone_);
}
TEST_P(UserAuthTests, OtherChallenge) {
provisionData();
setupRetrieveData();
uint64_t otherChallenge = authChallenge_ ^ 0x12345678;
auto [authToken, verificationToken] = mintTokens(otherChallenge, // challengeForAuthToken
0); // ageOfAuthTokenMilliSeconds
retrieveData(authToken, verificationToken, true /* expectSuccess */,
true /* useSessionTranscript */);
EXPECT_FALSE(canGetUserAuthPerSession_);
EXPECT_TRUE(canGetUserAuthTimeout_);
EXPECT_TRUE(canGetAccessibleByAll_);
EXPECT_FALSE(canGetAccessibleByNone_);
}
TEST_P(UserAuthTests, NoChallenge) {
provisionData();
setupRetrieveData();
auto [authToken, verificationToken] = mintTokens(0, // challengeForAuthToken
0); // ageOfAuthTokenMilliSeconds
retrieveData(authToken, verificationToken, true /* expectSuccess */,
true /* useSessionTranscript */);
EXPECT_FALSE(canGetUserAuthPerSession_);
EXPECT_TRUE(canGetUserAuthTimeout_);
EXPECT_TRUE(canGetAccessibleByAll_);
EXPECT_FALSE(canGetAccessibleByNone_);
}
TEST_P(UserAuthTests, AuthTokenAgeZero) {
provisionData();
setupRetrieveData();
auto [authToken, verificationToken] = mintTokens(0, // challengeForAuthToken
0); // ageOfAuthTokenMilliSeconds
retrieveData(authToken, verificationToken, true /* expectSuccess */,
true /* useSessionTranscript */);
EXPECT_FALSE(canGetUserAuthPerSession_);
EXPECT_TRUE(canGetUserAuthTimeout_);
EXPECT_TRUE(canGetAccessibleByAll_);
EXPECT_FALSE(canGetAccessibleByNone_);
}
TEST_P(UserAuthTests, AuthTokenFromTheFuture) {
provisionData();
setupRetrieveData();
auto [authToken, verificationToken] = mintTokens(0, // challengeForAuthToken
-1 * 1000); // ageOfAuthTokenMilliSeconds
retrieveData(authToken, verificationToken, true /* expectSuccess */,
true /* useSessionTranscript */);
EXPECT_FALSE(canGetUserAuthPerSession_);
EXPECT_FALSE(canGetUserAuthTimeout_);
EXPECT_TRUE(canGetAccessibleByAll_);
EXPECT_FALSE(canGetAccessibleByNone_);
}
TEST_P(UserAuthTests, AuthTokenInsideTimeout) {
provisionData();
setupRetrieveData();
auto [authToken, verificationToken] = mintTokens(0, // challengeForAuthToken
30 * 1000); // ageOfAuthTokenMilliSeconds
retrieveData(authToken, verificationToken, true /* expectSuccess */,
true /* useSessionTranscript */);
EXPECT_FALSE(canGetUserAuthPerSession_);
EXPECT_TRUE(canGetUserAuthTimeout_);
EXPECT_TRUE(canGetAccessibleByAll_);
EXPECT_FALSE(canGetAccessibleByNone_);
}
TEST_P(UserAuthTests, AuthTokenOutsideTimeout) {
provisionData();
setupRetrieveData();
auto [authToken, verificationToken] = mintTokens(0, // challengeForAuthToken
61 * 1000); // ageOfAuthTokenMilliSeconds
retrieveData(authToken, verificationToken, true /* expectSuccess */,
true /* useSessionTranscript */);
EXPECT_FALSE(canGetUserAuthPerSession_);
EXPECT_FALSE(canGetUserAuthTimeout_);
EXPECT_TRUE(canGetAccessibleByAll_);
EXPECT_FALSE(canGetAccessibleByNone_);
}
// The API works even when there's no SessionTranscript / itemsRequest.
// Verify that.
TEST_P(UserAuthTests, NoSessionTranscript) {
provisionData();
setupRetrieveData();
auto [authToken, verificationToken] = mintTokens(0, // challengeForAuthToken
1 * 1000); // ageOfAuthTokenMilliSeconds
retrieveData(authToken, verificationToken, true /* expectSuccess */,
false /* useSessionTranscript */);
EXPECT_FALSE(canGetUserAuthPerSession_);
EXPECT_TRUE(canGetUserAuthTimeout_);
EXPECT_TRUE(canGetAccessibleByAll_);
EXPECT_FALSE(canGetAccessibleByNone_);
}
// This test verifies that it's possible to do multiple requests as long
// as the sessionTranscript doesn't change.
//
TEST_P(UserAuthTests, MultipleRequestsSameSessionTranscript) {
provisionData();
setupRetrieveData();
// First we try with a stale authToken
//
auto [authToken, verificationToken] = mintTokens(0, // challengeForAuthToken
61 * 1000); // ageOfAuthTokenMilliSeconds
retrieveData(authToken, verificationToken, true /* expectSuccess */,
true /* useSessionTranscript */);
EXPECT_FALSE(canGetUserAuthPerSession_);
EXPECT_FALSE(canGetUserAuthTimeout_);
EXPECT_TRUE(canGetAccessibleByAll_);
EXPECT_FALSE(canGetAccessibleByNone_);
// Then we get a new authToken and try again.
tie(authToken, verificationToken) = mintTokens(0, // challengeForAuthToken
5 * 1000); // ageOfAuthTokenMilliSeconds
retrieveData(authToken, verificationToken, true /* expectSuccess */,
true /* useSessionTranscript */);
EXPECT_FALSE(canGetUserAuthPerSession_);
EXPECT_TRUE(canGetUserAuthTimeout_);
EXPECT_TRUE(canGetAccessibleByAll_);
EXPECT_FALSE(canGetAccessibleByNone_);
}
// Like MultipleRequestsSameSessionTranscript but we change the sessionTranscript
// between the two calls. This test verifies that change is detected and the
// second request fails.
//
TEST_P(UserAuthTests, MultipleRequestsSessionTranscriptChanges) {
provisionData();
setupRetrieveData();
// First we try with a stale authToken
//
auto [authToken, verificationToken] = mintTokens(0, // challengeForAuthToken
61 * 1000); // ageOfAuthTokenMilliSeconds
retrieveData(authToken, verificationToken, true /* expectSuccess */,
true /* useSessionTranscript */);
EXPECT_FALSE(canGetUserAuthPerSession_);
EXPECT_FALSE(canGetUserAuthTimeout_);
EXPECT_TRUE(canGetAccessibleByAll_);
EXPECT_FALSE(canGetAccessibleByNone_);
// Then we get a new authToken and try again.
tie(authToken, verificationToken) = mintTokens(0, // challengeForAuthToken
5 * 1000); // ageOfAuthTokenMilliSeconds
// Change sessionTranscript...
optional<vector<uint8_t>> eKeyPairNew = support::createEcKeyPair();
optional<vector<uint8_t>> ePublicKeyNew = support::ecKeyPairGetPublicKey(eKeyPairNew.value());
sessionTranscript_ = calcSessionTranscript(ePublicKeyNew.value());
// ... and expect failure.
retrieveData(authToken, verificationToken, false /* expectSuccess */,
true /* useSessionTranscript */);
}
INSTANTIATE_TEST_SUITE_P(
Identity, UserAuthTests,
testing::ValuesIn(android::getAidlHalInstanceNames(IIdentityCredentialStore::descriptor)),
android::PrintInstanceNameToString);
} // namespace android::hardware::identity

View File

@@ -61,51 +61,6 @@ class VtsAttestationTests : public testing::TestWithParam<std::string> {
sp<IIdentityCredentialStore> credentialStore_;
};
TEST_P(VtsAttestationTests, verifyAttestationWithEmptyChallengeEmptyId) {
Status result;
HardwareInformation hwInfo;
ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
sp<IWritableIdentityCredential> writableCredential;
ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
vector<uint8_t> attestationChallenge;
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, verifyAttestationWithEmptyChallengeNonemptyId) {
Status result;
HardwareInformation hwInfo;
ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
sp<IWritableIdentityCredential> writableCredential;
ASSERT_TRUE(setupWritableCredential(writableCredential, credentialStore_));
vector<uint8_t> attestationChallenge;
vector<Certificate> attestationCertificate;
string applicationId = "Attestation Verification";
vector<uint8_t> attestationApplicationId = {applicationId.begin(), applicationId.end()};
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, verifyAttestationWithNonemptyChallengeEmptyId) {
Status result;

View File

@@ -27,15 +27,18 @@
#include <gtest/gtest.h>
#include <future>
#include <map>
#include <tuple>
#include "VtsIdentityTestUtils.h"
namespace android::hardware::identity {
using std::endl;
using std::make_tuple;
using std::map;
using std::optional;
using std::string;
using std::tuple;
using std::vector;
using ::android::sp;
@@ -66,6 +69,61 @@ TEST_P(IdentityAidl, hardwareInformation) {
ASSERT_GE(info.dataChunkSize, 256);
}
tuple<bool, string, vector<uint8_t>, vector<uint8_t>> extractFromTestCredentialData(
const vector<uint8_t>& credentialData) {
string docType;
vector<uint8_t> storageKey;
vector<uint8_t> credentialPrivKey;
auto [item, _, message] = cppbor::parse(credentialData);
if (item == nullptr) {
return make_tuple(false, docType, storageKey, credentialPrivKey);
}
const cppbor::Array* arrayItem = item->asArray();
if (arrayItem == nullptr || arrayItem->size() != 3) {
return make_tuple(false, docType, storageKey, credentialPrivKey);
}
const cppbor::Tstr* docTypeItem = (*arrayItem)[0]->asTstr();
const cppbor::Bool* testCredentialItem =
((*arrayItem)[1]->asSimple() != nullptr ? ((*arrayItem)[1]->asSimple()->asBool())
: nullptr);
const cppbor::Bstr* encryptedCredentialKeysItem = (*arrayItem)[2]->asBstr();
if (docTypeItem == nullptr || testCredentialItem == nullptr ||
encryptedCredentialKeysItem == nullptr) {
return make_tuple(false, docType, storageKey, credentialPrivKey);
}
docType = docTypeItem->value();
vector<uint8_t> hardwareBoundKey = support::getTestHardwareBoundKey();
const vector<uint8_t>& encryptedCredentialKeys = encryptedCredentialKeysItem->value();
const vector<uint8_t> docTypeVec(docType.begin(), docType.end());
optional<vector<uint8_t>> decryptedCredentialKeys =
support::decryptAes128Gcm(hardwareBoundKey, encryptedCredentialKeys, docTypeVec);
if (!decryptedCredentialKeys) {
return make_tuple(false, docType, storageKey, credentialPrivKey);
}
auto [dckItem, dckPos, dckMessage] = cppbor::parse(decryptedCredentialKeys.value());
if (dckItem == nullptr) {
return make_tuple(false, docType, storageKey, credentialPrivKey);
}
const cppbor::Array* dckArrayItem = dckItem->asArray();
if (dckArrayItem == nullptr || dckArrayItem->size() != 2) {
return make_tuple(false, docType, storageKey, credentialPrivKey);
}
const cppbor::Bstr* storageKeyItem = (*dckArrayItem)[0]->asBstr();
const cppbor::Bstr* credentialPrivKeyItem = (*dckArrayItem)[1]->asBstr();
if (storageKeyItem == nullptr || credentialPrivKeyItem == nullptr) {
return make_tuple(false, docType, storageKey, credentialPrivKey);
}
storageKey = storageKeyItem->value();
credentialPrivKey = credentialPrivKeyItem->value();
return make_tuple(true, docType, storageKey, credentialPrivKey);
}
TEST_P(IdentityAidl, createAndRetrieveCredential) {
// First, generate a key-pair for the reader since its public key will be
// part of the request data.
@@ -155,6 +213,7 @@ TEST_P(IdentityAidl, createAndRetrieveCredential) {
writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature)
.isOk());
// Validate the proofOfProvisioning which was returned
optional<vector<uint8_t>> proofOfProvisioning =
support::coseSignGetPayload(proofOfProvisioningSignature);
ASSERT_TRUE(proofOfProvisioning);
@@ -215,6 +274,22 @@ TEST_P(IdentityAidl, createAndRetrieveCredential) {
credentialPubKey.value()));
writableCredential = nullptr;
// Extract doctype, storage key, and credentialPrivKey from credentialData... this works
// only because we asked for a test-credential meaning that the HBK is all zeroes.
auto [exSuccess, exDocType, exStorageKey, exCredentialPrivKey] =
extractFromTestCredentialData(credentialData);
ASSERT_TRUE(exSuccess);
ASSERT_EQ(exDocType, "org.iso.18013-5.2019.mdl");
// ... check that the public key derived from the private key matches what was
// in the certificate.
optional<vector<uint8_t>> exCredentialKeyPair =
support::ecPrivateKeyToKeyPair(exCredentialPrivKey);
ASSERT_TRUE(exCredentialKeyPair);
optional<vector<uint8_t>> exCredentialPubKey =
support::ecKeyPairGetPublicKey(exCredentialKeyPair.value());
ASSERT_TRUE(exCredentialPubKey);
ASSERT_EQ(exCredentialPubKey.value(), credentialPubKey.value());
// Now that the credential has been provisioned, read it back and check the
// correct data is returned.
sp<IIdentityCredential> credential;
@@ -244,7 +319,7 @@ TEST_P(IdentityAidl, createAndRetrieveCredential) {
cppbor::Array sessionTranscript = cppbor::Array()
.add(cppbor::Semantic(24, deviceEngagementBytes))
.add(cppbor::Semantic(24, eReaderPubBytes));
vector<uint8_t> sessionTranscriptBytes = sessionTranscript.encode();
vector<uint8_t> sessionTranscriptEncoded = sessionTranscript.encode();
vector<uint8_t> itemsRequestBytes =
cppbor::Map("nameSpaces",
@@ -272,14 +347,17 @@ TEST_P(IdentityAidl, createAndRetrieveCredential) {
" },\n"
"}",
cborPretty);
vector<uint8_t> dataToSign = cppbor::Array()
.add("ReaderAuthentication")
.add(sessionTranscript.clone())
.add(cppbor::Semantic(24, itemsRequestBytes))
.encode();
vector<uint8_t> encodedReaderAuthentication =
cppbor::Array()
.add("ReaderAuthentication")
.add(sessionTranscript.clone())
.add(cppbor::Semantic(24, itemsRequestBytes))
.encode();
vector<uint8_t> encodedReaderAuthenticationBytes =
cppbor::Semantic(24, encodedReaderAuthentication).encode();
optional<vector<uint8_t>> readerSignature =
support::coseSignEcDsa(readerKey, {}, // content
dataToSign, // detached content
support::coseSignEcDsa(readerKey, {}, // content
encodedReaderAuthenticationBytes, // detached content
readerCertificate.value());
ASSERT_TRUE(readerSignature);
@@ -287,15 +365,33 @@ TEST_P(IdentityAidl, createAndRetrieveCredential) {
vector<uint8_t> signingKeyBlob;
Certificate signingKeyCertificate;
ASSERT_TRUE(credential->generateSigningKeyPair(&signingKeyBlob, &signingKeyCertificate).isOk());
optional<vector<uint8_t>> signingPubKey =
support::certificateChainGetTopMostKey(signingKeyCertificate.encodedCertificate);
EXPECT_TRUE(signingPubKey);
// 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
// is in the certificate...
const vector<uint8_t> exDocTypeVec(exDocType.begin(), exDocType.end());
optional<vector<uint8_t>> exSigningPrivKey =
support::decryptAes128Gcm(exStorageKey, signingKeyBlob, exDocTypeVec);
ASSERT_TRUE(exSigningPrivKey);
optional<vector<uint8_t>> exSigningKeyPair =
support::ecPrivateKeyToKeyPair(exSigningPrivKey.value());
ASSERT_TRUE(exSigningKeyPair);
optional<vector<uint8_t>> exSigningPubKey =
support::ecKeyPairGetPublicKey(exSigningKeyPair.value());
ASSERT_TRUE(exSigningPubKey);
ASSERT_EQ(exSigningPubKey.value(), signingPubKey.value());
vector<RequestNamespace> requestedNamespaces = test_utils::buildRequestNamespaces(testEntries);
// OK to fail, not available in v1 HAL
credential->setRequestedNamespaces(requestedNamespaces).isOk();
credential->setRequestedNamespaces(requestedNamespaces);
// OK to fail, not available in v1 HAL
credential->setVerificationToken(verificationToken);
ASSERT_TRUE(credential
->startRetrieval(secureProfiles.value(), authToken, itemsRequestBytes,
signingKeyBlob, sessionTranscriptBytes,
signingKeyBlob, sessionTranscriptEncoded,
readerSignature.value(), testEntriesEntryCounts)
.isOk());
@@ -316,6 +412,9 @@ TEST_P(IdentityAidl, createAndRetrieveCredential) {
content.insert(content.end(), chunk.begin(), chunk.end());
}
EXPECT_EQ(content, entry.valueCbor);
// TODO: also use |exStorageKey| to decrypt data and check it's the same as whatt
// the HAL returns...
}
vector<uint8_t> mac;
@@ -336,7 +435,7 @@ TEST_P(IdentityAidl, createAndRetrieveCredential) {
" },\n"
"}",
cborPretty);
// The data that is MACed is ["DeviceAuthentication", sessionTranscriptBytes, docType,
// The data that is MACed is ["DeviceAuthentication", sessionTranscript, docType,
// deviceNameSpacesBytes] so build up that structure
cppbor::Array deviceAuthentication;
deviceAuthentication.add("DeviceAuthentication");
@@ -345,24 +444,80 @@ TEST_P(IdentityAidl, createAndRetrieveCredential) {
string docType = "org.iso.18013-5.2019.mdl";
deviceAuthentication.add(docType);
deviceAuthentication.add(cppbor::Semantic(24, deviceNameSpacesBytes));
vector<uint8_t> encodedDeviceAuthentication = deviceAuthentication.encode();
optional<vector<uint8_t>> signingPublicKey =
support::certificateChainGetTopMostKey(signingKeyCertificate.encodedCertificate);
EXPECT_TRUE(signingPublicKey);
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(signingPublicKey.value(), readerEphemeralPrivateKey.value());
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(sharedSecret.value(), salt, info, 32);
optional<vector<uint8_t>> derivedKey =
support::hkdf(sharedSecretWithSessionTranscriptBytes, salt, info, 32);
ASSERT_TRUE(derivedKey);
optional<vector<uint8_t>> calculatedMac =
support::coseMac0(derivedKey.value(), {}, // payload
encodedDeviceAuthentication); // detached content
support::coseMac0(derivedKey.value(), {}, // payload
deviceAuthenticationBytes); // detached content
ASSERT_TRUE(calculatedMac);
EXPECT_EQ(mac, calculatedMac);
// Also perform an additional empty request. This is what mDL applications
// are envisioned to do - one call to get the data elements, another to get
// an empty DeviceSignedItems and corresponding MAC.
//
credential->setRequestedNamespaces({}); // OK to fail, not available in v1 HAL
ASSERT_TRUE(credential
->startRetrieval(
secureProfiles.value(), authToken, {}, // itemsRequestBytes
signingKeyBlob, sessionTranscriptEncoded, {}, // readerSignature,
testEntriesEntryCounts)
.isOk());
ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesBytes).isOk());
cborPretty = support::cborPrettyPrint(deviceNameSpacesBytes, 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
ASSERT_TRUE(calculatedMac);
EXPECT_EQ(mac, calculatedMac);
// Some mDL apps might send a request but with a single empty
// namespace. Check that too.
RequestNamespace emptyRequestNS;
emptyRequestNS.namespaceName = "PersonalData";
credential->setRequestedNamespaces({emptyRequestNS}); // OK to fail, not available in v1 HAL
ASSERT_TRUE(credential
->startRetrieval(
secureProfiles.value(), authToken, {}, // itemsRequestBytes
signingKeyBlob, sessionTranscriptEncoded, {}, // readerSignature,
testEntriesEntryCounts)
.isOk());
ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesBytes).isOk());
cborPretty = support::cborPrettyPrint(deviceNameSpacesBytes, 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
ASSERT_TRUE(calculatedMac);
EXPECT_EQ(mac, calculatedMac);
}

View File

@@ -69,11 +69,10 @@ TEST_P(IdentityCredentialTests, verifyAttestationWithEmptyChallenge) {
result = writableCredential->getAttestationCertificate(
attestationApplicationId, attestationChallenge, &attestationCertificate);
EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
<< endl;
EXPECT_TRUE(test_utils::validateAttestationCertificate(
attestationCertificate, attestationChallenge, attestationApplicationId, hwInfo));
EXPECT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
<< endl;
EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
EXPECT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
}
TEST_P(IdentityCredentialTests, verifyAttestationSuccessWithChallenge) {
@@ -130,6 +129,7 @@ TEST_P(IdentityCredentialTests, verifyStartPersonalization) {
// First call should go through
const vector<int32_t> entryCounts = {2, 4};
writableCredential->setExpectedProofOfProvisioningSize(123456);
result = writableCredential->startPersonalization(5, entryCounts);
ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
<< endl;
@@ -151,18 +151,8 @@ TEST_P(IdentityCredentialTests, verifyStartPersonalizationMin) {
// Verify minimal number of profile count and entry count
const vector<int32_t> entryCounts = {1, 1};
writableCredential->startPersonalization(1, entryCounts);
EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
<< endl;
}
TEST_P(IdentityCredentialTests, verifyStartPersonalizationZero) {
Status result;
sp<IWritableIdentityCredential> writableCredential;
ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
const vector<int32_t> entryCounts = {0};
writableCredential->startPersonalization(0, entryCounts);
writableCredential->setExpectedProofOfProvisioningSize(123456);
result = writableCredential->startPersonalization(1, entryCounts);
EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
<< endl;
}
@@ -174,7 +164,8 @@ TEST_P(IdentityCredentialTests, verifyStartPersonalizationOne) {
// Verify minimal number of profile count and entry count
const vector<int32_t> entryCounts = {1};
writableCredential->startPersonalization(1, entryCounts);
writableCredential->setExpectedProofOfProvisioningSize(123456);
result = writableCredential->startPersonalization(1, entryCounts);
EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
<< endl;
}
@@ -186,7 +177,8 @@ TEST_P(IdentityCredentialTests, verifyStartPersonalizationLarge) {
// Verify set a large number of profile count and entry count is ok
const vector<int32_t> entryCounts = {3000};
writableCredential->startPersonalization(3500, entryCounts);
writableCredential->setExpectedProofOfProvisioningSize(123456);
result = writableCredential->startPersonalization(25, entryCounts);
EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
<< endl;
}
@@ -198,7 +190,8 @@ TEST_P(IdentityCredentialTests, verifyProfileNumberMismatchShouldFail) {
// Enter mismatched entry and profile numbers
const vector<int32_t> entryCounts = {5, 6};
writableCredential->startPersonalization(5, entryCounts);
writableCredential->setExpectedProofOfProvisioningSize(123456);
result = writableCredential->startPersonalization(5, entryCounts);
ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
<< endl;
@@ -234,7 +227,8 @@ TEST_P(IdentityCredentialTests, verifyDuplicateProfileId) {
ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
const vector<int32_t> entryCounts = {3, 6};
writableCredential->startPersonalization(3, entryCounts);
writableCredential->setExpectedProofOfProvisioningSize(123456);
result = writableCredential->startPersonalization(3, entryCounts);
ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
<< endl;
@@ -251,9 +245,10 @@ TEST_P(IdentityCredentialTests, verifyDuplicateProfileId) {
SecureAccessControlProfile profile;
Certificate cert;
cert.encodedCertificate = testProfile.readerCertificate;
int64_t secureUserId = testProfile.userAuthenticationRequired ? 66 : 0;
result = writableCredential->addAccessControlProfile(
testProfile.id, cert, testProfile.userAuthenticationRequired,
testProfile.timeoutMillis, 0, &profile);
testProfile.timeoutMillis, secureUserId, &profile);
if (expectOk) {
expectOk = false;
@@ -554,7 +549,7 @@ TEST_P(IdentityCredentialTests, verifyEmptyNameSpaceMixedWithNonEmptyWorks) {
;
// OK to fail, not available in v1 HAL
writableCredential->setExpectedProofOfProvisioningSize(expectedPoPSize);
writableCredential->startPersonalization(3, entryCounts);
result = writableCredential->startPersonalization(3, entryCounts);
ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
<< endl;
@@ -608,7 +603,8 @@ TEST_P(IdentityCredentialTests, verifyInterleavingEntryNameSpaceOrderingFails) {
// before "Image" and 2 after image, which is not correct. All of same name
// space should occur together. Let's see if this fails.
const vector<int32_t> entryCounts = {2u, 1u, 2u};
writableCredential->startPersonalization(3, entryCounts);
writableCredential->setExpectedProofOfProvisioningSize(123456);
result = writableCredential->startPersonalization(3, entryCounts);
ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
<< endl;
@@ -674,6 +670,7 @@ TEST_P(IdentityCredentialTests, verifyAccessControlProfileIdOutOfRange) {
ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
const vector<int32_t> entryCounts = {1};
writableCredential->setExpectedProofOfProvisioningSize(123456);
Status result = writableCredential->startPersonalization(1, entryCounts);
ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
<< endl;

View File

@@ -96,9 +96,10 @@ optional<vector<SecureAccessControlProfile>> addAccessControlProfiles(
SecureAccessControlProfile profile;
Certificate cert;
cert.encodedCertificate = testProfile.readerCertificate;
int64_t secureUserId = testProfile.userAuthenticationRequired ? 66 : 0;
result = writableCredential->addAccessControlProfile(
testProfile.id, cert, testProfile.userAuthenticationRequired,
testProfile.timeoutMillis, 0, &profile);
testProfile.timeoutMillis, secureUserId, &profile);
// Don't use assert so all errors can be outputed. Then return
// instead of exit even on errors so caller can decide.

View File

@@ -33,6 +33,7 @@ using ::std::optional;
using ::std::string;
using ::std::tuple;
using ::std::vector;
using ::std::pair;
// ---------------------------------------------------------------------------
// Miscellaneous utilities.
@@ -119,6 +120,12 @@ optional<vector<uint8_t>> encryptAes128Gcm(const vector<uint8_t>& key, const vec
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<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.
//
@@ -134,6 +141,11 @@ optional<vector<uint8_t>> ecKeyPairGetPublicKey(const vector<uint8_t>& keyPair);
//
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..
//
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
// 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
@@ -150,6 +162,12 @@ optional<vector<uint8_t>> ecKeyPairGetPkcs12(const vector<uint8_t>& keyPair, con
//
optional<vector<uint8_t>> signEcDsa(const vector<uint8_t>& key, const vector<uint8_t>& data);
// Like signEcDsa() but instead of taking the data to be signed, takes a digest
// of it instead.
//
optional<vector<uint8_t>> signEcDsaDigest(const vector<uint8_t>& key,
const vector<uint8_t>& dataDigest);
// Calculates the HMAC with SHA-256 for |data| using |key|. The calculated HMAC
// is returned and will be 32 bytes.
//
@@ -170,6 +188,27 @@ bool checkEcDsaSignature(const vector<uint8_t>& digest, const vector<uint8_t>& s
//
optional<vector<uint8_t>> certificateChainGetTopMostKey(const vector<uint8_t>& certificateChain);
// Extracts the public-key from the top-most certificate in |certificateChain|
// (which should be a concatenated chain of DER-encoded X.509 certificates).
//
// Return offset and size of the public-key
//
optional<pair<size_t, size_t>> certificateFindPublicKey(const vector<uint8_t>& x509Certificate);
// Extracts the TbsCertificate from the top-most certificate in |certificateChain|
// (which should be a concatenated chain of DER-encoded X.509 certificates).
//
// Return offset and size of the TbsCertificate
//
optional<pair<size_t, size_t>> certificateTbsCertificate(const vector<uint8_t>& x509Certificate);
// Extracts the Signature from the top-most certificate in |certificateChain|
// (which should be a concatenated chain of DER-encoded X.509 certificates).
//
// Return offset and size of the Signature
//
optional<pair<size_t, size_t>> certificateFindSignature(const vector<uint8_t>& x509Certificate);
// Generates a X.509 certificate for |publicKey| (which must be in the format
// returned by ecKeyPairGetPublicKey()).
//
@@ -226,6 +265,11 @@ optional<vector<vector<uint8_t>>> certificateChainSplit(const vector<uint8_t>& c
//
bool certificateChainValidate(const vector<uint8_t>& certificateChain);
// Returns true if |certificate| is signed by |publicKey|.
//
bool certificateSignedByPublicKey(const vector<uint8_t>& certificate,
const vector<uint8_t>& publicKey);
// Signs |data| and |detachedContent| with |key| (which must be in the format
// returned by ecKeyPairGetPrivateKey()).
//
@@ -238,6 +282,21 @@ optional<vector<uint8_t>> coseSignEcDsa(const vector<uint8_t>& key, const vector
const vector<uint8_t>& detachedContent,
const vector<uint8_t>& certificateChain);
// Creates a COSE_Signature1 where |signatureToBeSigned| is the ECDSA signature
// of the ToBeSigned CBOR from RFC 8051 "4.4. Signing and Verification Process".
//
// The |signatureToBeSigned| is expected to be 64 bytes and contain the R value,
// then the S value.
//
// The |data| parameter will be included in the COSE_Sign1 CBOR.
//
// If |certificateChain| is non-empty it's included in the 'x5chain'
// protected header element (as as described in'draft-ietf-cose-x509-04').
//
optional<vector<uint8_t>> coseSignEcDsaWithSignature(const vector<uint8_t>& signatureToBeSigned,
const vector<uint8_t>& data,
const vector<uint8_t>& certificateChain);
// Checks that |signatureCoseSign1| (in COSE_Sign1 format) is a valid signature
// made with |public_key| (which must be in the format returned by
// ecKeyPairGetPublicKey()) where |detachedContent| is the detached content.
@@ -246,9 +305,23 @@ bool coseCheckEcDsaSignature(const vector<uint8_t>& signatureCoseSign1,
const vector<uint8_t>& detachedContent,
const vector<uint8_t>& publicKey);
// Converts a DER-encoded signature to the format used in 'signature' bstr in COSE_Sign1.
bool ecdsaSignatureDerToCose(const vector<uint8_t>& ecdsaDerSignature,
vector<uint8_t>& ecdsaCoseSignature);
// Converts from the format in in 'signature' bstr in COSE_Sign1 to DER encoding.
bool ecdsaSignatureCoseToDer(const vector<uint8_t>& ecdsaCoseSignature,
vector<uint8_t>& ecdsaDerSignature);
// Extracts the payload from a COSE_Sign1.
optional<vector<uint8_t>> coseSignGetPayload(const vector<uint8_t>& signatureCoseSign1);
// Extracts the signature (of the ToBeSigned CBOR) from a COSE_Sign1.
optional<vector<uint8_t>> coseSignGetSignature(const vector<uint8_t>& signatureCoseSign1);
// Extracts the signature algorithm from a COSE_Sign1.
optional<int> coseSignGetAlg(const vector<uint8_t>& signatureCoseSign1);
// Extracts the X.509 certificate chain, if present. Returns the data as a
// concatenated chain of DER-encoded X.509 certificates
//
@@ -264,6 +337,16 @@ optional<vector<uint8_t>> coseSignGetX5Chain(const vector<uint8_t>& signatureCos
optional<vector<uint8_t>> coseMac0(const vector<uint8_t>& key, const vector<uint8_t>& data,
const vector<uint8_t>& detachedContent);
// Creates a COSE_Mac0 where |digestToBeMaced| is the HMAC-SHA256
// of the ToBeMaced CBOR from RFC 8051 "6.3. How to Compute and Verify a MAC".
//
// The |digestToBeMaced| is expected to be 32 bytes.
//
// The |data| parameter will be included in the COSE_Mac0 CBOR.
//
optional<vector<uint8_t>> coseMacWithDigest(const vector<uint8_t>& digestToBeMaced,
const vector<uint8_t>& data);
// ---------------------------------------------------------------------------
// Utility functions specific to IdentityCredential.
// ---------------------------------------------------------------------------

View File

@@ -24,6 +24,7 @@
#include <stdarg.h>
#include <stdio.h>
#include <time.h>
#include <chrono>
#include <iomanip>
#include <openssl/aes.h>
@@ -684,6 +685,48 @@ static bool parseX509Certificates(const vector<uint8_t>& certificateChain,
return true;
}
bool certificateSignedByPublicKey(const vector<uint8_t>& certificate,
const vector<uint8_t>& publicKey) {
const unsigned char* p = certificate.data();
auto x509 = X509_Ptr(d2i_X509(nullptr, &p, certificate.size()));
if (x509 == nullptr) {
LOG(ERROR) << "Error parsing X509 certificate";
return false;
}
auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
auto point = EC_POINT_Ptr(EC_POINT_new(group.get()));
if (EC_POINT_oct2point(group.get(), point.get(), publicKey.data(), publicKey.size(), nullptr) !=
1) {
LOG(ERROR) << "Error decoding publicKey";
return false;
}
auto ecKey = EC_KEY_Ptr(EC_KEY_new());
auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
if (ecKey.get() == nullptr || pkey.get() == nullptr) {
LOG(ERROR) << "Memory allocation failed";
return false;
}
if (EC_KEY_set_group(ecKey.get(), group.get()) != 1) {
LOG(ERROR) << "Error setting group";
return false;
}
if (EC_KEY_set_public_key(ecKey.get(), point.get()) != 1) {
LOG(ERROR) << "Error setting point";
return false;
}
if (EVP_PKEY_set1_EC_KEY(pkey.get(), ecKey.get()) != 1) {
LOG(ERROR) << "Error setting key";
return false;
}
if (X509_verify(x509.get(), pkey.get()) != 1) {
return false;
}
return true;
}
// TODO: Right now the only check we perform is to check that each certificate
// is signed by its successor. We should - but currently don't - also check
// things like valid dates etc.
@@ -770,7 +813,8 @@ vector<uint8_t> sha256(const vector<uint8_t>& data) {
return ret;
}
optional<vector<uint8_t>> signEcDsa(const vector<uint8_t>& key, const vector<uint8_t>& data) {
optional<vector<uint8_t>> signEcDsaDigest(const vector<uint8_t>& key,
const vector<uint8_t>& dataDigest) {
auto bn = BIGNUM_Ptr(BN_bin2bn(key.data(), key.size(), nullptr));
if (bn.get() == nullptr) {
LOG(ERROR) << "Error creating BIGNUM";
@@ -783,8 +827,7 @@ optional<vector<uint8_t>> signEcDsa(const vector<uint8_t>& key, const vector<uin
return {};
}
auto digest = sha256(data);
ECDSA_SIG* sig = ECDSA_do_sign(digest.data(), digest.size(), ec_key.get());
ECDSA_SIG* sig = ECDSA_do_sign(dataDigest.data(), dataDigest.size(), ec_key.get());
if (sig == nullptr) {
LOG(ERROR) << "Error signing digest";
return {};
@@ -798,6 +841,10 @@ optional<vector<uint8_t>> signEcDsa(const vector<uint8_t>& key, const vector<uin
return signature;
}
optional<vector<uint8_t>> signEcDsa(const vector<uint8_t>& key, const vector<uint8_t>& data) {
return signEcDsaDigest(key, sha256(data));
}
optional<vector<uint8_t>> hmacSha256(const vector<uint8_t>& key, const vector<uint8_t>& data) {
HMAC_CTX ctx;
HMAC_CTX_init(&ctx);
@@ -955,6 +1002,51 @@ optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> createEcKeyPairAnd
return make_pair(keyPair, attestationCert.value());
}
optional<vector<vector<uint8_t>>> createAttestationForEcPublicKey(
const vector<uint8_t>& publicKey, const vector<uint8_t>& challenge,
const vector<uint8_t>& applicationId) {
auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
auto point = EC_POINT_Ptr(EC_POINT_new(group.get()));
if (EC_POINT_oct2point(group.get(), point.get(), publicKey.data(), publicKey.size(), nullptr) !=
1) {
LOG(ERROR) << "Error decoding publicKey";
return {};
}
auto ecKey = EC_KEY_Ptr(EC_KEY_new());
auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
if (ecKey.get() == nullptr || pkey.get() == nullptr) {
LOG(ERROR) << "Memory allocation failed";
return {};
}
if (EC_KEY_set_group(ecKey.get(), group.get()) != 1) {
LOG(ERROR) << "Error setting group";
return {};
}
if (EC_KEY_set_public_key(ecKey.get(), point.get()) != 1) {
LOG(ERROR) << "Error setting point";
return {};
}
if (EVP_PKEY_set1_EC_KEY(pkey.get(), ecKey.get()) != 1) {
LOG(ERROR) << "Error setting key";
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;
optional<vector<vector<uint8_t>>> attestationCert =
createAttestation(pkey.get(), applicationId, challenge, now * 1000, expireTimeMs);
if (!attestationCert) {
LOG(ERROR) << "Error create attestation from key and challenge";
return {};
}
return attestationCert.value();
}
optional<vector<uint8_t>> createEcKeyPair() {
auto ec_key = EC_KEY_Ptr(EC_KEY_new());
auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
@@ -1047,6 +1139,42 @@ optional<vector<uint8_t>> ecKeyPairGetPrivateKey(const vector<uint8_t>& keyPair)
return privateKey;
}
optional<vector<uint8_t>> ecPrivateKeyToKeyPair(const vector<uint8_t>& privateKey) {
auto bn = BIGNUM_Ptr(BN_bin2bn(privateKey.data(), privateKey.size(), nullptr));
if (bn.get() == nullptr) {
LOG(ERROR) << "Error creating BIGNUM";
return {};
}
auto ecKey = EC_KEY_Ptr(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
if (EC_KEY_set_private_key(ecKey.get(), bn.get()) != 1) {
LOG(ERROR) << "Error setting private key from BIGNUM";
return {};
}
auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
if (pkey.get() == nullptr) {
LOG(ERROR) << "Memory allocation failed";
return {};
}
if (EVP_PKEY_set1_EC_KEY(pkey.get(), ecKey.get()) != 1) {
LOG(ERROR) << "Error getting private key";
return {};
}
int size = i2d_PrivateKey(pkey.get(), nullptr);
if (size == 0) {
LOG(ERROR) << "Error generating public key encoding";
return {};
}
vector<uint8_t> keyPair;
keyPair.resize(size);
unsigned char* p = keyPair.data();
i2d_PrivateKey(pkey.get(), &p);
return keyPair;
}
optional<vector<uint8_t>> ecKeyPairGetPkcs12(const vector<uint8_t>& keyPair, const string& name,
const string& serialDecimal, const string& issuer,
const string& subject, time_t validityNotBefore,
@@ -1441,6 +1569,120 @@ optional<vector<uint8_t>> certificateChainGetTopMostKey(const vector<uint8_t>& c
return publicKey;
}
optional<pair<size_t, size_t>> certificateFindPublicKey(const vector<uint8_t>& x509Certificate) {
vector<X509_Ptr> certs;
if (!parseX509Certificates(x509Certificate, certs)) {
return {};
}
if (certs.size() < 1) {
LOG(ERROR) << "No certificates in chain";
return {};
}
auto pkey = EVP_PKEY_Ptr(X509_get_pubkey(certs[0].get()));
if (pkey.get() == nullptr) {
LOG(ERROR) << "No public key";
return {};
}
auto ecKey = EC_KEY_Ptr(EVP_PKEY_get1_EC_KEY(pkey.get()));
if (ecKey.get() == nullptr) {
LOG(ERROR) << "Failed getting EC key";
return {};
}
auto ecGroup = EC_KEY_get0_group(ecKey.get());
auto ecPoint = EC_KEY_get0_public_key(ecKey.get());
int size = EC_POINT_point2oct(ecGroup, ecPoint, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0,
nullptr);
if (size == 0) {
LOG(ERROR) << "Error generating public key encoding";
return {};
}
vector<uint8_t> publicKey;
publicKey.resize(size);
EC_POINT_point2oct(ecGroup, ecPoint, POINT_CONVERSION_UNCOMPRESSED, publicKey.data(),
publicKey.size(), nullptr);
size_t publicKeyOffset = 0;
size_t publicKeySize = (size_t)size;
void* location = memmem((const void*)x509Certificate.data(), x509Certificate.size(),
(const void*)publicKey.data(), publicKey.size());
if (location == NULL) {
LOG(ERROR) << "Error finding publicKey from x509Certificate";
return {};
}
publicKeyOffset = (size_t)((const char*)location - (const char*)x509Certificate.data());
return std::make_pair(publicKeyOffset, publicKeySize);
}
optional<pair<size_t, size_t>> certificateTbsCertificate(const vector<uint8_t>& x509Certificate) {
vector<X509_Ptr> certs;
if (!parseX509Certificates(x509Certificate, certs)) {
return {};
}
if (certs.size() < 1) {
LOG(ERROR) << "No certificates in chain";
return {};
}
unsigned char* buf = NULL;
int len = i2d_re_X509_tbs(certs[0].get(), &buf);
if ((len < 0) || (buf == NULL)) {
LOG(ERROR) << "fail to extract tbsCertificate in x509Certificate";
return {};
}
vector<uint8_t> tbsCertificate(len);
memcpy(tbsCertificate.data(), buf, len);
size_t tbsCertificateOffset = 0;
size_t tbsCertificateSize = (size_t)len;
void* location = memmem((const void*)x509Certificate.data(), x509Certificate.size(),
(const void*)tbsCertificate.data(), tbsCertificate.size());
if (location == NULL) {
LOG(ERROR) << "Error finding tbsCertificate from x509Certificate";
return {};
}
tbsCertificateOffset = (size_t)((const char*)location - (const char*)x509Certificate.data());
return std::make_pair(tbsCertificateOffset, tbsCertificateSize);
}
optional<pair<size_t, size_t>> certificateFindSignature(const vector<uint8_t>& x509Certificate) {
vector<X509_Ptr> certs;
if (!parseX509Certificates(x509Certificate, certs)) {
return {};
}
if (certs.size() < 1) {
LOG(ERROR) << "No certificates in chain";
return {};
}
ASN1_BIT_STRING* psig;
X509_ALGOR* palg;
X509_get0_signature((const ASN1_BIT_STRING**)&psig, (const X509_ALGOR**)&palg, certs[0].get());
vector<char> signature(psig->length);
memcpy(signature.data(), psig->data, psig->length);
size_t signatureOffset = 0;
size_t signatureSize = (size_t)psig->length;
void* location = memmem((const void*)x509Certificate.data(), x509Certificate.size(),
(const void*)signature.data(), signature.size());
if (location == NULL) {
LOG(ERROR) << "Error finding signature from x509Certificate";
return {};
}
signatureOffset = (size_t)((const char*)location - (const char*)x509Certificate.data());
return std::make_pair(signatureOffset, signatureSize);
}
// ---------------------------------------------------------------------------
// COSE Utility Functions
// ---------------------------------------------------------------------------
@@ -1538,6 +1780,55 @@ bool ecdsaSignatureDerToCose(const vector<uint8_t>& ecdsaDerSignature,
return true;
}
optional<vector<uint8_t>> coseSignEcDsaWithSignature(const vector<uint8_t>& signatureToBeSigned,
const vector<uint8_t>& data,
const vector<uint8_t>& certificateChain) {
if (signatureToBeSigned.size() != 64) {
LOG(ERROR) << "Invalid size for signatureToBeSigned, expected 64 got "
<< signatureToBeSigned.size();
return {};
}
cppbor::Map unprotectedHeaders;
cppbor::Map protectedHeaders;
protectedHeaders.add(COSE_LABEL_ALG, COSE_ALG_ECDSA_256);
if (certificateChain.size() != 0) {
optional<vector<vector<uint8_t>>> certs = support::certificateChainSplit(certificateChain);
if (!certs) {
LOG(ERROR) << "Error splitting certificate chain";
return {};
}
if (certs.value().size() == 1) {
unprotectedHeaders.add(COSE_LABEL_X5CHAIN, certs.value()[0]);
} else {
cppbor::Array certArray;
for (const vector<uint8_t>& cert : certs.value()) {
certArray.add(cert);
}
unprotectedHeaders.add(COSE_LABEL_X5CHAIN, std::move(certArray));
}
}
vector<uint8_t> encodedProtectedHeaders = coseEncodeHeaders(protectedHeaders);
cppbor::Array coseSign1;
coseSign1.add(encodedProtectedHeaders);
coseSign1.add(std::move(unprotectedHeaders));
if (data.size() == 0) {
cppbor::Null nullValue;
coseSign1.add(std::move(nullValue));
} else {
coseSign1.add(data);
}
coseSign1.add(signatureToBeSigned);
vector<uint8_t> signatureCoseSign1;
signatureCoseSign1 = coseSign1.encode();
return signatureCoseSign1;
}
optional<vector<uint8_t>> coseSignEcDsa(const vector<uint8_t>& key, const vector<uint8_t>& data,
const vector<uint8_t>& detachedContent,
const vector<uint8_t>& certificateChain) {
@@ -1673,6 +1964,35 @@ bool coseCheckEcDsaSignature(const vector<uint8_t>& signatureCoseSign1,
return true;
}
// Extracts the signature (of the ToBeSigned CBOR) from a COSE_Sign1.
optional<vector<uint8_t>> coseSignGetSignature(const vector<uint8_t>& signatureCoseSign1) {
auto [item, _, message] = cppbor::parse(signatureCoseSign1);
if (item == nullptr) {
LOG(ERROR) << "Passed-in COSE_Sign1 is not valid CBOR: " << message;
return {};
}
const cppbor::Array* array = item->asArray();
if (array == nullptr) {
LOG(ERROR) << "Value for COSE_Sign1 is not an array";
return {};
}
if (array->size() != 4) {
LOG(ERROR) << "Value for COSE_Sign1 is not an array of size 4";
return {};
}
vector<uint8_t> signature;
const cppbor::Bstr* signatureAsBstr = (*array)[3]->asBstr();
if (signatureAsBstr == nullptr) {
LOG(ERROR) << "Value for signature is not a bstr";
return {};
}
// Copy payload into |data|
signature = signatureAsBstr->value();
return signature;
}
optional<vector<uint8_t>> coseSignGetPayload(const vector<uint8_t>& signatureCoseSign1) {
auto [item, _, message] = cppbor::parse(signatureCoseSign1);
if (item == nullptr) {
@@ -1710,6 +2030,59 @@ optional<vector<uint8_t>> coseSignGetPayload(const vector<uint8_t>& signatureCos
return data;
}
optional<int> coseSignGetAlg(const vector<uint8_t>& signatureCoseSign1) {
auto [item, _, message] = cppbor::parse(signatureCoseSign1);
if (item == nullptr) {
LOG(ERROR) << "Passed-in COSE_Sign1 is not valid CBOR: " << message;
return {};
}
const cppbor::Array* array = item->asArray();
if (array == nullptr) {
LOG(ERROR) << "Value for COSE_Sign1 is not an array";
return {};
}
if (array->size() != 4) {
LOG(ERROR) << "Value for COSE_Sign1 is not an array of size 4";
return {};
}
const cppbor::Bstr* protectedHeadersBytes = (*array)[0]->asBstr();
if (protectedHeadersBytes == nullptr) {
LOG(ERROR) << "Value for protectedHeaders is not a bstr";
return {};
}
auto [item2, _2, message2] = cppbor::parse(protectedHeadersBytes->value());
if (item2 == nullptr) {
LOG(ERROR) << "Error parsing protectedHeaders: " << message2;
return {};
}
const cppbor::Map* protectedHeaders = item2->asMap();
if (protectedHeaders == nullptr) {
LOG(ERROR) << "Decoded CBOR for protectedHeaders is not a map";
return {};
}
for (size_t n = 0; n < protectedHeaders->size(); n++) {
auto [keyItem, valueItem] = (*protectedHeaders)[n];
const cppbor::Int* number = keyItem->asInt();
if (number == nullptr) {
LOG(ERROR) << "Key item in top-level map is not a number";
return {};
}
int label = number->value();
if (label == COSE_LABEL_ALG) {
const cppbor::Int* number = valueItem->asInt();
if (number != nullptr) {
return number->value();
}
LOG(ERROR) << "Value for COSE_LABEL_ALG label is not a number";
return {};
}
}
LOG(ERROR) << "Did not find COSE_LABEL_ALG label in protected headers";
return {};
}
optional<vector<uint8_t>> coseSignGetX5Chain(const vector<uint8_t>& signatureCoseSign1) {
auto [item, _, message] = cppbor::parse(signatureCoseSign1);
if (item == nullptr) {
@@ -1825,6 +2198,28 @@ optional<vector<uint8_t>> coseMac0(const vector<uint8_t>& key, const vector<uint
return array.encode();
}
optional<vector<uint8_t>> coseMacWithDigest(const vector<uint8_t>& digestToBeMaced,
const vector<uint8_t>& data) {
cppbor::Map unprotectedHeaders;
cppbor::Map protectedHeaders;
protectedHeaders.add(COSE_LABEL_ALG, COSE_ALG_HMAC_256_256);
vector<uint8_t> encodedProtectedHeaders = coseEncodeHeaders(protectedHeaders);
cppbor::Array array;
array.add(encodedProtectedHeaders);
array.add(std::move(unprotectedHeaders));
if (data.size() == 0) {
cppbor::Null nullValue;
array.add(std::move(nullValue));
} else {
array.add(data);
}
array.add(digestToBeMaced);
return array.encode();
}
// ---------------------------------------------------------------------------
// Utility functions specific to IdentityCredential.
// ---------------------------------------------------------------------------

View File

@@ -121,8 +121,8 @@ void appendUint64(std::vector<uint8_t>& vec, uint64_t value) {
uint64_t extractUint64(const std::vector<uint8_t>& data, size_t offset) {
uint64_t value = 0;
for (size_t n = 0; n < sizeof(uint64_t); n++) {
uint8_t byte = data[offset + n];
value |= byte << (n * 8);
uint64_t tmp = data[offset + n];
value |= (tmp << (n * 8));
}
return value;
}
@@ -137,8 +137,8 @@ void appendUint32(std::vector<uint8_t>& vec, uint32_t value) {
uint32_t extractUint32(const std::vector<uint8_t>& data, size_t offset) {
uint32_t value = 0;
for (size_t n = 0; n < sizeof(uint32_t); n++) {
uint8_t byte = data[offset + n];
value |= byte << (n * 8);
uint32_t tmp = data[offset + n];
value |= (tmp << (n * 8));
}
return value;
}

View File

@@ -438,10 +438,10 @@ bool verify_attestation_record(const string& challenge, const string& app_id,
EXPECT_TRUE(device_locked);
}
// Check that the expected result from VBMeta matches the build type. Only a user build
// should have AVB reporting the device is locked.
EXPECT_NE(property_get("ro.build.type", property_value, ""), 0);
if (!strcmp(property_value, "user")) {
// Check that the device is locked if not debuggable, e.g., user build
// images in CTS. For VTS, debuggable images are used to allow adb root
// and the device is unlocked.
if (!property_get_bool("ro.debuggable", false)) {
EXPECT_TRUE(device_locked);
} else {
EXPECT_FALSE(device_locked);

View File

@@ -74,5 +74,6 @@ cc_defaults {
// TODO(b/64437680): Assume these libs are always available on the device.
shared_libs: [
"libstagefright_foundation",
"libstagefright_omx_utils",
],
}

View File

@@ -33,6 +33,7 @@
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
#include <media/stagefright/omx/OMXUtils.h>
using ::android::sp;
using ::android::base::Join;
@@ -87,71 +88,6 @@ void displayComponentInfo(hidl_vec<IOmx::ComponentInfo>& nodeList) {
}
}
/*
* Returns the role based on is_encoder and mime.
*
* The mapping from a pair (is_encoder, mime) to a role string is
* defined in frameworks/av/media/libmedia/MediaDefs.cpp and
* frameworks/av/media/libstagefright/omx/OMXUtils.cpp. This function
* does essentially the same work as GetComponentRole() in
* OMXUtils.cpp.
*
* Args:
* is_encoder: A boolean indicating whether the role is for an
* encoder or a decoder.
* mime: A string of the desired mime type.
*
* Returns:
* A const string for the requested role name, empty if mime is not
* recognized.
*/
const std::string getComponentRole(bool isEncoder, const std::string mime) {
// Mapping from mime types to roles.
// These values come from MediaDefs.cpp and OMXUtils.cpp
const std::map<const std::string, const std::string> audioMimeToRole = {
{"3gpp", "amrnb"}, {"ac3", "ac3"}, {"amr-wb", "amrwb"},
{"eac3", "eac3"}, {"flac", "flac"}, {"g711-alaw", "g711alaw"},
{"g711-mlaw", "g711mlaw"}, {"gsm", "gsm"}, {"mp4a-latm", "aac"},
{"mpeg", "mp3"}, {"mpeg-L1", "mp1"}, {"mpeg-L2", "mp2"},
{"opus", "opus"}, {"raw", "raw"}, {"vorbis", "vorbis"},
};
const std::map<const std::string, const std::string> videoMimeToRole = {
{"3gpp", "h263"}, {"avc", "avc"}, {"dolby-vision", "dolby-vision"},
{"hevc", "hevc"}, {"mp4v-es", "mpeg4"}, {"mpeg2", "mpeg2"},
{"x-vnd.on2.vp8", "vp8"}, {"x-vnd.on2.vp9", "vp9"},
};
const std::map<const std::string, const std::string> imageMimeToRole = {
{"vnd.android.heic", "heic"},
};
// Suffix begins after the mime prefix.
const size_t prefixEnd = mime.find("/");
if (prefixEnd == std::string::npos || prefixEnd == mime.size()) return "";
const std::string mime_suffix = mime.substr(prefixEnd + 1, mime.size() - 1);
const std::string middle = isEncoder ? "encoder." : "decoder.";
std::string prefix;
std::string suffix;
if (mime.rfind("audio/", 0) != std::string::npos) {
const auto it = audioMimeToRole.find(mime_suffix);
if (it == audioMimeToRole.end()) return "";
prefix = "audio_";
suffix = it->second;
} else if (mime.rfind("video/", 0) != std::string::npos) {
const auto it = videoMimeToRole.find(mime_suffix);
if (it == videoMimeToRole.end()) return "";
prefix = "video_";
suffix = it->second;
} else if (mime.rfind("image/", 0) != std::string::npos) {
const auto it = imageMimeToRole.find(mime_suffix);
if (it == imageMimeToRole.end()) return "";
prefix = "image_";
suffix = it->second;
} else {
return "";
}
return prefix + middle + suffix;
}
void validateAttributes(
const std::map<const std::string, const testing::internal::RE>& knownPatterns,
const std::vector<const struct AttributePattern>& unknownPatterns,
@@ -315,7 +251,7 @@ TEST_P(MasterHidlTest, ListRoles) {
};
// Matching rules for node names and owners
const testing::internal::RE nodeNamePattern = "[a-zA-Z0-9.-]+";
const testing::internal::RE nodeNamePattern = "[a-zA-Z0-9._-]+";
const testing::internal::RE nodeOwnerPattern = "[a-zA-Z0-9._-]+";
std::set<const std::string> roleKeys;
@@ -328,7 +264,8 @@ TEST_P(MasterHidlTest, ListRoles) {
// Make sure role name follows expected format based on type and
// isEncoder
const std::string role_name = getComponentRole(role.isEncoder, role.type);
const std::string role_name(
::android::GetComponentRole(role.isEncoder, role.type.c_str()));
EXPECT_EQ(role_name, role.role) << "Role \"" << role.role << "\" does not match "
<< (role.isEncoder ? "an encoder " : "a decoder ")
<< "for mime type \"" << role.type << ".";

View File

@@ -62,11 +62,12 @@ cc_test {
defaults: ["neuralnetworks_vts_functional_defaults"],
srcs: [
"BasicTests.cpp",
"GeneratedTestHarness.cpp",
"TestAssertions.cpp",
"TestMain.cpp",
"ValidateModel.cpp",
"ValidateRequest.cpp",
"VtsHalNeuralnetworks.cpp",
"GeneratedTestHarness.cpp",
],
shared_libs: [
"libfmq",

View File

@@ -26,10 +26,6 @@
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<!-- b/155577050, temporarily disable the failing tests.
Must be deleted after corresponding driver issues are fixed.
-->
<option name="native-test-flag" value="--gtest_filter=-*Validation*:*CycleTest*:*sample_float_fast*:*sample_float_slow*:*sample_minimal*:*sample_quant*" />
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="VtsHalNeuralnetworksV1_0TargetTest" />
</test>

View File

@@ -0,0 +1,25 @@
/*
* 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 "1.0/LogTestCaseToLogcat.h"
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
testing::UnitTest::GetInstance()->listeners().Append(
new android::hardware::neuralnetworks::LogTestCaseToLogcat());
return RUN_ALL_TESTS();
}

View File

@@ -0,0 +1,40 @@
/*
* 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_NEURALNETWORKS_V1_0_LOG_TEST_CASE_TO_LOGCAT_H
#define ANDROID_HARDWARE_NEURALNETWORKS_V1_0_LOG_TEST_CASE_TO_LOGCAT_H
#include <android-base/logging.h>
#include <gtest/gtest.h>
namespace android::hardware::neuralnetworks {
class LogTestCaseToLogcat : public ::testing::EmptyTestEventListener {
public:
void OnTestStart(const ::testing::TestInfo& test_info) override {
LOG(INFO) << "[Test Case] " << test_info.test_suite_name() << "." << test_info.name()
<< " BEGIN";
}
void OnTestEnd(const ::testing::TestInfo& test_info) override {
LOG(INFO) << "[Test Case] " << test_info.test_suite_name() << "." << test_info.name()
<< " END";
}
};
} // namespace android::hardware::neuralnetworks
#endif // ANDROID_HARDWARE_NEURALNETWORKS_V1_0_LOG_TEST_CASE_TO_LOGCAT_H

View File

@@ -20,6 +20,7 @@ cc_test {
srcs: [
"BasicTests.cpp",
"TestAssertions.cpp",
"TestMain.cpp",
"ValidateModel.cpp",
"ValidateRequest.cpp",
"VtsHalNeuralnetworks.cpp",

View File

@@ -26,10 +26,6 @@
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<!-- b/155577050, temporarily disable the failing tests.
Must be deleted after corresponding driver issues are fixed.
-->
<option name="native-test-flag" value="--gtest_filter=-*Validation*:*CycleTest*:*sample_float_fast*:*sample_float_slow*:*sample_minimal*:*sample_quant*" />
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="VtsHalNeuralnetworksV1_1TargetTest" />
</test>

View File

@@ -0,0 +1,25 @@
/*
* 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 "1.0/LogTestCaseToLogcat.h"
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
testing::UnitTest::GetInstance()->listeners().Append(
new android::hardware::neuralnetworks::LogTestCaseToLogcat());
return RUN_ALL_TESTS();
}

View File

@@ -40,6 +40,7 @@ cc_test {
"CompilationCachingTests.cpp",
"GeneratedTestHarness.cpp",
"TestAssertions.cpp",
"TestMain.cpp",
"ValidateBurst.cpp",
"ValidateModel.cpp",
"ValidateRequest.cpp",

View File

@@ -26,10 +26,6 @@
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<!-- b/155577050, b/155674368, b/153876253, temporarily disable the test.
Must be deleted after corresponding driver issues are fixed.
-->
<option name="native-test-flag" value="--gtest_filter=-*Validation*:*squeeze*_all*_inputs*:*strided_slice*_all*_inputs*:*transpose*_all*_inputs*:*l2_normalization_axis_corner_case*:*sample_float_fast*:*sample_float_slow*:*sample_minimal*:*sample_quant*" />
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="VtsHalNeuralnetworksV1_2TargetTest" />
</test>

View File

@@ -0,0 +1,25 @@
/*
* 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 "1.0/LogTestCaseToLogcat.h"
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
testing::UnitTest::GetInstance()->listeners().Append(
new android::hardware::neuralnetworks::LogTestCaseToLogcat());
return RUN_ALL_TESTS();
}

View File

@@ -21,6 +21,7 @@
#include <android/hardware/neuralnetworks/1.2/IPreparedModel.h>
#include <android/hardware/neuralnetworks/1.2/types.h>
#include <gtest/gtest.h>
#include <vector>
#include "1.0/Utils.h"
#include "1.2/Callbacks.h"

View File

@@ -5102,11 +5102,15 @@ enum OperationType : int32_t {
* The inputs and outputs of the two referenced subgraphs must agree with the
* signature of this operation. That is, if the operation has (3 + n) inputs
* and m outputs, both subgraphs must have n inputs and m outputs with the same
* types as the corresponding operation inputs and outputs.
* types, ranks, dimensions, scales,
* zeroPoints, and extraParams as the corresponding operation inputs and
* outputs.
* All of the operands mentioned must have fully specified dimensions.
*
* Inputs:
* * 0: A value of type {@link OperandType::TENSOR_BOOL8} and shape [1]
* that determines which of the two referenced subgraphs to execute.
* The operand must have fully specified dimensions.
* * 1: A {@link OperandType::SUBGRAPH} reference to the subgraph to be
* executed if the condition is true.
* * 2: A {@link OperandType::SUBGRAPH} reference to the subgraph to be
@@ -5165,13 +5169,17 @@ enum OperationType : int32_t {
* Inputs:
* * 0: A {@link OperandType::SUBGRAPH} reference to the condition
* subgraph. The subgraph must have (m + k + n) inputs with
* the same types as the corresponding inputs of the WHILE operation
* and exactly one output of {@link OperandType::TENSOR_BOOL8}
* and shape [1].
* the same types, ranks, dimensions,
* scales, zeroPoints, and extraParams as the corresponding inputs of
* the WHILE operation and exactly one output of
* {@link OperandType::TENSOR_BOOL8} and shape [1].
* All of the operands mentioned must have fully specified dimensions.
* * 1: A {@link OperandType::SUBGRAPH} reference to the body subgraph.
* The subgraph must have (m + k + n) inputs and (m + k) outputs with
* the same types as the corresponding inputs and outputs of the WHILE
* operation.
* the same types, ranks, dimensions,
* scales, zeroPoints, and extraParams as the corresponding inputs and
* outputs of the WHILE operation.
* All of the operands mentioned must have fully specified dimensions.
* * (m inputs): Initial values for input-output operands.
* * (k inputs): Initial values for state-only operands.
* * (n inputs): Values for input-only operands.
@@ -5491,7 +5499,9 @@ struct Operand {
* If a tensor operand's dimensions are not fully specified, the
* dimensions of the operand are deduced from the operand
* dimensions and values of the operation for which that operand
* is an output.
* is an output or from the corresponding {@link OperationType::IF} or
* {@link OperationType::WHILE} operation input operand dimensions in the
* case of referenced subgraph input operands.
*
* In the following situations, a tensor operand's dimensions must
* be fully specified:
@@ -5499,8 +5509,8 @@ struct Operand {
* . The operand has lifetime CONSTANT_COPY or
* CONSTANT_REFERENCE.
*
* . The operand has lifetime SUBGRAPH_INPUT. Fully
* specified dimensions must either be present in the
* . The operand has lifetime SUBGRAPH_INPUT and belongs to the main
* subgraph. Fully specified dimensions must either be present in the
* Operand or they must be provided in the corresponding
* RequestArgument.
* EXCEPTION: If the input is optional and omitted

View File

@@ -264,7 +264,9 @@ struct Operand {
* If a tensor operand's dimensions are not fully specified, the
* dimensions of the operand are deduced from the operand
* dimensions and values of the operation for which that operand
* is an output.
* is an output or from the corresponding {@link OperationType::IF} or
* {@link OperationType::WHILE} operation input operand dimensions in the
* case of referenced subgraph input operands.
*
* In the following situations, a tensor operand's dimensions must
* be fully specified:
@@ -272,8 +274,8 @@ struct Operand {
* . The operand has lifetime CONSTANT_COPY or
* CONSTANT_REFERENCE.
*
* . The operand has lifetime SUBGRAPH_INPUT. Fully
* specified dimensions must either be present in the
* . The operand has lifetime SUBGRAPH_INPUT and belongs to the main
* subgraph. Fully specified dimensions must either be present in the
* Operand or they must be provided in the corresponding
* RequestArgument.
* EXCEPTION: If the input is optional and omitted

View File

@@ -43,6 +43,7 @@ cc_test {
"MemoryDomainTests.cpp",
"QualityOfServiceTests.cpp",
"TestAssertions.cpp",
"TestMain.cpp",
"ValidateBurst.cpp",
"ValidateModel.cpp",
"ValidateRequest.cpp",

View File

@@ -26,10 +26,6 @@
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<!-- b/156691406, b/155577050, b/155674368, b/153876253, temporarily disable the test.
Must be deleted after corresponding driver issues are fixed.
-->
<option name="native-test-flag" value="--gtest_filter=-*Validation*:*DynamicOutputShapeTest*:*FencedComputeTest*:*MemoryDomain*:*QuantizationCouplingTest*:*DeadlineTest*:*resize_*_v1_3*:*squeeze*_all*_inputs*:*strided_slice*_all*_inputs*:*transpose*_all*_inputs*:*l2_normalization_axis_corner_case*:*sample_float_fast*:*sample_float_slow*:*sample_minimal*:*sample_quant*" />
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="VtsHalNeuralnetworksV1_3TargetTest" />
</test>

View File

@@ -0,0 +1,25 @@
/*
* 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 "1.0/LogTestCaseToLogcat.h"
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
testing::UnitTest::GetInstance()->listeners().Append(
new android::hardware::neuralnetworks::LogTestCaseToLogcat());
return RUN_ALL_TESTS();
}

View File

@@ -21,6 +21,7 @@
#include <android/hardware/neuralnetworks/1.3/IPreparedModel.h>
#include <android/hardware/neuralnetworks/1.3/types.h>
#include <gtest/gtest.h>
#include <vector>
#include "1.0/Utils.h"
#include "1.3/Callbacks.h"

View File

@@ -14,6 +14,7 @@
* limitations under the License.
*/
#include <android-base/logging.h>
#include <radio_hidl_hal_utils_v1_0.h>
using namespace ::android::hardware::radio::V1_0;
@@ -22,6 +23,7 @@ using namespace ::android::hardware::radio::V1_0;
* Test IRadio.setGsmBroadcastConfig() for the response returned.
*/
TEST_P(RadioHidlTest, setGsmBroadcastConfig) {
LOG(DEBUG) << "setGsmBroadcastConfig";
serial = GetRandomSerialNumber();
// Create GsmBroadcastSmsConfigInfo #1
@@ -79,12 +81,14 @@ TEST_P(RadioHidlTest, setGsmBroadcastConfig) {
RadioError::INVALID_MODEM_STATE, RadioError::INVALID_STATE},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "setGsmBroadcastConfig finished";
}
/*
* Test IRadio.getGsmBroadcastConfig() for the response returned.
*/
TEST_P(RadioHidlTest, getGsmBroadcastConfig) {
LOG(DEBUG) << "getGsmBroadcastConfig";
serial = GetRandomSerialNumber();
radio->getGsmBroadcastConfig(serial);
@@ -99,12 +103,14 @@ TEST_P(RadioHidlTest, getGsmBroadcastConfig) {
{RadioError::NONE, RadioError::INVALID_MODEM_STATE, RadioError::INVALID_STATE},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "getGsmBroadcastConfig finished";
}
/*
* Test IRadio.setCdmaBroadcastConfig() for the response returned.
*/
TEST_P(RadioHidlTest, setCdmaBroadcastConfig) {
LOG(DEBUG) << "setCdmaBroadcastConfig";
serial = GetRandomSerialNumber();
CdmaBroadcastSmsConfigInfo cbSmsConfig;
@@ -126,12 +132,14 @@ TEST_P(RadioHidlTest, setCdmaBroadcastConfig) {
{RadioError::NONE, RadioError::INVALID_MODEM_STATE},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "setCdmaBroadcastConfig finished";
}
/*
* Test IRadio.getCdmaBroadcastConfig() for the response returned.
*/
TEST_P(RadioHidlTest, getCdmaBroadcastConfig) {
LOG(DEBUG) << "getCdmaBroadcastConfig";
serial = GetRandomSerialNumber();
radio->getCdmaBroadcastConfig(serial);
@@ -144,12 +152,14 @@ TEST_P(RadioHidlTest, getCdmaBroadcastConfig) {
ASSERT_TRUE(
CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "getCdmaBroadcastConfig finished";
}
/*
* Test IRadio.setCdmaBroadcastActivation() for the response returned.
*/
TEST_P(RadioHidlTest, setCdmaBroadcastActivation) {
LOG(DEBUG) << "setCdmaBroadcastActivation";
serial = GetRandomSerialNumber();
bool activate = false;
@@ -164,12 +174,14 @@ TEST_P(RadioHidlTest, setCdmaBroadcastActivation) {
{RadioError::NONE, RadioError::INVALID_ARGUMENTS},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "setCdmaBroadcastActivation finished";
}
/*
* Test IRadio.setGsmBroadcastActivation() for the response returned.
*/
TEST_P(RadioHidlTest, setGsmBroadcastActivation) {
LOG(DEBUG) << "setGsmBroadcastActivation";
serial = GetRandomSerialNumber();
bool activate = false;
@@ -186,4 +198,5 @@ TEST_P(RadioHidlTest, setGsmBroadcastActivation) {
RadioError::INVALID_STATE, RadioError::OPERATION_NOT_ALLOWED},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "setGsmBroadcastActivation finished";
}

View File

@@ -14,6 +14,7 @@
* limitations under the License.
*/
#include <android-base/logging.h>
#include <radio_hidl_hal_utils_v1_0.h>
using namespace ::android::hardware::radio::V1_0;
@@ -22,6 +23,7 @@ using namespace ::android::hardware::radio::V1_0;
* Test IRadio.getDataRegistrationState() for the response returned.
*/
TEST_P(RadioHidlTest, getDataRegistrationState) {
LOG(DEBUG) << "getDataRegistrationState";
serial = GetRandomSerialNumber();
radio->getDataRegistrationState(serial);
@@ -94,12 +96,14 @@ TEST_P(RadioHidlTest, getDataRegistrationState) {
}
}
}
LOG(DEBUG) << "getDataRegistrationState finished";
}
/*
* Test IRadio.setupDataCall() for the response returned.
*/
TEST_P(RadioHidlTest, setupDataCall) {
LOG(DEBUG) << "setupDataCall";
serial = GetRandomSerialNumber();
RadioTechnology radioTechnology = RadioTechnology::LTE;
@@ -142,12 +146,14 @@ TEST_P(RadioHidlTest, setupDataCall) {
RadioError::RADIO_NOT_AVAILABLE, RadioError::SIM_ABSENT},
CHECK_OEM_ERROR));
}
LOG(DEBUG) << "setupDataCall finished";
}
/*
* Test IRadio.deactivateDataCall() for the response returned.
*/
TEST_P(RadioHidlTest, deactivateDataCall) {
LOG(DEBUG) << "deactivateDataCall";
serial = GetRandomSerialNumber();
int cid = 1;
bool reasonRadioShutDown = false;
@@ -164,12 +170,14 @@ TEST_P(RadioHidlTest, deactivateDataCall) {
RadioError::SIM_ABSENT, RadioError::INVALID_CALL_ID},
CHECK_OEM_ERROR));
}
LOG(DEBUG) << "deactivateDataCall finished";
}
/*
* Test IRadio.getDataCallList() for the response returned.
*/
TEST_P(RadioHidlTest, getDataCallList) {
LOG(DEBUG) << "getDataCallList";
serial = GetRandomSerialNumber();
radio->getDataCallList(serial);
@@ -183,12 +191,14 @@ TEST_P(RadioHidlTest, getDataCallList) {
radioRsp->rspInfo.error,
{RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::SIM_ABSENT}));
}
LOG(DEBUG) << "getDataCallList finished";
}
/*
* Test IRadio.setInitialAttachApn() for the response returned.
*/
TEST_P(RadioHidlTest, setInitialAttachApn) {
LOG(DEBUG) << "setInitialAttachApn";
serial = GetRandomSerialNumber();
DataProfileInfo dataProfileInfo;
@@ -226,12 +236,14 @@ TEST_P(RadioHidlTest, setInitialAttachApn) {
RadioError::SUBSCRIPTION_NOT_AVAILABLE},
CHECK_OEM_ERROR));
}
LOG(DEBUG) << "setInitialAttachApn finished";
}
/*
* Test IRadio.setDataAllowed() for the response returned.
*/
TEST_P(RadioHidlTest, setDataAllowed) {
LOG(DEBUG) << "setDataAllowed";
serial = GetRandomSerialNumber();
bool allow = true;
@@ -244,12 +256,14 @@ TEST_P(RadioHidlTest, setDataAllowed) {
if (cardStatus.cardState == CardState::ABSENT) {
EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
}
LOG(DEBUG) << "setDataAllowed finished";
}
/*
* Test IRadio.setDataProfile() for the response returned.
*/
TEST_P(RadioHidlTest, setDataProfile) {
LOG(DEBUG) << "setDataProfile";
serial = GetRandomSerialNumber();
// Create a dataProfileInfo
@@ -289,4 +303,5 @@ TEST_P(RadioHidlTest, setDataProfile) {
{RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
RadioError::SIM_ABSENT, RadioError::REQUEST_NOT_SUPPORTED}));
}
LOG(DEBUG) << "setDataProfile finished";
}

View File

@@ -14,22 +14,26 @@
* limitations under the License.
*/
#include <android-base/logging.h>
#include <radio_hidl_hal_utils_v1_0.h>
/*
* Test IRadio.getIccCardStatus() for the response returned.
*/
TEST_P(RadioHidlTest, getIccCardStatus) {
LOG(DEBUG) << "getIccCardStatus";
EXPECT_LE(cardStatus.applications.size(), (unsigned int)RadioConst::CARD_MAX_APPS);
EXPECT_LT(cardStatus.gsmUmtsSubscriptionAppIndex, (int)RadioConst::CARD_MAX_APPS);
EXPECT_LT(cardStatus.cdmaSubscriptionAppIndex, (int)RadioConst::CARD_MAX_APPS);
EXPECT_LT(cardStatus.imsSubscriptionAppIndex, (int)RadioConst::CARD_MAX_APPS);
LOG(DEBUG) << "getIccCardStatus finished";
}
/*
* Test IRadio.supplyIccPinForApp() for the response returned
*/
TEST_P(RadioHidlTest, supplyIccPinForApp) {
LOG(DEBUG) << "supplyIccPinForApp";
serial = GetRandomSerialNumber();
// Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
@@ -49,12 +53,14 @@ TEST_P(RadioHidlTest, supplyIccPinForApp) {
{RadioError::PASSWORD_INCORRECT, RadioError::REQUEST_NOT_SUPPORTED}));
}
}
LOG(DEBUG) << "supplyIccPinForApp finished";
}
/*
* Test IRadio.supplyIccPukForApp() for the response returned.
*/
TEST_P(RadioHidlTest, supplyIccPukForApp) {
LOG(DEBUG) << "supplyIccPukForApp";
serial = GetRandomSerialNumber();
// Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
@@ -73,12 +79,14 @@ TEST_P(RadioHidlTest, supplyIccPukForApp) {
RadioError::INVALID_SIM_STATE}));
}
}
LOG(DEBUG) << "supplyIccPukForApp finished";
}
/*
* Test IRadio.supplyIccPin2ForApp() for the response returned.
*/
TEST_P(RadioHidlTest, supplyIccPin2ForApp) {
LOG(DEBUG) << "supplyIccPin2ForApp";
serial = GetRandomSerialNumber();
// Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
@@ -99,12 +107,14 @@ TEST_P(RadioHidlTest, supplyIccPin2ForApp) {
RadioError::SIM_PUK2}));
}
}
LOG(DEBUG) << "supplyIccPin2ForApp finished";
}
/*
* Test IRadio.supplyIccPuk2ForApp() for the response returned.
*/
TEST_P(RadioHidlTest, supplyIccPuk2ForApp) {
LOG(DEBUG) << "supplyIccPuk2ForApp";
serial = GetRandomSerialNumber();
// Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
@@ -123,12 +133,14 @@ TEST_P(RadioHidlTest, supplyIccPuk2ForApp) {
RadioError::INVALID_SIM_STATE}));
}
}
LOG(DEBUG) << "supplyIccPuk2ForApp finished";
}
/*
* Test IRadio.changeIccPinForApp() for the response returned.
*/
TEST_P(RadioHidlTest, changeIccPinForApp) {
LOG(DEBUG) << "changeIccPinForApp";
serial = GetRandomSerialNumber();
// Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
@@ -148,12 +160,14 @@ TEST_P(RadioHidlTest, changeIccPinForApp) {
{RadioError::PASSWORD_INCORRECT, RadioError::REQUEST_NOT_SUPPORTED}));
}
}
LOG(DEBUG) << "changeIccPinForApp finished";
}
/*
* Test IRadio.changeIccPin2ForApp() for the response returned.
*/
TEST_P(RadioHidlTest, changeIccPin2ForApp) {
LOG(DEBUG) << "changeIccPin2ForApp";
serial = GetRandomSerialNumber();
// Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
@@ -174,6 +188,7 @@ TEST_P(RadioHidlTest, changeIccPin2ForApp) {
RadioError::SIM_PUK2}));
}
}
LOG(DEBUG) << "changeIccPin2ForApp finished";
}
/*
@@ -182,6 +197,7 @@ TEST_P(RadioHidlTest, changeIccPin2ForApp) {
* Test IRadio.getImsiForApp() for the response returned.
*/
TEST_P(RadioHidlTest, DISABLED_getImsiForApp) {
LOG(DEBUG) << "DISABLED_getImsiForApp";
serial = GetRandomSerialNumber();
// Check success returned while getting imsi for 3GPP and 3GPP2 apps only
@@ -205,12 +221,14 @@ TEST_P(RadioHidlTest, DISABLED_getImsiForApp) {
}
}
}
LOG(DEBUG) << "DISABLED_getImsiForApp finished";
}
/*
* Test IRadio.iccIOForApp() for the response returned.
*/
TEST_P(RadioHidlTest, iccIOForApp) {
LOG(DEBUG) << "iccIOForApp";
serial = GetRandomSerialNumber();
for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
@@ -230,12 +248,14 @@ TEST_P(RadioHidlTest, iccIOForApp) {
EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
EXPECT_EQ(serial, radioRsp->rspInfo.serial);
}
LOG(DEBUG) << "iccIOForApp finished";
}
/*
* Test IRadio.iccTransmitApduBasicChannel() for the response returned.
*/
TEST_P(RadioHidlTest, iccTransmitApduBasicChannel) {
LOG(DEBUG) << "iccTransmitApduBasicChannel";
serial = GetRandomSerialNumber();
SimApdu msg;
memset(&msg, 0, sizeof(msg));
@@ -247,12 +267,14 @@ TEST_P(RadioHidlTest, iccTransmitApduBasicChannel) {
EXPECT_EQ(serial, radioRsp->rspInfo.serial);
// TODO(sanketpadawe): Add test for error code
LOG(DEBUG) << "iccTransmitApduBasicChannel finished";
}
/*
* Test IRadio.iccOpenLogicalChannel() for the response returned.
*/
TEST_P(RadioHidlTest, iccOpenLogicalChannel) {
LOG(DEBUG) << "iccOpenLogicalChannel";
serial = GetRandomSerialNumber();
int p2 = 0x04;
// Specified in ISO 7816-4 clause 7.1.1 0x04 means that FCP template is requested.
@@ -262,12 +284,14 @@ TEST_P(RadioHidlTest, iccOpenLogicalChannel) {
EXPECT_EQ(serial, radioRsp->rspInfo.serial);
EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
}
LOG(DEBUG) << "iccOpenLogicalChannel finished";
}
/*
* Test IRadio.iccCloseLogicalChannel() for the response returned.
*/
TEST_P(RadioHidlTest, iccCloseLogicalChannel) {
LOG(DEBUG) << "iccCloseLogicalChannel";
serial = GetRandomSerialNumber();
// Try closing invalid channel and check INVALID_ARGUMENTS returned as error
radio->iccCloseLogicalChannel(serial, 0);
@@ -276,12 +300,14 @@ TEST_P(RadioHidlTest, iccCloseLogicalChannel) {
EXPECT_EQ(serial, radioRsp->rspInfo.serial);
EXPECT_EQ(RadioError::INVALID_ARGUMENTS, radioRsp->rspInfo.error);
LOG(DEBUG) << "iccCloseLogicalChannel finished";
}
/*
* Test IRadio.iccTransmitApduLogicalChannel() for the response returned.
*/
TEST_P(RadioHidlTest, iccTransmitApduLogicalChannel) {
LOG(DEBUG) << "iccTransmitApduLogicalChannel";
serial = GetRandomSerialNumber();
SimApdu msg;
memset(&msg, 0, sizeof(msg));
@@ -293,12 +319,14 @@ TEST_P(RadioHidlTest, iccTransmitApduLogicalChannel) {
EXPECT_EQ(serial, radioRsp->rspInfo.serial);
// TODO(sanketpadawe): Add test for error code
LOG(DEBUG) << "iccTransmitApduLogicalChannel finished";
}
/*
* Test IRadio.requestIccSimAuthentication() for the response returned.
*/
TEST_P(RadioHidlTest, requestIccSimAuthentication) {
LOG(DEBUG) << "requestIccSimAuthentication";
serial = GetRandomSerialNumber();
// Pass wrong challenge string and check RadioError::INVALID_ARGUMENTS
@@ -312,12 +340,14 @@ TEST_P(RadioHidlTest, requestIccSimAuthentication) {
ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::INVALID_ARGUMENTS,
RadioError::REQUEST_NOT_SUPPORTED}));
}
LOG(DEBUG) << "requestIccSimAuthentication finished";
}
/*
* Test IRadio.supplyNetworkDepersonalization() for the response returned.
*/
TEST_P(RadioHidlTest, supplyNetworkDepersonalization) {
LOG(DEBUG) << "supplyNetworkDepersonalization";
serial = GetRandomSerialNumber();
radio->supplyNetworkDepersonalization(serial, hidl_string("test"));
@@ -332,4 +362,5 @@ TEST_P(RadioHidlTest, supplyNetworkDepersonalization) {
RadioError::INVALID_SIM_STATE, RadioError::MODEM_ERR, RadioError::NO_MEMORY,
RadioError::PASSWORD_INCORRECT, RadioError::SIM_ABSENT, RadioError::SYSTEM_ERR}));
}
LOG(DEBUG) << "supplyNetworkDepersonalization finished";
}

View File

@@ -14,12 +14,14 @@
* limitations under the License.
*/
#include <android-base/logging.h>
#include <radio_hidl_hal_utils_v1_0.h>
/*
* Test IRadio.getSignalStrength() for the response returned.
*/
TEST_P(RadioHidlTest, getSignalStrength) {
LOG(DEBUG) << "getSignalStrength";
serial = GetRandomSerialNumber();
radio->getSignalStrength(serial);
@@ -30,12 +32,14 @@ TEST_P(RadioHidlTest, getSignalStrength) {
if (cardStatus.cardState == CardState::ABSENT) {
EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
}
LOG(DEBUG) << "getSignalStrength finished";
}
/*
* Test IRadio.getVoiceRegistrationState() for the response returned.
*/
TEST_P(RadioHidlTest, getVoiceRegistrationState) {
LOG(DEBUG) << "getVoiceRegistrationState";
serial = GetRandomSerialNumber();
radio->getVoiceRegistrationState(serial);
@@ -46,12 +50,14 @@ TEST_P(RadioHidlTest, getVoiceRegistrationState) {
if (cardStatus.cardState == CardState::ABSENT) {
EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
}
LOG(DEBUG) << "getVoiceRegistrationState finished";
}
/*
* Test IRadio.getOperator() for the response returned.
*/
TEST_P(RadioHidlTest, getOperator) {
LOG(DEBUG) << "getOperator";
serial = GetRandomSerialNumber();
radio->getOperator(serial);
@@ -62,12 +68,14 @@ TEST_P(RadioHidlTest, getOperator) {
if (cardStatus.cardState == CardState::ABSENT) {
EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
}
LOG(DEBUG) << "getOperator finished";
}
/*
* Test IRadio.setRadioPower() for the response returned.
*/
TEST_P(RadioHidlTest, setRadioPower) {
LOG(DEBUG) << "setRadioPower";
serial = GetRandomSerialNumber();
radio->setRadioPower(serial, 1);
@@ -78,12 +86,14 @@ TEST_P(RadioHidlTest, setRadioPower) {
if (cardStatus.cardState == CardState::ABSENT) {
EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
}
LOG(DEBUG) << "setRadioPower finished";
}
/*
* Test IRadio.getNetworkSelectionMode() for the response returned.
*/
TEST_P(RadioHidlTest, getNetworkSelectionMode) {
LOG(DEBUG) << "getNetworkSelectionMode";
serial = GetRandomSerialNumber();
radio->getNetworkSelectionMode(serial);
@@ -94,12 +104,14 @@ TEST_P(RadioHidlTest, getNetworkSelectionMode) {
if (cardStatus.cardState == CardState::ABSENT) {
EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
}
LOG(DEBUG) << "getNetworkSelectionMode finished";
}
/*
* Test IRadio.setNetworkSelectionModeAutomatic() for the response returned.
*/
TEST_P(RadioHidlTest, setNetworkSelectionModeAutomatic) {
LOG(DEBUG) << "setNetworkSelectionModeAutomatic";
serial = GetRandomSerialNumber();
radio->setNetworkSelectionModeAutomatic(serial);
@@ -113,12 +125,14 @@ TEST_P(RadioHidlTest, setNetworkSelectionModeAutomatic) {
{RadioError::NONE, RadioError::ILLEGAL_SIM_OR_ME, RadioError::OPERATION_NOT_ALLOWED},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "setNetworkSelectionModeAutomatic finished";
}
/*
* Test IRadio.setNetworkSelectionModeManual() for the response returned.
*/
TEST_P(RadioHidlTest, setNetworkSelectionModeManual) {
LOG(DEBUG) << "setNetworkSelectionModeManual";
serial = GetRandomSerialNumber();
radio->setNetworkSelectionModeManual(serial, "123456");
@@ -132,12 +146,14 @@ TEST_P(RadioHidlTest, setNetworkSelectionModeManual) {
RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "setNetworkSelectionModeManual finished";
}
/*
* Test IRadio.getAvailableNetworks() for the response returned.
*/
TEST_P(RadioHidlTest, getAvailableNetworks) {
LOG(DEBUG) << "getAvailableNetworks";
serial = GetRandomSerialNumber();
radio->getAvailableNetworks(serial);
@@ -153,12 +169,14 @@ TEST_P(RadioHidlTest, getAvailableNetworks) {
RadioError::MODEM_ERR, RadioError::OPERATION_NOT_ALLOWED},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "getAvailableNetworks finished";
}
/*
* Test IRadio.getBasebandVersion() for the response returned.
*/
TEST_P(RadioHidlTest, getBasebandVersion) {
LOG(DEBUG) << "getBasebandVersion";
serial = GetRandomSerialNumber();
radio->getBasebandVersion(serial);
@@ -169,12 +187,14 @@ TEST_P(RadioHidlTest, getBasebandVersion) {
if (cardStatus.cardState == CardState::ABSENT) {
EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
}
LOG(DEBUG) << "getBasebandVersion finished";
}
/*
* Test IRadio.setBandMode() for the response returned.
*/
TEST_P(RadioHidlTest, setBandMode) {
LOG(DEBUG) << "setBandMode";
serial = GetRandomSerialNumber();
radio->setBandMode(serial, RadioBandMode::BAND_MODE_USA);
@@ -186,12 +206,14 @@ TEST_P(RadioHidlTest, setBandMode) {
ASSERT_TRUE(
CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "setBandMode finished";
}
/*
* Test IRadio.getAvailableBandModes() for the response returned.
*/
TEST_P(RadioHidlTest, getAvailableBandModes) {
LOG(DEBUG) << "getAvailableBandModes";
serial = GetRandomSerialNumber();
radio->getAvailableBandModes(serial);
@@ -202,12 +224,14 @@ TEST_P(RadioHidlTest, getAvailableBandModes) {
if (cardStatus.cardState == CardState::ABSENT) {
EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
}
LOG(DEBUG) << "getAvailableBandModes finished";
}
/*
* Test IRadio.setPreferredNetworkType() for the response returned.
*/
TEST_P(RadioHidlTest, setPreferredNetworkType) {
LOG(DEBUG) << "setPreferredNetworkType";
serial = GetRandomSerialNumber();
radio->setPreferredNetworkType(serial, PreferredNetworkType::GSM_ONLY);
@@ -219,12 +243,14 @@ TEST_P(RadioHidlTest, setPreferredNetworkType) {
ASSERT_TRUE(
CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "setPreferredNetworkType finished";
}
/*
* Test IRadio.getPreferredNetworkType() for the response returned.
*/
TEST_P(RadioHidlTest, getPreferredNetworkType) {
LOG(DEBUG) << "getPreferredNetworkType";
serial = GetRandomSerialNumber();
radio->getPreferredNetworkType(serial);
@@ -235,12 +261,14 @@ TEST_P(RadioHidlTest, getPreferredNetworkType) {
if (cardStatus.cardState == CardState::ABSENT) {
EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
}
LOG(DEBUG) << "getPreferredNetworkType finished";
}
/*
* Test IRadio.getNeighboringCids() for the response returned.
*/
TEST_P(RadioHidlTest, getNeighboringCids) {
LOG(DEBUG) << "getNeighboringCids";
serial = GetRandomSerialNumber();
radio->getNeighboringCids(serial);
@@ -253,12 +281,14 @@ TEST_P(RadioHidlTest, getNeighboringCids) {
{RadioError::NONE, RadioError::SIM_ABSENT},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "getNeighboringCids finished";
}
/*
* Test IRadio.setLocationUpdates() for the response returned.
*/
TEST_P(RadioHidlTest, setLocationUpdates) {
LOG(DEBUG) << "setLocationUpdates";
serial = GetRandomSerialNumber();
radio->setLocationUpdates(serial, true);
@@ -270,12 +300,14 @@ TEST_P(RadioHidlTest, setLocationUpdates) {
ASSERT_TRUE(
CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE, RadioError::SIM_ABSENT}));
}
LOG(DEBUG) << "setLocationUpdates finished";
}
/*
* Test IRadio.setCdmaRoamingPreference() for the response returned.
*/
TEST_P(RadioHidlTest, setCdmaRoamingPreference) {
LOG(DEBUG) << "setCdmaRoamingPreference";
serial = GetRandomSerialNumber();
radio->setCdmaRoamingPreference(serial, CdmaRoamingType::HOME_NETWORK);
@@ -288,12 +320,14 @@ TEST_P(RadioHidlTest, setCdmaRoamingPreference) {
radioRsp->rspInfo.error,
{RadioError::NONE, RadioError::SIM_ABSENT, RadioError::REQUEST_NOT_SUPPORTED}));
}
LOG(DEBUG) << "setCdmaRoamingPreference finished";
}
/*
* Test IRadio.getCdmaRoamingPreference() for the response returned.
*/
TEST_P(RadioHidlTest, getCdmaRoamingPreference) {
LOG(DEBUG) << "getCdmaRoamingPreference";
serial = GetRandomSerialNumber();
radio->getCdmaRoamingPreference(serial);
@@ -307,12 +341,14 @@ TEST_P(RadioHidlTest, getCdmaRoamingPreference) {
{RadioError::NONE, RadioError::SIM_ABSENT, RadioError::MODEM_ERR},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "getCdmaRoamingPreference finished";
}
/*
* Test IRadio.getTTYMode() for the response returned.
*/
TEST_P(RadioHidlTest, getTTYMode) {
LOG(DEBUG) << "getTTYMode";
serial = GetRandomSerialNumber();
radio->getTTYMode(serial);
@@ -323,12 +359,14 @@ TEST_P(RadioHidlTest, getTTYMode) {
if (cardStatus.cardState == CardState::ABSENT) {
EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
}
LOG(DEBUG) << "getTTYMode finished";
}
/*
* Test IRadio.setTTYMode() for the response returned.
*/
TEST_P(RadioHidlTest, setTTYMode) {
LOG(DEBUG) << "setTTYMode";
serial = GetRandomSerialNumber();
radio->setTTYMode(serial, TtyMode::OFF);
@@ -339,12 +377,14 @@ TEST_P(RadioHidlTest, setTTYMode) {
if (cardStatus.cardState == CardState::ABSENT) {
EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
}
LOG(DEBUG) << "setTTYMode finished";
}
/*
* Test IRadio.setPreferredVoicePrivacy() for the response returned.
*/
TEST_P(RadioHidlTest, setPreferredVoicePrivacy) {
LOG(DEBUG) << "setPreferredVoicePrivacy";
serial = GetRandomSerialNumber();
radio->setPreferredVoicePrivacy(serial, true);
@@ -356,12 +396,14 @@ TEST_P(RadioHidlTest, setPreferredVoicePrivacy) {
ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
{RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
}
LOG(DEBUG) << "setPreferredVoicePrivacy finished";
}
/*
* Test IRadio.getPreferredVoicePrivacy() for the response returned.
*/
TEST_P(RadioHidlTest, getPreferredVoicePrivacy) {
LOG(DEBUG) << "getPreferredVoicePrivacy";
serial = GetRandomSerialNumber();
radio->getPreferredVoicePrivacy(serial);
@@ -373,12 +415,14 @@ TEST_P(RadioHidlTest, getPreferredVoicePrivacy) {
ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
{RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
}
LOG(DEBUG) << "getPreferredVoicePrivacy finished";
}
/*
* Test IRadio.getCDMASubscription() for the response returned.
*/
TEST_P(RadioHidlTest, getCDMASubscription) {
LOG(DEBUG) << "getCDMASubscription";
serial = GetRandomSerialNumber();
radio->getCDMASubscription(serial);
@@ -391,12 +435,14 @@ TEST_P(RadioHidlTest, getCDMASubscription) {
radioRsp->rspInfo.error,
{RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED, RadioError::SIM_ABSENT}));
}
LOG(DEBUG) << "getCDMASubscription finished";
}
/*
* Test IRadio.getDeviceIdentity() for the response returned.
*/
TEST_P(RadioHidlTest, getDeviceIdentity) {
LOG(DEBUG) << "getDeviceIdentity";
serial = GetRandomSerialNumber();
radio->getDeviceIdentity(serial);
@@ -408,12 +454,14 @@ TEST_P(RadioHidlTest, getDeviceIdentity) {
ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
{RadioError::NONE, RadioError::EMPTY_RECORD}));
}
LOG(DEBUG) << "getDeviceIdentity finished";
}
/*
* Test IRadio.exitEmergencyCallbackMode() for the response returned.
*/
TEST_P(RadioHidlTest, exitEmergencyCallbackMode) {
LOG(DEBUG) << "exitEmergencyCallbackMode";
serial = GetRandomSerialNumber();
radio->exitEmergencyCallbackMode(serial);
@@ -426,12 +474,14 @@ TEST_P(RadioHidlTest, exitEmergencyCallbackMode) {
radioRsp->rspInfo.error,
{RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED, RadioError::SIM_ABSENT}));
}
LOG(DEBUG) << "exitEmergencyCallbackMode finished";
}
/*
* Test IRadio.getCdmaSubscriptionSource() for the response returned.
*/
TEST_P(RadioHidlTest, getCdmaSubscriptionSource) {
LOG(DEBUG) << "getCdmaSubscriptionSource";
serial = GetRandomSerialNumber();
radio->getCdmaSubscriptionSource(serial);
@@ -444,12 +494,14 @@ TEST_P(RadioHidlTest, getCdmaSubscriptionSource) {
radioRsp->rspInfo.error,
{RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED, RadioError::SIM_ABSENT}));
}
LOG(DEBUG) << "getCdmaSubscriptionSource finished";
}
/*
* Test IRadio.setCdmaSubscriptionSource() for the response returned.
*/
TEST_P(RadioHidlTest, setCdmaSubscriptionSource) {
LOG(DEBUG) << "setCdmaSubscriptionSource";
serial = GetRandomSerialNumber();
radio->setCdmaSubscriptionSource(serial, CdmaSubscriptionSource::RUIM_SIM);
@@ -463,12 +515,14 @@ TEST_P(RadioHidlTest, setCdmaSubscriptionSource) {
{RadioError::NONE, RadioError::SIM_ABSENT, RadioError::SUBSCRIPTION_NOT_AVAILABLE},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "setCdmaSubscriptionSource finished";
}
/*
* Test IRadio.getVoiceRadioTechnology() for the response returned.
*/
TEST_P(RadioHidlTest, getVoiceRadioTechnology) {
LOG(DEBUG) << "getVoiceRadioTechnology";
serial = GetRandomSerialNumber();
radio->getVoiceRadioTechnology(serial);
@@ -479,12 +533,14 @@ TEST_P(RadioHidlTest, getVoiceRadioTechnology) {
if (cardStatus.cardState == CardState::ABSENT) {
EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
}
LOG(DEBUG) << "getVoiceRadioTechnology finished";
}
/*
* Test IRadio.getCellInfoList() for the response returned.
*/
TEST_P(RadioHidlTest, getCellInfoList) {
LOG(DEBUG) << "getCellInfoList";
serial = GetRandomSerialNumber();
radio->getCellInfoList(serial);
@@ -497,12 +553,14 @@ TEST_P(RadioHidlTest, getCellInfoList) {
{RadioError::NONE, RadioError::NO_NETWORK_FOUND},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "getCellInfoList finished";
}
/*
* Test IRadio.setCellInfoListRate() for the response returned.
*/
TEST_P(RadioHidlTest, setCellInfoListRate) {
LOG(DEBUG) << "setCellInfoListRate";
serial = GetRandomSerialNumber();
// TODO(sanketpadawe): RIL crashes with value of rate = 10
@@ -515,12 +573,14 @@ TEST_P(RadioHidlTest, setCellInfoListRate) {
ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
{RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
}
LOG(DEBUG) << "setCellInfoListRate finished";
}
/*
* Test IRadio.nvReadItem() for the response returned.
*/
TEST_P(RadioHidlTest, nvReadItem) {
LOG(DEBUG) << "nvReadItem";
serial = GetRandomSerialNumber();
radio->nvReadItem(serial, NvItem::LTE_BAND_ENABLE_25);
@@ -532,12 +592,14 @@ TEST_P(RadioHidlTest, nvReadItem) {
ASSERT_TRUE(
CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "nvReadItem finished";
}
/*
* Test IRadio.nvWriteItem() for the response returned.
*/
TEST_P(RadioHidlTest, nvWriteItem) {
LOG(DEBUG) << "nvWriteItem";
serial = GetRandomSerialNumber();
NvWriteItem item;
memset(&item, 0, sizeof(item));
@@ -552,12 +614,14 @@ TEST_P(RadioHidlTest, nvWriteItem) {
ASSERT_TRUE(
CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "nvWriteItem finished";
}
/*
* Test IRadio.nvWriteCdmaPrl() for the response returned.
*/
TEST_P(RadioHidlTest, nvWriteCdmaPrl) {
LOG(DEBUG) << "nvWriteCdmaPrl";
serial = GetRandomSerialNumber();
std::vector<uint8_t> prl = {1, 2, 3, 4, 5};
@@ -570,12 +634,14 @@ TEST_P(RadioHidlTest, nvWriteCdmaPrl) {
ASSERT_TRUE(
CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "nvWriteCdmaPrl finished";
}
/*
* Test IRadio.nvResetConfig() for the response returned.
*/
TEST_P(RadioHidlTest, nvResetConfig) {
LOG(DEBUG) << "nvResetConfig";
serial = GetRandomSerialNumber();
radio->nvResetConfig(serial, ResetNvType::FACTORY_RESET);
@@ -587,12 +653,14 @@ TEST_P(RadioHidlTest, nvResetConfig) {
ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
{RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
}
LOG(DEBUG) << "nvResetConfig finished";
}
/*
* Test IRadio.setUiccSubscription() for the response returned.
*/
TEST_P(RadioHidlTest, setUiccSubscription) {
LOG(DEBUG) << "setUiccSubscription";
serial = GetRandomSerialNumber();
SelectUiccSub item;
memset(&item, 0, sizeof(item));
@@ -609,12 +677,14 @@ TEST_P(RadioHidlTest, setUiccSubscription) {
RadioError::MODEM_ERR, RadioError::SUBSCRIPTION_NOT_SUPPORTED},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "setUiccSubscription finished";
}
/*
* Test IRadio.getHardwareConfig() for the response returned.
*/
TEST_P(RadioHidlTest, getHardwareConfig) {
LOG(DEBUG) << "getHardwareConfig";
serial = GetRandomSerialNumber();
radio->getHardwareConfig(serial);
@@ -626,6 +696,7 @@ TEST_P(RadioHidlTest, getHardwareConfig) {
ASSERT_TRUE(
CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "getHardwareConfig finished";
}
/*
@@ -651,6 +722,7 @@ TEST_P(RadioHidlTest, DISABLED_requestShutdown) {
* Test IRadio.getRadioCapability() for the response returned.
*/
TEST_P(RadioHidlTest, getRadioCapability) {
LOG(DEBUG) << "getRadioCapability";
serial = GetRandomSerialNumber();
radio->getRadioCapability(serial);
@@ -661,12 +733,14 @@ TEST_P(RadioHidlTest, getRadioCapability) {
if (cardStatus.cardState == CardState::ABSENT) {
EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
}
LOG(DEBUG) << "getRadioCapability finished";
}
/*
* Test IRadio.setRadioCapability() for the response returned.
*/
TEST_P(RadioHidlTest, setRadioCapability) {
LOG(DEBUG) << "setRadioCapability";
serial = GetRandomSerialNumber();
RadioCapability rc;
memset(&rc, 0, sizeof(rc));
@@ -682,12 +756,14 @@ TEST_P(RadioHidlTest, setRadioCapability) {
{RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "setRadioCapability finished";
}
/*
* Test IRadio.startLceService() for the response returned.
*/
TEST_P(RadioHidlTest, startLceService) {
LOG(DEBUG) << "startLceService";
serial = GetRandomSerialNumber();
radio->startLceService(serial, 5, true);
@@ -701,12 +777,14 @@ TEST_P(RadioHidlTest, startLceService) {
{RadioError::INTERNAL_ERR, RadioError::LCE_NOT_SUPPORTED,
RadioError::RADIO_NOT_AVAILABLE, RadioError::SIM_ABSENT, RadioError::NONE}));
}
LOG(DEBUG) << "startLceService finished";
}
/*
* Test IRadio.stopLceService() for the response returned.
*/
TEST_P(RadioHidlTest, stopLceService) {
LOG(DEBUG) << "stopLceService";
serial = GetRandomSerialNumber();
radio->stopLceService(serial);
@@ -719,12 +797,14 @@ TEST_P(RadioHidlTest, stopLceService) {
{RadioError::NONE, RadioError::LCE_NOT_SUPPORTED,
RadioError::REQUEST_NOT_SUPPORTED, RadioError::SIM_ABSENT}));
}
LOG(DEBUG) << "stopLceService finished";
}
/*
* Test IRadio.pullLceData() for the response returned.
*/
TEST_P(RadioHidlTest, pullLceData) {
LOG(DEBUG) << "pullLceData";
serial = GetRandomSerialNumber();
radio->pullLceData(serial);
@@ -738,12 +818,14 @@ TEST_P(RadioHidlTest, pullLceData) {
RadioError::RADIO_NOT_AVAILABLE, RadioError::SIM_ABSENT},
CHECK_OEM_ERROR));
}
LOG(DEBUG) << "pullLceData finished";
}
/*
* Test IRadio.getModemActivityInfo() for the response returned.
*/
TEST_P(RadioHidlTest, getModemActivityInfo) {
LOG(DEBUG) << "getModemActivityInfo";
serial = GetRandomSerialNumber();
radio->getModemActivityInfo(serial);
@@ -755,6 +837,7 @@ TEST_P(RadioHidlTest, getModemActivityInfo) {
ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
{RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
}
LOG(DEBUG) << "getModemActivityInfo finished";
}
/*
@@ -840,6 +923,7 @@ TEST_P(RadioHidlTest, DISABLED_setAllowedCarriers) {
* Test IRadio.getAllowedCarriers() for the response returned.
*/
TEST_P(RadioHidlTest, getAllowedCarriers) {
LOG(DEBUG) << "getAllowedCarriers";
serial = GetRandomSerialNumber();
radio->getAllowedCarriers(serial);
@@ -851,12 +935,14 @@ TEST_P(RadioHidlTest, getAllowedCarriers) {
ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
{RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
}
LOG(DEBUG) << "getAllowedCarriers finished";
}
/*
* Test IRadio.sendDeviceState() for the response returned.
*/
TEST_P(RadioHidlTest, sendDeviceState) {
LOG(DEBUG) << "sendDeviceState";
serial = GetRandomSerialNumber();
radio->sendDeviceState(serial, DeviceStateType::POWER_SAVE_MODE, true);
@@ -870,12 +956,14 @@ TEST_P(RadioHidlTest, sendDeviceState) {
ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
{RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
}
LOG(DEBUG) << "sendDeviceState finished";
}
/*
* Test IRadio.setIndicationFilter() for the response returned.
*/
TEST_P(RadioHidlTest, setIndicationFilter) {
LOG(DEBUG) << "setIndicationFilter";
serial = GetRandomSerialNumber();
radio->setIndicationFilter(serial, 1);
@@ -889,12 +977,14 @@ TEST_P(RadioHidlTest, setIndicationFilter) {
ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
{RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
}
LOG(DEBUG) << "setIndicationFilter finished";
}
/*
* Test IRadio.setSimCardPower() for the response returned.
*/
TEST_P(RadioHidlTest, setSimCardPower) {
LOG(DEBUG) << "setSimCardPower";
serial = GetRandomSerialNumber();
radio->setSimCardPower(serial, true);
@@ -906,4 +996,5 @@ TEST_P(RadioHidlTest, setSimCardPower) {
ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
{RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
}
LOG(DEBUG) << "setSimCardPower finished";
}

View File

@@ -14,6 +14,7 @@
* limitations under the License.
*/
#include <android-base/logging.h>
#include <radio_hidl_hal_utils_v1_0.h>
using namespace ::android::hardware::radio::V1_0;
@@ -22,6 +23,7 @@ using namespace ::android::hardware::radio::V1_0;
* Test IRadio.sendSms() for the response returned.
*/
TEST_P(RadioHidlTest, sendSms) {
LOG(DEBUG) << "sendSms";
serial = GetRandomSerialNumber();
GsmSmsMessage msg;
msg.smscPdu = "";
@@ -40,12 +42,14 @@ TEST_P(RadioHidlTest, sendSms) {
CHECK_GENERAL_ERROR));
EXPECT_EQ(0, radioRsp->sendSmsResult.errorCode);
}
LOG(DEBUG) << "sendSms finished";
}
/*
* Test IRadio.sendSMSExpectMore() for the response returned.
*/
TEST_P(RadioHidlTest, sendSMSExpectMore) {
LOG(DEBUG) << "sendSMSExpectMore";
serial = GetRandomSerialNumber();
GsmSmsMessage msg;
msg.smscPdu = "";
@@ -66,12 +70,14 @@ TEST_P(RadioHidlTest, sendSMSExpectMore) {
{RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::SIM_ABSENT},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "sendSMSExpectMore finished";
}
/*
* Test IRadio.acknowledgeLastIncomingGsmSms() for the response returned.
*/
TEST_P(RadioHidlTest, acknowledgeLastIncomingGsmSms) {
LOG(DEBUG) << "acknowledgeLastIncomingGsmSms";
serial = GetRandomSerialNumber();
bool success = true;
@@ -87,12 +93,14 @@ TEST_P(RadioHidlTest, acknowledgeLastIncomingGsmSms) {
{RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "acknowledgeLastIncomingGsmSms finished";
}
/*
* Test IRadio.acknowledgeIncomingGsmSmsWithPdu() for the response returned.
*/
TEST_P(RadioHidlTest, acknowledgeIncomingGsmSmsWithPdu) {
LOG(DEBUG) << "acknowledgeIncomingGsmSmsWithPdu";
serial = GetRandomSerialNumber();
bool success = true;
std::string ackPdu = "";
@@ -106,12 +114,14 @@ TEST_P(RadioHidlTest, acknowledgeIncomingGsmSmsWithPdu) {
if (cardStatus.cardState == CardState::ABSENT) {
// TODO(shuoq): Will add error check when we know the expected error from QC
}
LOG(DEBUG) << "acknowledgeIncomingGsmSmsWithPdu finished";
}
/*
* Test IRadio.sendCdmaSms() for the response returned.
*/
TEST_P(RadioHidlTest, sendCdmaSms) {
LOG(DEBUG) << "sendCdmaSms";
serial = GetRandomSerialNumber();
// Create a CdmaSmsAddress
@@ -150,12 +160,14 @@ TEST_P(RadioHidlTest, sendCdmaSms) {
{RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::SIM_ABSENT},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "sendCdmaSms finished";
}
/*
* Test IRadio.acknowledgeLastIncomingCdmaSms() for the response returned.
*/
TEST_P(RadioHidlTest, acknowledgeLastIncomingCdmaSms) {
LOG(DEBUG) << "acknowledgeLastIncomingCdmaSms";
serial = GetRandomSerialNumber();
// Create a CdmaSmsAck
@@ -174,12 +186,14 @@ TEST_P(RadioHidlTest, acknowledgeLastIncomingCdmaSms) {
{RadioError::INVALID_ARGUMENTS, RadioError::NO_SMS_TO_ACK},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "acknowledgeLastIncomingCdmaSms finished";
}
/*
* Test IRadio.sendImsSms() for the response returned.
*/
TEST_P(RadioHidlTest, sendImsSms) {
LOG(DEBUG) << "sendImsSms";
serial = GetRandomSerialNumber();
// Create a CdmaSmsAddress
@@ -224,12 +238,14 @@ TEST_P(RadioHidlTest, sendImsSms) {
ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::INVALID_ARGUMENTS},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "sendImsSms finished";
}
/*
* Test IRadio.getSmscAddress() for the response returned.
*/
TEST_P(RadioHidlTest, getSmscAddress) {
LOG(DEBUG) << "getSmscAddress";
serial = GetRandomSerialNumber();
radio->getSmscAddress(serial);
@@ -244,12 +260,14 @@ TEST_P(RadioHidlTest, getSmscAddress) {
{RadioError::INVALID_MODEM_STATE, RadioError::INVALID_STATE, RadioError::SIM_ABSENT},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "getSmscAddress finished";
}
/*
* Test IRadio.setSmscAddress() for the response returned.
*/
TEST_P(RadioHidlTest, setSmscAddress) {
LOG(DEBUG) << "setSmscAddress";
serial = GetRandomSerialNumber();
hidl_string address = hidl_string("smscAddress");
@@ -265,12 +283,14 @@ TEST_P(RadioHidlTest, setSmscAddress) {
{RadioError::INVALID_ARGUMENTS, RadioError::INVALID_SMS_FORMAT, RadioError::SIM_ABSENT},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "setSmscAddress finished";
}
/*
* Test IRadio.writeSmsToSim() for the response returned.
*/
TEST_P(RadioHidlTest, writeSmsToSim) {
LOG(DEBUG) << "writeSmsToSim";
serial = GetRandomSerialNumber();
SmsWriteArgs smsWriteArgs;
smsWriteArgs.status = SmsWriteArgsStatus::REC_UNREAD;
@@ -291,12 +311,14 @@ TEST_P(RadioHidlTest, writeSmsToSim) {
RadioError::NO_RESOURCES, RadioError::SIM_ABSENT},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "writeSmsToSim finished";
}
/*
* Test IRadio.deleteSmsOnSim() for the response returned.
*/
TEST_P(RadioHidlTest, deleteSmsOnSim) {
LOG(DEBUG) << "deleteSmsOnSim";
serial = GetRandomSerialNumber();
int index = 1;
@@ -314,12 +336,14 @@ TEST_P(RadioHidlTest, deleteSmsOnSim) {
RadioError::SIM_ABSENT},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "deleteSmsOnSim finished";
}
/*
* Test IRadio.writeSmsToRuim() for the response returned.
*/
TEST_P(RadioHidlTest, writeSmsToRuim) {
LOG(DEBUG) << "writeSmsToRuim";
serial = GetRandomSerialNumber();
// Create a CdmaSmsAddress
@@ -365,12 +389,14 @@ TEST_P(RadioHidlTest, writeSmsToRuim) {
RadioError::NO_SUCH_ENTRY, RadioError::SIM_ABSENT},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "writeSmsToRuim finished";
}
/*
* Test IRadio.deleteSmsOnRuim() for the response returned.
*/
TEST_P(RadioHidlTest, deleteSmsOnRuim) {
LOG(DEBUG) << "deleteSmsOnRuim";
serial = GetRandomSerialNumber();
int index = 1;
@@ -416,12 +442,14 @@ TEST_P(RadioHidlTest, deleteSmsOnRuim) {
RadioError::MODEM_ERR, RadioError::NO_SUCH_ENTRY, RadioError::SIM_ABSENT},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "deleteSmsOnRuim finished";
}
/*
* Test IRadio.reportSmsMemoryStatus() for the response returned.
*/
TEST_P(RadioHidlTest, reportSmsMemoryStatus) {
LOG(DEBUG) << "reportSmsMemoryStatus";
serial = GetRandomSerialNumber();
bool available = true;
@@ -437,4 +465,5 @@ TEST_P(RadioHidlTest, reportSmsMemoryStatus) {
RadioError::MODEM_ERR, RadioError::SIM_ABSENT},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "reportSmsMemoryStatus finished";
}

View File

@@ -14,6 +14,7 @@
* limitations under the License.
*/
#include <android-base/logging.h>
#include <radio_hidl_hal_utils_v1_0.h>
using namespace ::android::hardware::radio::V1_0;
@@ -22,6 +23,7 @@ using namespace ::android::hardware::radio::V1_0;
* Test IRadio.sendEnvelope() for the response returned.
*/
TEST_P(RadioHidlTest, sendEnvelope) {
LOG(DEBUG) << "sendEnvelope";
serial = GetRandomSerialNumber();
// Test with sending empty string
@@ -39,12 +41,14 @@ TEST_P(RadioHidlTest, sendEnvelope) {
RadioError::MODEM_ERR, RadioError::SIM_ABSENT},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "sendEnvelope finished";
}
/*
* Test IRadio.sendTerminalResponseToSim() for the response returned.
*/
TEST_P(RadioHidlTest, sendTerminalResponseToSim) {
LOG(DEBUG) << "sendTerminalResponseToSim";
serial = GetRandomSerialNumber();
// Test with sending empty string
@@ -62,12 +66,14 @@ TEST_P(RadioHidlTest, sendTerminalResponseToSim) {
{RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::SIM_ABSENT},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "sendTerminalResponseToSim finished";
}
/*
* Test IRadio.handleStkCallSetupRequestFromSim() for the response returned.
*/
TEST_P(RadioHidlTest, handleStkCallSetupRequestFromSim) {
LOG(DEBUG) << "handleStkCallSetupRequestFromSim";
serial = GetRandomSerialNumber();
bool accept = false;
@@ -83,12 +89,14 @@ TEST_P(RadioHidlTest, handleStkCallSetupRequestFromSim) {
RadioError::MODEM_ERR, RadioError::SIM_ABSENT},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "handleStkCallSetupRequestFromSim finished";
}
/*
* Test IRadio.reportStkServiceIsRunning() for the response returned.
*/
TEST_P(RadioHidlTest, reportStkServiceIsRunning) {
LOG(DEBUG) << "reportStkServiceIsRunning";
serial = GetRandomSerialNumber();
radio->reportStkServiceIsRunning(serial);
@@ -101,6 +109,7 @@ TEST_P(RadioHidlTest, reportStkServiceIsRunning) {
ASSERT_TRUE(
CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "reportStkServiceIsRunning finished";
}
/*
@@ -108,6 +117,7 @@ TEST_P(RadioHidlTest, reportStkServiceIsRunning) {
* string.
*/
TEST_P(RadioHidlTest, sendEnvelopeWithStatus) {
LOG(DEBUG) << "sendEnvelopeWithStatus";
serial = GetRandomSerialNumber();
// Test with sending empty string
@@ -125,4 +135,5 @@ TEST_P(RadioHidlTest, sendEnvelopeWithStatus) {
{RadioError::INVALID_ARGUMENTS, RadioError::MODEM_ERR, RadioError::SIM_ABSENT},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "sendEnvelopeWithStatus finished";
}

View File

@@ -14,11 +14,13 @@
* limitations under the License.
*/
#include <android-base/logging.h>
#include <radio_hidl_hal_utils_v1_0.h>
void RadioHidlTest::SetUp() {
radio = IRadio::getService(GetParam());
if (radio == NULL) {
LOG(DEBUG) << "Radio is NULL, waiting 1 minute to retry";
sleep(60);
radio = IRadio::getService(GetParam());
}
@@ -70,4 +72,4 @@ void RadioHidlTest::updateSimCardStatus() {
serial = GetRandomSerialNumber();
radio->getIccCardStatus(serial);
EXPECT_EQ(std::cv_status::no_timeout, wait());
}
}

View File

@@ -14,12 +14,14 @@
* limitations under the License.
*/
#include <android-base/logging.h>
#include <radio_hidl_hal_utils_v1_0.h>
/*
* Test IRadio.getCurrentCalls() for the response returned.
*/
TEST_P(RadioHidlTest, getCurrentCalls) {
LOG(DEBUG) << "getCurrentCalls";
serial = GetRandomSerialNumber();
radio->getCurrentCalls(serial);
@@ -30,12 +32,14 @@ TEST_P(RadioHidlTest, getCurrentCalls) {
if (cardStatus.cardState == CardState::ABSENT) {
EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
}
LOG(DEBUG) << "getCurrentCalls finished";
}
/*
* Test IRadio.dial() for the response returned.
*/
TEST_P(RadioHidlTest, dial) {
LOG(DEBUG) << "dial";
serial = GetRandomSerialNumber();
Dial dialInfo;
@@ -57,12 +61,14 @@ TEST_P(RadioHidlTest, dial) {
RadioError::OPERATION_NOT_ALLOWED},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "dial finished";
}
/*
* Test IRadio.hangup() for the response returned.
*/
TEST_P(RadioHidlTest, hangup) {
LOG(DEBUG) << "hangup";
serial = GetRandomSerialNumber();
radio->hangup(serial, 1);
@@ -76,12 +82,14 @@ TEST_P(RadioHidlTest, hangup) {
{RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "hangup finished";
}
/*
* Test IRadio.hangupWaitingOrBackground() for the response returned.
*/
TEST_P(RadioHidlTest, hangupWaitingOrBackground) {
LOG(DEBUG) << "hangupWaitingOrBackground";
serial = GetRandomSerialNumber();
radio->hangupWaitingOrBackground(serial);
@@ -94,12 +102,14 @@ TEST_P(RadioHidlTest, hangupWaitingOrBackground) {
{RadioError::INVALID_STATE, RadioError::MODEM_ERR},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "hangupWaitingOrBackground finished";
}
/*
* Test IRadio.hangupForegroundResumeBackground() for the response returned.
*/
TEST_P(RadioHidlTest, hangupForegroundResumeBackground) {
LOG(DEBUG) << "hangupForegroundResumeBackground";
serial = GetRandomSerialNumber();
radio->hangupForegroundResumeBackground(serial);
@@ -112,12 +122,14 @@ TEST_P(RadioHidlTest, hangupForegroundResumeBackground) {
{RadioError::INVALID_STATE, RadioError::MODEM_ERR},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "hangupForegroundResumeBackground finished";
}
/*
* Test IRadio.switchWaitingOrHoldingAndActive() for the response returned.
*/
TEST_P(RadioHidlTest, switchWaitingOrHoldingAndActive) {
LOG(DEBUG) << "switchWaitingOrHoldingAndActive";
serial = GetRandomSerialNumber();
radio->switchWaitingOrHoldingAndActive(serial);
@@ -130,12 +142,14 @@ TEST_P(RadioHidlTest, switchWaitingOrHoldingAndActive) {
{RadioError::INVALID_STATE, RadioError::MODEM_ERR},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "switchWaitingOrHoldingAndActive finished";
}
/*
* Test IRadio.conference() for the response returned.
*/
TEST_P(RadioHidlTest, conference) {
LOG(DEBUG) << "conference";
serial = GetRandomSerialNumber();
radio->conference(serial);
@@ -148,12 +162,14 @@ TEST_P(RadioHidlTest, conference) {
{RadioError::INVALID_STATE, RadioError::MODEM_ERR},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "conference finished";
}
/*
* Test IRadio.rejectCall() for the response returned.
*/
TEST_P(RadioHidlTest, rejectCall) {
LOG(DEBUG) << "rejectCall";
serial = GetRandomSerialNumber();
radio->rejectCall(serial);
@@ -166,12 +182,14 @@ TEST_P(RadioHidlTest, rejectCall) {
{RadioError::INVALID_STATE, RadioError::MODEM_ERR},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "rejectCall finished";
}
/*
* Test IRadio.getLastCallFailCause() for the response returned.
*/
TEST_P(RadioHidlTest, getLastCallFailCause) {
LOG(DEBUG) << "getLastCallFailCause";
serial = GetRandomSerialNumber();
radio->getLastCallFailCause(serial);
@@ -183,12 +201,14 @@ TEST_P(RadioHidlTest, getLastCallFailCause) {
ASSERT_TRUE(
CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "getLastCallFailCause finished";
}
/*
* Test IRadio.sendUssd() for the response returned.
*/
TEST_P(RadioHidlTest, sendUssd) {
LOG(DEBUG) << "sendUssd";
serial = GetRandomSerialNumber();
radio->sendUssd(serial, hidl_string("test"));
EXPECT_EQ(std::cv_status::no_timeout, wait());
@@ -201,12 +221,14 @@ TEST_P(RadioHidlTest, sendUssd) {
{RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "sendUssd finished";
}
/*
* Test IRadio.cancelPendingUssd() for the response returned.
*/
TEST_P(RadioHidlTest, cancelPendingUssd) {
LOG(DEBUG) << "cancelPendingUssd";
serial = GetRandomSerialNumber();
radio->cancelPendingUssd(serial);
@@ -220,12 +242,14 @@ TEST_P(RadioHidlTest, cancelPendingUssd) {
{RadioError::NONE, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "cancelPendingUssd finished";
}
/*
* Test IRadio.getCallForwardStatus() for the response returned.
*/
TEST_P(RadioHidlTest, getCallForwardStatus) {
LOG(DEBUG) << "getCallForwardStatus";
serial = GetRandomSerialNumber();
CallForwardInfo callInfo;
memset(&callInfo, 0, sizeof(callInfo));
@@ -242,12 +266,14 @@ TEST_P(RadioHidlTest, getCallForwardStatus) {
{RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "getCallForwardStatus finished";
}
/*
* Test IRadio.setCallForward() for the response returned.
*/
TEST_P(RadioHidlTest, setCallForward) {
LOG(DEBUG) << "setCallForward";
serial = GetRandomSerialNumber();
CallForwardInfo callInfo;
memset(&callInfo, 0, sizeof(callInfo));
@@ -264,12 +290,14 @@ TEST_P(RadioHidlTest, setCallForward) {
{RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "setCallForward finished";
}
/*
* Test IRadio.getCallWaiting() for the response returned.
*/
TEST_P(RadioHidlTest, getCallWaiting) {
LOG(DEBUG) << "getCallWaiting";
serial = GetRandomSerialNumber();
radio->getCallWaiting(serial, 1);
@@ -283,12 +311,14 @@ TEST_P(RadioHidlTest, getCallWaiting) {
{RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::MODEM_ERR},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "getCallWaiting finished";
}
/*
* Test IRadio.setCallWaiting() for the response returned.
*/
TEST_P(RadioHidlTest, setCallWaiting) {
LOG(DEBUG) << "setCallWaiting";
serial = GetRandomSerialNumber();
radio->setCallWaiting(serial, true, 1);
@@ -302,12 +332,14 @@ TEST_P(RadioHidlTest, setCallWaiting) {
{RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "setCallWaiting finished";
}
/*
* Test IRadio.acceptCall() for the response returned.
*/
TEST_P(RadioHidlTest, acceptCall) {
LOG(DEBUG) << "acceptCall";
serial = GetRandomSerialNumber();
radio->acceptCall(serial);
@@ -320,12 +352,14 @@ TEST_P(RadioHidlTest, acceptCall) {
{RadioError::INVALID_STATE, RadioError::MODEM_ERR},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "acceptCall finished";
}
/*
* Test IRadio.separateConnection() for the response returned.
*/
TEST_P(RadioHidlTest, separateConnection) {
LOG(DEBUG) << "separateConnection";
serial = GetRandomSerialNumber();
radio->separateConnection(serial, 1);
@@ -339,12 +373,14 @@ TEST_P(RadioHidlTest, separateConnection) {
{RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "separateConnection finished";
}
/*
* Test IRadio.explicitCallTransfer() for the response returned.
*/
TEST_P(RadioHidlTest, explicitCallTransfer) {
LOG(DEBUG) << "explicitCallTransfer";
serial = GetRandomSerialNumber();
radio->explicitCallTransfer(serial);
@@ -357,12 +393,14 @@ TEST_P(RadioHidlTest, explicitCallTransfer) {
{RadioError::INVALID_STATE, RadioError::MODEM_ERR},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "explicitCallTransfer finished";
}
/*
* Test IRadio.sendCDMAFeatureCode() for the response returned.
*/
TEST_P(RadioHidlTest, sendCDMAFeatureCode) {
LOG(DEBUG) << "sendCDMAFeatureCode";
serial = GetRandomSerialNumber();
radio->sendCDMAFeatureCode(serial, hidl_string());
@@ -377,12 +415,14 @@ TEST_P(RadioHidlTest, sendCDMAFeatureCode) {
RadioError::MODEM_ERR, RadioError::OPERATION_NOT_ALLOWED},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "sendCDMAFeatureCode finished";
}
/*
* Test IRadio.sendDtmf() for the response returned.
*/
TEST_P(RadioHidlTest, sendDtmf) {
LOG(DEBUG) << "sendDtmf";
serial = GetRandomSerialNumber();
radio->sendDtmf(serial, "1");
@@ -397,12 +437,14 @@ TEST_P(RadioHidlTest, sendDtmf) {
RadioError::INVALID_MODEM_STATE, RadioError::MODEM_ERR},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "sendDtmf finished";
}
/*
* Test IRadio.startDtmf() for the response returned.
*/
TEST_P(RadioHidlTest, startDtmf) {
LOG(DEBUG) << "startDtmf";
serial = GetRandomSerialNumber();
radio->startDtmf(serial, "1");
@@ -417,12 +459,14 @@ TEST_P(RadioHidlTest, startDtmf) {
RadioError::INVALID_MODEM_STATE, RadioError::MODEM_ERR},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "startDtmf finished";
}
/*
* Test IRadio.stopDtmf() for the response returned.
*/
TEST_P(RadioHidlTest, stopDtmf) {
LOG(DEBUG) << "stopDtmf";
serial = GetRandomSerialNumber();
radio->stopDtmf(serial);
@@ -436,12 +480,14 @@ TEST_P(RadioHidlTest, stopDtmf) {
RadioError::INVALID_MODEM_STATE, RadioError::MODEM_ERR},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "stopDtmf finished";
}
/*
* Test IRadio.setMute() for the response returned.
*/
TEST_P(RadioHidlTest, setMute) {
LOG(DEBUG) << "setMute";
serial = GetRandomSerialNumber();
radio->setMute(serial, true);
@@ -454,12 +500,14 @@ TEST_P(RadioHidlTest, setMute) {
{RadioError::NONE, RadioError::INVALID_ARGUMENTS},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "setMute finished";
}
/*
* Test IRadio.getMute() for the response returned.
*/
TEST_P(RadioHidlTest, getMute) {
LOG(DEBUG) << "getMute";
serial = GetRandomSerialNumber();
radio->getMute(serial);
@@ -470,12 +518,14 @@ TEST_P(RadioHidlTest, getMute) {
if (cardStatus.cardState == CardState::ABSENT) {
EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
}
LOG(DEBUG) << "getMute finished";
}
/*
* Test IRadio.sendBurstDtmf() for the response returned.
*/
TEST_P(RadioHidlTest, sendBurstDtmf) {
LOG(DEBUG) << "sendBurstDtmf";
serial = GetRandomSerialNumber();
radio->sendBurstDtmf(serial, "1", 0, 0);
@@ -489,4 +539,5 @@ TEST_P(RadioHidlTest, sendBurstDtmf) {
RadioError::MODEM_ERR, RadioError::OPERATION_NOT_ALLOWED},
CHECK_GENERAL_ERROR));
}
LOG(DEBUG) << "sendBurstDtmf finished";
}

View File

@@ -14,12 +14,14 @@
* limitations under the License.
*/
#include <android-base/logging.h>
#include <sap_hidl_hal_utils.h>
/*
* Test ISap.connectReq() for the response returned.
*/
TEST_P(SapHidlTest, connectReq) {
LOG(DEBUG) << "connectReq";
token = GetRandomSerialNumber();
int32_t maxMsgSize = 100;
@@ -30,23 +32,27 @@ TEST_P(SapHidlTest, connectReq) {
// Modem side need time for connect to finish. Adding a waiting time to prevent
// disconnect being requested right after connect request.
sleep(1);
LOG(DEBUG) << "connectReq finished";
}
/*
* Test IRadio.disconnectReq() for the response returned
*/
TEST_P(SapHidlTest, disconnectReq) {
LOG(DEBUG) << "disconnectReq";
token = GetRandomSerialNumber();
sap->disconnectReq(token);
EXPECT_EQ(std::cv_status::no_timeout, wait());
EXPECT_EQ(sapCb->sapResponseToken, token);
LOG(DEBUG) << "disconnectReq finished";
}
/*
* Test IRadio.apduReq() for the response returned.
*/
TEST_P(SapHidlTest, apduReq) {
LOG(DEBUG) << "apduReq";
token = GetRandomSerialNumber();
SapApduType sapApduType = SapApduType::APDU;
android::hardware::hidl_vec<uint8_t> command = {};
@@ -59,12 +65,14 @@ TEST_P(SapHidlTest, apduReq) {
CheckAnyOfErrors(sapCb->sapResultCode,
{SapResultCode::GENERIC_FAILURE, SapResultCode::CARD_ALREADY_POWERED_OFF,
SapResultCode::CARD_NOT_ACCESSSIBLE, SapResultCode::CARD_REMOVED}));
LOG(DEBUG) << "apduReq finished";
}
/*
* Test IRadio.transferAtrReq() for the response returned.
*/
TEST_P(SapHidlTest, transferAtrReq) {
LOG(DEBUG) << "transferAtrReq";
token = GetRandomSerialNumber();
sap->transferAtrReq(token);
@@ -75,12 +83,14 @@ TEST_P(SapHidlTest, transferAtrReq) {
CheckAnyOfErrors(sapCb->sapResultCode,
{SapResultCode::GENERIC_FAILURE, SapResultCode::DATA_NOT_AVAILABLE,
SapResultCode::CARD_ALREADY_POWERED_OFF, SapResultCode::CARD_REMOVED}));
LOG(DEBUG) << "transferAtrReq finished";
}
/*
* Test IRadio.powerReq() for the response returned.
*/
TEST_P(SapHidlTest, powerReq) {
LOG(DEBUG) << "powerReq";
token = GetRandomSerialNumber();
bool state = true;
@@ -92,12 +102,14 @@ TEST_P(SapHidlTest, powerReq) {
sapCb->sapResultCode, {SapResultCode::GENERIC_FAILURE, SapResultCode::CARD_NOT_ACCESSSIBLE,
SapResultCode::CARD_ALREADY_POWERED_OFF, SapResultCode::CARD_REMOVED,
SapResultCode::CARD_ALREADY_POWERED_ON}));
LOG(DEBUG) << "powerReq finished";
}
/*
* Test IRadio.resetSimReq() for the response returned.
*/
TEST_P(SapHidlTest, resetSimReq) {
LOG(DEBUG) << "resetSimReq";
token = GetRandomSerialNumber();
sap->resetSimReq(token);
@@ -108,12 +120,14 @@ TEST_P(SapHidlTest, resetSimReq) {
CheckAnyOfErrors(sapCb->sapResultCode,
{SapResultCode::GENERIC_FAILURE, SapResultCode::CARD_NOT_ACCESSSIBLE,
SapResultCode::CARD_ALREADY_POWERED_OFF, SapResultCode::CARD_REMOVED}));
LOG(DEBUG) << "resetSimReq finished";
}
/*
* Test IRadio.transferCardReaderStatusReq() for the response returned.
*/
TEST_P(SapHidlTest, transferCardReaderStatusReq) {
LOG(DEBUG) << "transferCardReaderStatusReq";
token = GetRandomSerialNumber();
sap->transferCardReaderStatusReq(token);
@@ -122,12 +136,14 @@ TEST_P(SapHidlTest, transferCardReaderStatusReq) {
ASSERT_TRUE(CheckAnyOfErrors(
sapCb->sapResultCode, {SapResultCode::GENERIC_FAILURE, SapResultCode::DATA_NOT_AVAILABLE}));
LOG(DEBUG) << "transferCardReaderStatusReq finished";
}
/*
* Test IRadio.setTransferProtocolReq() for the response returned.
*/
TEST_P(SapHidlTest, setTransferProtocolReq) {
LOG(DEBUG) << "setTransferProtocolReq";
token = GetRandomSerialNumber();
SapTransferProtocol sapTransferProtocol = SapTransferProtocol::T0;
@@ -136,4 +152,5 @@ TEST_P(SapHidlTest, setTransferProtocolReq) {
EXPECT_EQ(sapCb->sapResponseToken, token);
EXPECT_EQ(SapResultCode::NOT_SUPPORTED, sapCb->sapResultCode);
LOG(DEBUG) << "setTransferProtocolReq finished";
}

View File

@@ -30,5 +30,6 @@
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="VtsHalRadioV1_0TargetTest" />
<option name="native-test-timeout" value="300000" /> <!-- 5 min -->
</test>
</configuration>

View File

@@ -22,6 +22,8 @@
<target_preparer class="com.android.tradefed.targetprep.MultiSimPreparer" />
<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
<target_preparer class="com.android.tradefed.targetprep.StopServicesSetup"/>
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="VtsHalSapV1_0TargetTest->/data/local/tmp/VtsHalSapV1_0TargetTest" />

View File

@@ -29,6 +29,7 @@
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="native-test-timeout" value="300000" /> <!-- 5 min -->
<option name="module-name" value="VtsHalRadioV1_1TargetTest" />
</test>
</configuration>

View File

@@ -49,7 +49,6 @@ TEST_P(RadioHidlTest_v1_1, setSimCardPower_1_1) {
}
EXPECT_EQ(CardState::ABSENT, cardStatus.cardState);
}
#endif
/* Test setSimCardPower power up */
serial = GetRandomSerialNumber();
@@ -60,6 +59,7 @@ TEST_P(RadioHidlTest_v1_1, setSimCardPower_1_1) {
ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_1->rspInfo.error,
{RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED,
RadioError::INVALID_ARGUMENTS, RadioError::RADIO_NOT_AVAILABLE}));
#endif
/**
* If the sim card status for the testing environment is PRESENT,

View File

@@ -735,7 +735,7 @@ TEST_P(RadioHidlTest_v1_2, getDataRegistrationState) {
EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_2->rspInfo.type);
EXPECT_EQ(serial, radioRsp_v1_2->rspInfo.serial);
ALOGI("getVoiceRegistrationStateResponse_1_2, rspInfo.error = %s\n",
ALOGI("getDataRegistrationStateResponse_1_2, rspInfo.error = %s\n",
toString(radioRsp_v1_2->rspInfo.error).c_str());
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_v1_2->rspInfo.error,

View File

@@ -18,6 +18,15 @@
#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
namespace {
const RadioAccessSpecifier GERAN_SPECIFIER_P900 = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
.geranBands = {GeranBands::BAND_P900},
.channels = {1, 2}};
const RadioAccessSpecifier GERAN_SPECIFIER_850 = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
.geranBands = {GeranBands::BAND_850},
.channels = {128, 129}};
} // namespace
/*
* Test IRadio.emergencyDial() for the response returned.
*/
@@ -199,14 +208,10 @@ TEST_P(RadioHidlTest_v1_4, setPreferredNetworkTypeBitmap) {
TEST_P(RadioHidlTest_v1_4, startNetworkScan) {
serial = GetRandomSerialNumber();
RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
.geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
.channels = {1, 2}};
::android::hardware::radio::V1_2::NetworkScanRequest request = {
.type = ScanType::ONE_SHOT,
.interval = 60,
.specifiers = {specifier},
.specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
.maxSearchTime = 60,
.incrementalResults = false,
.incrementalResultsPeriodicity = 1};
@@ -234,6 +239,11 @@ TEST_P(RadioHidlTest_v1_4, startNetworkScan) {
{RadioError::NONE, RadioError::OPERATION_NOT_ALLOWED,
RadioError::REQUEST_NOT_SUPPORTED}));
}
if (radioRsp_v1_4->rspInfo.error == RadioError::NONE) {
ALOGI("Stop Network Scan");
stopNetworkScan();
}
}
/*
@@ -270,14 +280,10 @@ TEST_P(RadioHidlTest_v1_4, startNetworkScan_InvalidArgument) {
TEST_P(RadioHidlTest_v1_4, startNetworkScan_InvalidInterval1) {
serial = GetRandomSerialNumber();
RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
.geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
.channels = {1, 2}};
::android::hardware::radio::V1_2::NetworkScanRequest request = {
.type = ScanType::ONE_SHOT,
.interval = 4,
.specifiers = {specifier},
.specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
.maxSearchTime = 60,
.incrementalResults = false,
.incrementalResultsPeriodicity = 1};
@@ -307,14 +313,10 @@ TEST_P(RadioHidlTest_v1_4, startNetworkScan_InvalidInterval1) {
TEST_P(RadioHidlTest_v1_4, startNetworkScan_InvalidInterval2) {
serial = GetRandomSerialNumber();
RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
.geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
.channels = {1, 2}};
::android::hardware::radio::V1_2::NetworkScanRequest request = {
.type = ScanType::ONE_SHOT,
.interval = 301,
.specifiers = {specifier},
.specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
.maxSearchTime = 60,
.incrementalResults = false,
.incrementalResultsPeriodicity = 1};
@@ -343,14 +345,10 @@ TEST_P(RadioHidlTest_v1_4, startNetworkScan_InvalidInterval2) {
TEST_P(RadioHidlTest_v1_4, startNetworkScan_InvalidMaxSearchTime1) {
serial = GetRandomSerialNumber();
RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
.geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
.channels = {1, 2}};
::android::hardware::radio::V1_2::NetworkScanRequest request = {
.type = ScanType::ONE_SHOT,
.interval = 60,
.specifiers = {specifier},
.specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
.maxSearchTime = 59,
.incrementalResults = false,
.incrementalResultsPeriodicity = 1};
@@ -379,14 +377,10 @@ TEST_P(RadioHidlTest_v1_4, startNetworkScan_InvalidMaxSearchTime1) {
TEST_P(RadioHidlTest_v1_4, startNetworkScan_InvalidMaxSearchTime2) {
serial = GetRandomSerialNumber();
RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
.geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
.channels = {1, 2}};
::android::hardware::radio::V1_2::NetworkScanRequest request = {
.type = ScanType::ONE_SHOT,
.interval = 60,
.specifiers = {specifier},
.specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
.maxSearchTime = 3601,
.incrementalResults = false,
.incrementalResultsPeriodicity = 1};
@@ -415,14 +409,10 @@ TEST_P(RadioHidlTest_v1_4, startNetworkScan_InvalidMaxSearchTime2) {
TEST_P(RadioHidlTest_v1_4, startNetworkScan_InvalidPeriodicity1) {
serial = GetRandomSerialNumber();
RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
.geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
.channels = {1, 2}};
::android::hardware::radio::V1_2::NetworkScanRequest request = {
.type = ScanType::ONE_SHOT,
.interval = 60,
.specifiers = {specifier},
.specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
.maxSearchTime = 600,
.incrementalResults = true,
.incrementalResultsPeriodicity = 0};
@@ -451,14 +441,10 @@ TEST_P(RadioHidlTest_v1_4, startNetworkScan_InvalidPeriodicity1) {
TEST_P(RadioHidlTest_v1_4, startNetworkScan_InvalidPeriodicity2) {
serial = GetRandomSerialNumber();
RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
.geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
.channels = {1, 2}};
::android::hardware::radio::V1_2::NetworkScanRequest request = {
.type = ScanType::ONE_SHOT,
.interval = 60,
.specifiers = {specifier},
.specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
.maxSearchTime = 600,
.incrementalResults = true,
.incrementalResultsPeriodicity = 11};
@@ -487,14 +473,10 @@ TEST_P(RadioHidlTest_v1_4, startNetworkScan_InvalidPeriodicity2) {
TEST_P(RadioHidlTest_v1_4, startNetworkScan_GoodRequest1) {
serial = GetRandomSerialNumber();
RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
.geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
.channels = {1, 2}};
::android::hardware::radio::V1_2::NetworkScanRequest request = {
.type = ScanType::ONE_SHOT,
.interval = 60,
.specifiers = {specifier},
.specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
// Some vendor may not support max search time of 360s.
// This issue is tracked in b/112205669.
.maxSearchTime = 300,
@@ -518,6 +500,11 @@ TEST_P(RadioHidlTest_v1_4, startNetworkScan_GoodRequest1) {
{RadioError::NONE, RadioError::INVALID_ARGUMENTS,
RadioError::REQUEST_NOT_SUPPORTED}));
}
if (radioRsp_v1_4->rspInfo.error == RadioError::NONE) {
ALOGI("Stop Network Scan");
stopNetworkScan();
}
}
/*
@@ -526,14 +513,10 @@ TEST_P(RadioHidlTest_v1_4, startNetworkScan_GoodRequest1) {
TEST_P(RadioHidlTest_v1_4, startNetworkScan_GoodRequest2) {
serial = GetRandomSerialNumber();
RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
.geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
.channels = {1, 2}};
::android::hardware::radio::V1_2::NetworkScanRequest request = {
.type = ScanType::ONE_SHOT,
.interval = 60,
.specifiers = {specifier},
.specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
// Some vendor may not support max search time of 360s.
// This issue is tracked in b/112205669.
.maxSearchTime = 300,
@@ -559,6 +542,11 @@ TEST_P(RadioHidlTest_v1_4, startNetworkScan_GoodRequest2) {
{RadioError::NONE, RadioError::INVALID_ARGUMENTS,
RadioError::REQUEST_NOT_SUPPORTED}));
}
if (radioRsp_v1_4->rspInfo.error == RadioError::NONE) {
ALOGI("Stop Network Scan");
stopNetworkScan();
}
}
/*

View File

@@ -107,3 +107,9 @@ void RadioHidlTest_v1_4::updateSimCardStatus() {
radio_v1_4->getIccCardStatus(serial);
EXPECT_EQ(std::cv_status::no_timeout, wait());
}
void RadioHidlTest_v1_4::stopNetworkScan() {
serial = GetRandomSerialNumber();
radio_v1_4->stopNetworkScan(serial);
EXPECT_EQ(std::cv_status::no_timeout, wait());
}

View File

@@ -721,7 +721,10 @@ class RadioHidlTest_v1_4 : public ::testing::TestWithParam<std::string> {
/* Update Sim Card Status */
void updateSimCardStatus();
public:
/* Stop Network Scan Command */
void stopNetworkScan();
public:
virtual void SetUp() override;
/* Used as a mechanism to inform the test about data/event callback */

View File

@@ -14,6 +14,7 @@
* limitations under the License.
*/
#include <android-base/properties.h>
#include <radio_hidl_hal_utils_v1_5.h>
#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
@@ -248,7 +249,7 @@ TEST_P(RadioHidlTest_v1_5, setSignalStrengthReportingCriteria_1_5_NGRAN_SSRSRQ)
signalThresholdInfo.signalMeasurement = SignalMeasurementType::SSRSRQ;
signalThresholdInfo.hysteresisMs = 5000;
signalThresholdInfo.hysteresisDb = 0;
signalThresholdInfo.thresholds = {-15, -10, -5, -4};
signalThresholdInfo.thresholds = {-43, -20, 0, 20};
signalThresholdInfo.isEnabled = true;
Return<void> res = radio_v1_5->setSignalStrengthReportingCriteria_1_5(
@@ -502,15 +503,21 @@ TEST_P(RadioHidlTest_v1_5, areUiccApplicationsEnabled) {
TEST_P(RadioHidlTest_v1_5, setSystemSelectionChannels_1_5) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands bandP900;
bandP900.geranBands() = {GeranBands::BAND_P900};
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands band850;
band850.geranBands() = {GeranBands::BAND_850};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifierP900 = {
.radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
.bands = rasBands,
.bands = bandP900,
.channels = {1, 2}};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifier850 = {
.radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
.bands = band850,
.channels = {128, 129}};
Return<void> res = radio_v1_5->setSystemSelectionChannels_1_5(serial, true, {specifier});
Return<void> res =
radio_v1_5->setSystemSelectionChannels_1_5(serial, true, {specifierP900, specifier850});
ASSERT_OK(res);
EXPECT_EQ(std::cv_status::no_timeout, wait());
EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
@@ -523,7 +530,8 @@ TEST_P(RadioHidlTest_v1_5, setSystemSelectionChannels_1_5) {
if (radioRsp_v1_5->rspInfo.error == RadioError::NONE) {
serial = GetRandomSerialNumber();
Return<void> res = radio_v1_5->setSystemSelectionChannels_1_5(serial, false, {specifier});
Return<void> res = radio_v1_5->setSystemSelectionChannels_1_5(
serial, false, {specifierP900, specifier850});
ASSERT_OK(res);
EXPECT_EQ(std::cv_status::no_timeout, wait());
EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
@@ -540,18 +548,23 @@ TEST_P(RadioHidlTest_v1_5, setSystemSelectionChannels_1_5) {
TEST_P(RadioHidlTest_v1_5, startNetworkScan) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands bandP900;
bandP900.geranBands() = {GeranBands::BAND_P900};
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands band850;
band850.geranBands() = {GeranBands::BAND_850};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifierP900 = {
.radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
.bands = rasBands,
.bands = bandP900,
.channels = {1, 2}};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifier850 = {
.radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
.bands = band850,
.channels = {128, 129}};
::android::hardware::radio::V1_5::NetworkScanRequest request = {
.type = ScanType::ONE_SHOT,
.interval = 60,
.specifiers = {specifier},
.specifiers = {specifierP900, specifier850},
.maxSearchTime = 60,
.incrementalResults = false,
.incrementalResultsPeriodicity = 1};
@@ -573,6 +586,11 @@ TEST_P(RadioHidlTest_v1_5, startNetworkScan) {
ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
{RadioError::NONE, RadioError::OPERATION_NOT_ALLOWED}));
}
if (radioRsp_v1_5->rspInfo.error == RadioError::NONE) {
ALOGI("Stop Network Scan");
stopNetworkScan();
}
}
/*
@@ -608,18 +626,23 @@ TEST_P(RadioHidlTest_v1_5, startNetworkScan_InvalidArgument) {
TEST_P(RadioHidlTest_v1_5, startNetworkScan_InvalidInterval1) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands bandP900;
bandP900.geranBands() = {GeranBands::BAND_P900};
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands band850;
band850.geranBands() = {GeranBands::BAND_850};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifierP900 = {
.radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
.bands = rasBands,
.bands = bandP900,
.channels = {1, 2}};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifier850 = {
.radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
.bands = band850,
.channels = {128, 129}};
::android::hardware::radio::V1_5::NetworkScanRequest request = {
.type = ScanType::ONE_SHOT,
.interval = 4,
.specifiers = {specifier},
.specifiers = {specifierP900, specifier850},
.maxSearchTime = 60,
.incrementalResults = false,
.incrementalResultsPeriodicity = 1};
@@ -647,18 +670,23 @@ TEST_P(RadioHidlTest_v1_5, startNetworkScan_InvalidInterval1) {
TEST_P(RadioHidlTest_v1_5, startNetworkScan_InvalidInterval2) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands bandP900;
bandP900.geranBands() = {GeranBands::BAND_P900};
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands band850;
band850.geranBands() = {GeranBands::BAND_850};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifierP900 = {
.radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
.bands = rasBands,
.bands = bandP900,
.channels = {1, 2}};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifier850 = {
.radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
.bands = band850,
.channels = {128, 129}};
::android::hardware::radio::V1_5::NetworkScanRequest request = {
.type = ScanType::ONE_SHOT,
.interval = 301,
.specifiers = {specifier},
.specifiers = {specifierP900, specifier850},
.maxSearchTime = 60,
.incrementalResults = false,
.incrementalResultsPeriodicity = 1};
@@ -686,18 +714,23 @@ TEST_P(RadioHidlTest_v1_5, startNetworkScan_InvalidInterval2) {
TEST_P(RadioHidlTest_v1_5, startNetworkScan_InvalidMaxSearchTime1) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands bandP900;
bandP900.geranBands() = {GeranBands::BAND_P900};
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands band850;
band850.geranBands() = {GeranBands::BAND_850};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifierP900 = {
.radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
.bands = rasBands,
.bands = bandP900,
.channels = {1, 2}};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifier850 = {
.radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
.bands = band850,
.channels = {128, 129}};
::android::hardware::radio::V1_5::NetworkScanRequest request = {
.type = ScanType::ONE_SHOT,
.interval = 60,
.specifiers = {specifier},
.specifiers = {specifierP900, specifier850},
.maxSearchTime = 59,
.incrementalResults = false,
.incrementalResultsPeriodicity = 1};
@@ -725,18 +758,23 @@ TEST_P(RadioHidlTest_v1_5, startNetworkScan_InvalidMaxSearchTime1) {
TEST_P(RadioHidlTest_v1_5, startNetworkScan_InvalidMaxSearchTime2) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands bandP900;
bandP900.geranBands() = {GeranBands::BAND_P900};
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands band850;
band850.geranBands() = {GeranBands::BAND_850};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifierP900 = {
.radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
.bands = rasBands,
.bands = bandP900,
.channels = {1, 2}};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifier850 = {
.radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
.bands = band850,
.channels = {128, 129}};
::android::hardware::radio::V1_5::NetworkScanRequest request = {
.type = ScanType::ONE_SHOT,
.interval = 60,
.specifiers = {specifier},
.specifiers = {specifierP900, specifier850},
.maxSearchTime = 3601,
.incrementalResults = false,
.incrementalResultsPeriodicity = 1};
@@ -764,18 +802,23 @@ TEST_P(RadioHidlTest_v1_5, startNetworkScan_InvalidMaxSearchTime2) {
TEST_P(RadioHidlTest_v1_5, startNetworkScan_InvalidPeriodicity1) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands bandP900;
bandP900.geranBands() = {GeranBands::BAND_P900};
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands band850;
band850.geranBands() = {GeranBands::BAND_850};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifierP900 = {
.radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
.bands = rasBands,
.bands = bandP900,
.channels = {1, 2}};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifier850 = {
.radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
.bands = band850,
.channels = {128, 129}};
::android::hardware::radio::V1_5::NetworkScanRequest request = {
.type = ScanType::ONE_SHOT,
.interval = 60,
.specifiers = {specifier},
.specifiers = {specifierP900, specifier850},
.maxSearchTime = 600,
.incrementalResults = true,
.incrementalResultsPeriodicity = 0};
@@ -803,18 +846,23 @@ TEST_P(RadioHidlTest_v1_5, startNetworkScan_InvalidPeriodicity1) {
TEST_P(RadioHidlTest_v1_5, startNetworkScan_InvalidPeriodicity2) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands bandP900;
bandP900.geranBands() = {GeranBands::BAND_P900};
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands band850;
band850.geranBands() = {GeranBands::BAND_850};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifierP900 = {
.radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
.bands = rasBands,
.bands = bandP900,
.channels = {1, 2}};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifier850 = {
.radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
.bands = band850,
.channels = {128, 129}};
::android::hardware::radio::V1_5::NetworkScanRequest request = {
.type = ScanType::ONE_SHOT,
.interval = 60,
.specifiers = {specifier},
.specifiers = {specifierP900, specifier850},
.maxSearchTime = 600,
.incrementalResults = true,
.incrementalResultsPeriodicity = 11};
@@ -842,18 +890,23 @@ TEST_P(RadioHidlTest_v1_5, startNetworkScan_InvalidPeriodicity2) {
TEST_P(RadioHidlTest_v1_5, startNetworkScan_GoodRequest1) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands bandP900;
bandP900.geranBands() = {GeranBands::BAND_P900};
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands band850;
band850.geranBands() = {GeranBands::BAND_850};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifierP900 = {
.radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
.bands = rasBands,
.bands = bandP900,
.channels = {1, 2}};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifier850 = {
.radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
.bands = band850,
.channels = {128, 129}};
::android::hardware::radio::V1_5::NetworkScanRequest request = {
.type = ScanType::ONE_SHOT,
.interval = 60,
.specifiers = {specifier},
.specifiers = {specifierP900, specifier850},
.maxSearchTime = 360,
.incrementalResults = false,
.incrementalResultsPeriodicity = 10};
@@ -873,6 +926,11 @@ TEST_P(RadioHidlTest_v1_5, startNetworkScan_GoodRequest1) {
{RadioError::NONE, RadioError::INVALID_ARGUMENTS,
RadioError::REQUEST_NOT_SUPPORTED}));
}
if (radioRsp_v1_5->rspInfo.error == RadioError::NONE) {
ALOGI("Stop Network Scan");
stopNetworkScan();
}
}
/*
@@ -881,18 +939,23 @@ TEST_P(RadioHidlTest_v1_5, startNetworkScan_GoodRequest1) {
TEST_P(RadioHidlTest_v1_5, startNetworkScan_GoodRequest2) {
serial = GetRandomSerialNumber();
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands bandP900;
bandP900.geranBands() = {GeranBands::BAND_P900};
::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands band850;
band850.geranBands() = {GeranBands::BAND_850};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifierP900 = {
.radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
.bands = rasBands,
.bands = bandP900,
.channels = {1, 2}};
::android::hardware::radio::V1_5::RadioAccessSpecifier specifier850 = {
.radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
.bands = band850,
.channels = {128, 129}};
::android::hardware::radio::V1_5::NetworkScanRequest request = {
.type = ScanType::ONE_SHOT,
.interval = 60,
.specifiers = {specifier},
.specifiers = {specifierP900, specifier850},
.maxSearchTime = 360,
.incrementalResults = false,
.incrementalResultsPeriodicity = 10,
@@ -913,6 +976,11 @@ TEST_P(RadioHidlTest_v1_5, startNetworkScan_GoodRequest2) {
{RadioError::NONE, RadioError::INVALID_ARGUMENTS,
RadioError::REQUEST_NOT_SUPPORTED}));
}
if (radioRsp_v1_5->rspInfo.error == RadioError::NONE) {
ALOGI("Stop Network Scan");
stopNetworkScan();
}
}
/*
@@ -1174,6 +1242,17 @@ TEST_P(RadioHidlTest_v1_5, getBarringInfo) {
EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
int32_t firstApiLevel = android::base::GetIntProperty<int32_t>("ro.product.first_api_level", 0);
// Allow devices shipping with Radio::1_5 and Android 11 to not support barring info.
if (firstApiLevel > 0 && firstApiLevel <= 30) {
ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
{RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
// Early exit for devices that don't support barring info.
if (radioRsp_v1_5->rspInfo.error != RadioError::NONE) {
return;
}
}
ASSERT_TRUE(radioRsp_v1_5->barringInfos.size() > 0);
std::set<BarringInfo::ServiceType> reportedServices;

View File

@@ -78,3 +78,9 @@ void RadioHidlTest_v1_5::updateSimCardStatus() {
radio_v1_5->getIccCardStatus(serial);
EXPECT_EQ(std::cv_status::no_timeout, wait());
}
void RadioHidlTest_v1_5::stopNetworkScan() {
serial = GetRandomSerialNumber();
radio_v1_5->stopNetworkScan(serial);
EXPECT_EQ(std::cv_status::no_timeout, wait());
}

View File

@@ -831,6 +831,9 @@ class RadioHidlTest_v1_5 : public ::testing::TestWithParam<std::string> {
/* Update Sim Card Status */
void updateSimCardStatus();
/* Stop Network Scan Command */
void stopNetworkScan();
public:
virtual void SetUp() override;

View File

@@ -1017,8 +1017,10 @@ Return<void> RadioResponse_v1_5::setNetworkSelectionModeManualResponse_1_5(
return Void();
}
Return<void> RadioResponse_v1_5::sendCdmaSmsExpectMoreResponse(const RadioResponseInfo& /*info*/,
Return<void> RadioResponse_v1_5::sendCdmaSmsExpectMoreResponse(const RadioResponseInfo& info,
const SendSmsResult& /*sms*/) {
rspInfo = info;
parent_v1_5.notify(info.serial);
return Void();
}

View File

@@ -0,0 +1,7 @@
Many of the tests in this directory may require that TEE Keymaster
"EARLY_BOOT_ONLY" keys be usable when this test runs. In order to accomplish
this, a build of "vold" that omits the call to "earlyBootEnded()" function
should be made. Then these DISABLED tests may be run successfully.
The CTS test ResumeOnRebootHostTests will test the functionality without a
special build.

View File

@@ -60,7 +60,10 @@ class RebootEscrowAidlTest : public testing::TestWithParam<std::string> {
};
};
TEST_P(RebootEscrowAidlTest, StoreAndRetrieve_Success) {
// This test assumes that it can retrieve keys immediately, but some
// implementations use the TEE's EARLY_BOOT_ONLY keys. This means that the
// earlyBootEnded() calls will need to be disabled to test this correctly.
TEST_P(RebootEscrowAidlTest, DISABLED_StoreAndRetrieve_Success) {
SKIP_UNSUPPORTED;
ASSERT_TRUE(rebootescrow->storeKey(KEY_1).isOk());
@@ -70,7 +73,10 @@ TEST_P(RebootEscrowAidlTest, StoreAndRetrieve_Success) {
EXPECT_EQ(actualKey, KEY_1);
}
TEST_P(RebootEscrowAidlTest, StoreAndRetrieve_SecondRetrieveSucceeds) {
// This test assumes that it can retrieve keys immediately, but some
// implementations use the TEE's EARLY_BOOT_ONLY keys. This means that the
// earlyBootEnded() calls will need to be disabled to test this correctly.
TEST_P(RebootEscrowAidlTest, DISABLED_StoreAndRetrieve_SecondRetrieveSucceeds) {
SKIP_UNSUPPORTED;
ASSERT_TRUE(rebootescrow->storeKey(KEY_1).isOk());
@@ -83,7 +89,10 @@ TEST_P(RebootEscrowAidlTest, StoreAndRetrieve_SecondRetrieveSucceeds) {
EXPECT_EQ(actualKey, KEY_1);
}
TEST_P(RebootEscrowAidlTest, StoreTwiceOverwrites_Success) {
// This test assumes that it can retrieve keys immediately, but some
// implementations use the TEE's EARLY_BOOT_ONLY keys. This means that the
// earlyBootEnded() calls will need to be disabled to test this correctly.
TEST_P(RebootEscrowAidlTest, DISABLED_StoreTwiceOverwrites_Success) {
SKIP_UNSUPPORTED;
ASSERT_TRUE(rebootescrow->storeKey(KEY_1).isOk());
@@ -94,7 +103,10 @@ TEST_P(RebootEscrowAidlTest, StoreTwiceOverwrites_Success) {
EXPECT_EQ(actualKey, KEY_2);
}
TEST_P(RebootEscrowAidlTest, StoreEmpty_AfterGetEmptyKey_Success) {
// This test assumes that it can retrieve keys immediately, but some
// implementations use the TEE's EARLY_BOOT_ONLY keys. This means that the
// earlyBootEnded() calls will need to be disabled to test this correctly.
TEST_P(RebootEscrowAidlTest, DISABLED_StoreEmpty_AfterGetEmptyKey_Success) {
SKIP_UNSUPPORTED;
rebootescrow->storeKey(KEY_1);
@@ -105,6 +117,12 @@ TEST_P(RebootEscrowAidlTest, StoreEmpty_AfterGetEmptyKey_Success) {
EXPECT_EQ(actualKey, EMPTY_KEY);
}
TEST_P(RebootEscrowAidlTest, Store_Success) {
SKIP_UNSUPPORTED;
rebootescrow->storeKey(KEY_1);
}
INSTANTIATE_TEST_SUITE_P(
RebootEscrow, RebootEscrowAidlTest,
testing::ValuesIn(android::getAidlHalInstanceNames(IRebootEscrow::descriptor)),

View File

@@ -3,6 +3,8 @@
hidl_interface {
name: "android.hardware.renderscript@1.0",
root: "android.hardware",
// TODO(b/153609531): remove when no longer needed.
native_bridge_supported: true,
vndk: {
enabled: true,
support_system_process: true,

View File

@@ -23,11 +23,6 @@ cc_test {
"VtsHalSensorsV1_0TargetTest.cpp",
],
static_libs: [
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.allocator@3.0",
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@2.1",
"android.hardware.graphics.mapper@3.0",
"android.hardware.sensors@1.0",
"VtsHalSensorsTargetTestUtils",
],

View File

@@ -25,11 +25,6 @@ cc_test {
"android.hardware.sensors@2.X-shared-utils",
],
static_libs: [
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.allocator@3.0",
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@2.1",
"android.hardware.graphics.mapper@3.0",
"android.hardware.sensors@1.0",
"android.hardware.sensors@1.0-convert",
"android.hardware.sensors@2.0",

View File

@@ -27,11 +27,6 @@ cc_test {
"android.hardware.sensors@2.X-shared-utils",
],
static_libs: [
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.allocator@3.0",
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@2.1",
"android.hardware.graphics.mapper@3.0",
"android.hardware.sensors@1.0",
"android.hardware.sensors@1.0-convert",
"android.hardware.sensors@2.0",

View File

@@ -29,11 +29,6 @@ cc_defaults {
"libbinder",
],
static_libs: [
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.allocator@3.0",
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@2.1",
"android.hardware.graphics.mapper@3.0",
"android.hardware.sensors@1.0",
"android.hardware.sensors@1.0-convert",
"android.hardware.sensors@2.0",

Some files were not shown because too many files have changed in this diff Show More