Merge "Merge ab/12162526 into stage-aosp-rvc-ts-dev" into stage-aosp-rvc-ts-dev
diff --git a/audio/4.0/Android.bp b/audio/4.0/Android.bp
index 862c711..bc695c8 100644
--- a/audio/4.0/Android.bp
+++ b/audio/4.0/Android.bp
@@ -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,
},
diff --git a/audio/common/2.0/Android.bp b/audio/common/2.0/Android.bp
index bd3b069..56b43ff 100644
--- a/audio/common/2.0/Android.bp
+++ b/audio/common/2.0/Android.bp
@@ -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,
},
diff --git a/audio/common/4.0/Android.bp b/audio/common/4.0/Android.bp
index c01c486..e4676ec 100644
--- a/audio/common/4.0/Android.bp
+++ b/audio/common/4.0/Android.bp
@@ -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,
},
diff --git a/audio/effect/2.0/Android.bp b/audio/effect/2.0/Android.bp
index d4482c2..7b37260 100644
--- a/audio/effect/2.0/Android.bp
+++ b/audio/effect/2.0/Android.bp
@@ -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,
},
diff --git a/audio/effect/4.0/Android.bp b/audio/effect/4.0/Android.bp
index 8c1900f..2242d6d 100644
--- a/audio/effect/4.0/Android.bp
+++ b/audio/effect/4.0/Android.bp
@@ -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,
},
diff --git a/automotive/evs/1.1/types.hal b/automotive/evs/1.1/types.hal
index 1f69f09..e699fd0 100644
--- a/automotive/evs/1.1/types.hal
+++ b/automotive/evs/1.1/types.hal
@@ -105,6 +105,10 @@
* Master role has become available
*/
MASTER_RELEASED,
+ /**
+ * Any other erroneous streaming events
+ */
+ STREAM_ERROR,
};
/**
diff --git a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
index 6a386c3..8b68fd6 100644
--- a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
+++ b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
@@ -2262,6 +2262,7 @@
// 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;
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index a4fd641..d9ac239 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -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 {
+ 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 {
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_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 {
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 {
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_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",
],
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index b8a606a..16c33b9 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -1039,6 +1039,22 @@
{
.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 =
+ {
.prop = toInt(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION),
.access = VehiclePropertyAccess::READ_WRITE,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp
index d744a06..ea38cb3 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp
@@ -30,6 +30,8 @@
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 @@
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 @@
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,33 +71,45 @@
}
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) {
ALOGE("set(INITIAL_USER_INFO): no int32values, ignoring it: %s", toString(value).c_str());
@@ -147,6 +168,20 @@
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 @@
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 @@
}
// 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 @@
} 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());
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.h
index 3168d75..db2f117 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.h
@@ -58,7 +58,8 @@
*
* @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 @@
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;
};
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
index 9cfcc1c..a0b566d 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
@@ -153,7 +153,7 @@
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());
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp
index 31ba8ab..c5b9ed6 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp
@@ -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",
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 341aae7..f7a42e9 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -2532,23 +2532,23 @@
*
* 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 @@
* 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 @@
* 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 @@
* 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 @@
* 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 @@
* 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 @@
/** 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;
};
@@ -4371,15 +4391,15 @@
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;
};
/**
diff --git a/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp b/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
index 7ac44a4..78f93af 100644
--- a/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
+++ b/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
@@ -28,6 +28,7 @@
#include <chrono>
#include <cstdint>
#include <random>
+#include <thread>
using android::sp;
using android::hardware::hidl_vec;
@@ -144,7 +145,10 @@
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;
diff --git a/biometrics/fingerprint/2.1/vts/functional/VtsHalBiometricsFingerprintV2_1TargetTest.cpp b/biometrics/fingerprint/2.1/vts/functional/VtsHalBiometricsFingerprintV2_1TargetTest.cpp
index bdbf72d..6093caa 100644
--- a/biometrics/fingerprint/2.1/vts/functional/VtsHalBiometricsFingerprintV2_1TargetTest.cpp
+++ b/biometrics/fingerprint/2.1/vts/functional/VtsHalBiometricsFingerprintV2_1TargetTest.cpp
@@ -49,7 +49,7 @@
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
diff --git a/bluetooth/1.0/vts/functional/Android.bp b/bluetooth/1.0/vts/functional/Android.bp
index 463ed84..e9f867f 100644
--- a/bluetooth/1.0/vts/functional/Android.bp
+++ b/bluetooth/1.0/vts/functional/Android.bp
@@ -26,4 +26,5 @@
"general-tests",
"vts",
],
+ disable_framework: true,
}
diff --git a/camera/device/3.2/ICameraDeviceCallback.hal b/camera/device/3.2/ICameraDeviceCallback.hal
index dec3bd8..206a649 100644
--- a/camera/device/3.2/ICameraDeviceCallback.hal
+++ b/camera/device/3.2/ICameraDeviceCallback.hal
@@ -87,15 +87,19 @@
* 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:
*
diff --git a/camera/device/3.2/default/convert.cpp b/camera/device/3.2/default/convert.cpp
index d878deb..06ad7e9 100644
--- a/camera/device/3.2/default/convert.cpp
+++ b/camera/device/3.2/default/convert.cpp
@@ -38,7 +38,7 @@
}
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;
diff --git a/camera/provider/2.4/vts/functional/AndroidTest.xml b/camera/provider/2.4/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..3000c0e
--- /dev/null
+++ b/camera/provider/2.4/vts/functional/AndroidTest.xml
@@ -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>
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index f6860cf..f235235 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -843,7 +843,7 @@
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 @@
}
// 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 @@
}
}
-// 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 @@
// 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 @@
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;
diff --git a/camera/provider/2.6/ICameraProvider.hal b/camera/provider/2.6/ICameraProvider.hal
index ed1d31d..d720b26 100644
--- a/camera/provider/2.6/ICameraProvider.hal
+++ b/camera/provider/2.6/ICameraProvider.hal
@@ -61,6 +61,12 @@
* 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 @@
* 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
diff --git a/current.txt b/current.txt
index e2d1408..6696516 100644
--- a/current.txt
+++ b/current.txt
@@ -588,6 +588,7 @@
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 @@
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 @@
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 @@
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
diff --git a/gnss/1.1/vts/functional/Android.bp b/gnss/1.1/vts/functional/Android.bp
index 0d540b7..94bfb89 100644
--- a/gnss/1.1/vts/functional/Android.bp
+++ b/gnss/1.1/vts/functional/Android.bp
@@ -25,6 +25,7 @@
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: [
diff --git a/gnss/2.0/vts/functional/gnss_hal_test.cpp b/gnss/2.0/vts/functional/gnss_hal_test.cpp
index 59e18f3..1cb44c5 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test.cpp
+++ b/gnss/2.0/vts/functional/gnss_hal_test.cpp
@@ -247,3 +247,46 @@
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;
+}
diff --git a/gnss/2.0/vts/functional/gnss_hal_test.h b/gnss/2.0/vts/functional/gnss_hal_test.h
index a02a9ff..7fbd735 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test.h
+++ b/gnss/2.0/vts/functional/gnss_hal_test.h
@@ -31,6 +31,9 @@
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 @@
*/
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
};
diff --git a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
index 094c7c1..51dcf0d 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
@@ -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;
@@ -492,31 +490,6 @@
}
/*
- * 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:
*
* Search through a GnssSvStatus list for the strongest non-GPS satellite observed enough times
@@ -555,7 +528,7 @@
(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 @@
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 @@
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 @@
}
/*
- * 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 @@
* 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 @@
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 @@
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 @@
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));
}
diff --git a/gnss/common/utils/vts/Android.bp b/gnss/common/utils/vts/Android.bp
index fd9613b..4c6d443 100644
--- a/gnss/common/utils/vts/Android.bp
+++ b/gnss/common/utils/vts/Android.bp
@@ -29,6 +29,7 @@
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",
],
diff --git a/gnss/common/utils/vts/Utils.cpp b/gnss/common/utils/vts/Utils.cpp
index 4b5a50f..9bf68e6 100644
--- a/gnss/common/utils/vts/Utils.cpp
+++ b/gnss/common/utils/vts/Utils.cpp
@@ -169,6 +169,31 @@
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
diff --git a/gnss/common/utils/vts/include/Utils.h b/gnss/common/utils/vts/include/Utils.h
index c3cdd18..9c838b2 100644
--- a/gnss/common/utils/vts/include/Utils.h
+++ b/gnss/common/utils/vts/include/Utils.h
@@ -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 @@
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
diff --git a/graphics/common/aidl/android/hardware/graphics/common/PlaneLayout.aidl b/graphics/common/aidl/android/hardware/graphics/common/PlaneLayout.aidl
index ccb0690..b329cb2 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/PlaneLayout.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/PlaneLayout.aidl
@@ -100,10 +100,11 @@
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;
diff --git a/graphics/composer/2.1/vts/functional/Android.bp b/graphics/composer/2.1/vts/functional/Android.bp
index dafbbf9..e137afb 100644
--- a/graphics/composer/2.1/vts/functional/Android.bp
+++ b/graphics/composer/2.1/vts/functional/Android.bp
@@ -23,6 +23,10 @@
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 @@
"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: [
diff --git a/graphics/composer/2.2/vts/functional/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp
index e1a254d..d80845f 100644
--- a/graphics/composer/2.2/vts/functional/Android.bp
+++ b/graphics/composer/2.2/vts/functional/Android.bp
@@ -33,6 +33,10 @@
"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 @@
"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",
diff --git a/graphics/composer/2.3/vts/functional/Android.bp b/graphics/composer/2.3/vts/functional/Android.bp
index 18ea2aa..1ab6b3b 100644
--- a/graphics/composer/2.3/vts/functional/Android.bp
+++ b/graphics/composer/2.3/vts/functional/Android.bp
@@ -24,6 +24,10 @@
"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 @@
"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: [
diff --git a/graphics/composer/2.4/vts/functional/Android.bp b/graphics/composer/2.4/vts/functional/Android.bp
index 9e7cc46..d0209b7 100644
--- a/graphics/composer/2.4/vts/functional/Android.bp
+++ b/graphics/composer/2.4/vts/functional/Android.bp
@@ -23,6 +23,10 @@
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 @@
"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: [
diff --git a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
index 27b633a..6b0d106 100644
--- a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
+++ b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
@@ -414,12 +414,9 @@
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 @@
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 @@
// 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);
}
diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
index 529fb18..bb775dc 100644
--- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
+++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
@@ -587,8 +587,8 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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
*/
@@ -1707,6 +1844,84 @@
}
/**
+ * 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
*/
TEST_P(GraphicsMapperHidlTest, SetConstantMetadata) {
diff --git a/identity/aidl/android/hardware/identity/IIdentityCredential.aidl b/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
index d7f47e8..730b601 100644
--- a/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
+++ b/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
@@ -151,8 +151,8 @@
* 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 @@
* 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 @@
*
* 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 @@
*
* @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 @@
*
* 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 @@
*
* - 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.
*/
diff --git a/identity/aidl/android/hardware/identity/IIdentityCredentialStore.aidl b/identity/aidl/android/hardware/identity/IIdentityCredentialStore.aidl
index bd664e8..33e25b1 100644
--- a/identity/aidl/android/hardware/identity/IIdentityCredentialStore.aidl
+++ b/identity/aidl/android/hardware/identity/IIdentityCredentialStore.aidl
@@ -99,7 +99,7 @@
* 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
diff --git a/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl b/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
index b7ad283..297fd1d 100644
--- a/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
+++ b/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
@@ -29,9 +29,27 @@
* 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 @@
* 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 @@
* 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
diff --git a/identity/aidl/default/IdentityCredential.cpp b/identity/aidl/default/IdentityCredential.cpp
index 8a00d22..10f9aa5 100644
--- a/identity/aidl/default/IdentityCredential.cpp
+++ b/identity/aidl/default/IdentityCredential.cpp
@@ -39,6 +39,10 @@
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 @@
}
*outChallenge = challenge;
+ authChallenge_ = challenge;
return ndk::ScopedAStatus::ok();
}
@@ -223,7 +228,8 @@
}
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 @@
}
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 @@
//
// 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 @@
"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 @@
}
// 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 @@
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 @@
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"));
diff --git a/identity/aidl/default/WritableIdentityCredential.cpp b/identity/aidl/default/WritableIdentityCredential.cpp
index 7732c33..c218866 100644
--- a/identity/aidl/default/WritableIdentityCredential.cpp
+++ b/identity/aidl/default/WritableIdentityCredential.cpp
@@ -65,6 +65,10 @@
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 @@
"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;
diff --git a/identity/aidl/vts/Android.bp b/identity/aidl/vts/Android.bp
index 5b075c6..c1f44e7 100644
--- a/identity/aidl/vts/Android.bp
+++ b/identity/aidl/vts/Android.bp
@@ -10,20 +10,23 @@
"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",
diff --git a/identity/aidl/vts/ReaderAuthTests.cpp b/identity/aidl/vts/ReaderAuthTests.cpp
new file mode 100644
index 0000000..b11f6c5
--- /dev/null
+++ b/identity/aidl/vts/ReaderAuthTests.cpp
@@ -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
diff --git a/identity/aidl/vts/UserAuthTests.cpp b/identity/aidl/vts/UserAuthTests.cpp
new file mode 100644
index 0000000..5b4c8f1
--- /dev/null
+++ b/identity/aidl/vts/UserAuthTests.cpp
@@ -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
diff --git a/identity/aidl/vts/VtsAttestationTests.cpp b/identity/aidl/vts/VtsAttestationTests.cpp
index 00b5893..c7cdfc7 100644
--- a/identity/aidl/vts/VtsAttestationTests.cpp
+++ b/identity/aidl/vts/VtsAttestationTests.cpp
@@ -61,51 +61,6 @@
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;
diff --git a/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp b/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp
index 464ab0c..e347654 100644
--- a/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp
+++ b/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp
@@ -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 @@
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 @@
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 @@
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 @@
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 @@
" },\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 @@
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 @@
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 @@
" },\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 @@
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);
}
diff --git a/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp b/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
index 8b0c050..b572b0f 100644
--- a/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
+++ b/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
@@ -69,11 +69,10 @@
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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
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 @@
;
// 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 @@
// 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 @@
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;
diff --git a/identity/aidl/vts/VtsIdentityTestUtils.cpp b/identity/aidl/vts/VtsIdentityTestUtils.cpp
index aaebcbe..b6ed80f 100644
--- a/identity/aidl/vts/VtsIdentityTestUtils.cpp
+++ b/identity/aidl/vts/VtsIdentityTestUtils.cpp
@@ -96,9 +96,10 @@
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.
diff --git a/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h b/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h
index 507e914..f7ec7c5 100644
--- a/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h
+++ b/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h
@@ -33,6 +33,7 @@
using ::std::string;
using ::std::tuple;
using ::std::vector;
+using ::std::pair;
// ---------------------------------------------------------------------------
// Miscellaneous utilities.
@@ -119,6 +120,12 @@
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>> 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>> 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 @@
//
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 @@
//
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 @@
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 @@
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>> 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.
// ---------------------------------------------------------------------------
diff --git a/identity/support/src/IdentityCredentialSupport.cpp b/identity/support/src/IdentityCredentialSupport.cpp
index dc49ddc..8e099e7 100644
--- a/identity/support/src/IdentityCredentialSupport.cpp
+++ b/identity/support/src/IdentityCredentialSupport.cpp
@@ -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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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.
// ---------------------------------------------------------------------------
diff --git a/keymaster/4.0/support/keymaster_utils.cpp b/keymaster/4.0/support/keymaster_utils.cpp
index 366cd0e..bcfa757 100644
--- a/keymaster/4.0/support/keymaster_utils.cpp
+++ b/keymaster/4.0/support/keymaster_utils.cpp
@@ -121,8 +121,8 @@
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 @@
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;
}
diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
index 6cbe4da..aa2de2a 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -438,10 +438,10 @@
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);
diff --git a/media/omx/1.0/vts/functional/common/Android.bp b/media/omx/1.0/vts/functional/common/Android.bp
index 2c024a0..720ea9f 100644
--- a/media/omx/1.0/vts/functional/common/Android.bp
+++ b/media/omx/1.0/vts/functional/common/Android.bp
@@ -74,5 +74,6 @@
// TODO(b/64437680): Assume these libs are always available on the device.
shared_libs: [
"libstagefright_foundation",
+ "libstagefright_omx_utils",
],
}
diff --git a/media/omx/1.0/vts/functional/master/VtsHalMediaOmxV1_0TargetMasterTest.cpp b/media/omx/1.0/vts/functional/master/VtsHalMediaOmxV1_0TargetMasterTest.cpp
index 9b4722e..68ee900 100644
--- a/media/omx/1.0/vts/functional/master/VtsHalMediaOmxV1_0TargetMasterTest.cpp
+++ b/media/omx/1.0/vts/functional/master/VtsHalMediaOmxV1_0TargetMasterTest.cpp
@@ -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 @@
}
}
-/*
- * 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 @@
};
// 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 @@
// 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 << ".";
diff --git a/neuralnetworks/1.0/vts/functional/Android.bp b/neuralnetworks/1.0/vts/functional/Android.bp
index 87e8519..d802911 100644
--- a/neuralnetworks/1.0/vts/functional/Android.bp
+++ b/neuralnetworks/1.0/vts/functional/Android.bp
@@ -62,11 +62,12 @@
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",
diff --git a/neuralnetworks/1.0/vts/functional/AndroidTest.xml b/neuralnetworks/1.0/vts/functional/AndroidTest.xml
index 54e6e91..13671f9 100644
--- a/neuralnetworks/1.0/vts/functional/AndroidTest.xml
+++ b/neuralnetworks/1.0/vts/functional/AndroidTest.xml
@@ -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>
diff --git a/neuralnetworks/1.0/vts/functional/TestMain.cpp b/neuralnetworks/1.0/vts/functional/TestMain.cpp
new file mode 100644
index 0000000..6bf4e5f
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/TestMain.cpp
@@ -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();
+}
diff --git a/neuralnetworks/1.0/vts/functional/include/1.0/LogTestCaseToLogcat.h b/neuralnetworks/1.0/vts/functional/include/1.0/LogTestCaseToLogcat.h
new file mode 100644
index 0000000..f1413ef
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/include/1.0/LogTestCaseToLogcat.h
@@ -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
diff --git a/neuralnetworks/1.1/vts/functional/Android.bp b/neuralnetworks/1.1/vts/functional/Android.bp
index 9afa0af..405548f 100644
--- a/neuralnetworks/1.1/vts/functional/Android.bp
+++ b/neuralnetworks/1.1/vts/functional/Android.bp
@@ -20,6 +20,7 @@
srcs: [
"BasicTests.cpp",
"TestAssertions.cpp",
+ "TestMain.cpp",
"ValidateModel.cpp",
"ValidateRequest.cpp",
"VtsHalNeuralnetworks.cpp",
diff --git a/neuralnetworks/1.1/vts/functional/AndroidTest.xml b/neuralnetworks/1.1/vts/functional/AndroidTest.xml
index a6f812f..cfde60c 100644
--- a/neuralnetworks/1.1/vts/functional/AndroidTest.xml
+++ b/neuralnetworks/1.1/vts/functional/AndroidTest.xml
@@ -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>
diff --git a/neuralnetworks/1.1/vts/functional/TestMain.cpp b/neuralnetworks/1.1/vts/functional/TestMain.cpp
new file mode 100644
index 0000000..6bf4e5f
--- /dev/null
+++ b/neuralnetworks/1.1/vts/functional/TestMain.cpp
@@ -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();
+}
diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp
index 182f716..93edca6 100644
--- a/neuralnetworks/1.2/vts/functional/Android.bp
+++ b/neuralnetworks/1.2/vts/functional/Android.bp
@@ -40,6 +40,7 @@
"CompilationCachingTests.cpp",
"GeneratedTestHarness.cpp",
"TestAssertions.cpp",
+ "TestMain.cpp",
"ValidateBurst.cpp",
"ValidateModel.cpp",
"ValidateRequest.cpp",
diff --git a/neuralnetworks/1.2/vts/functional/AndroidTest.xml b/neuralnetworks/1.2/vts/functional/AndroidTest.xml
index adbdf40..3f91618 100644
--- a/neuralnetworks/1.2/vts/functional/AndroidTest.xml
+++ b/neuralnetworks/1.2/vts/functional/AndroidTest.xml
@@ -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>
diff --git a/neuralnetworks/1.2/vts/functional/TestMain.cpp b/neuralnetworks/1.2/vts/functional/TestMain.cpp
new file mode 100644
index 0000000..6bf4e5f
--- /dev/null
+++ b/neuralnetworks/1.2/vts/functional/TestMain.cpp
@@ -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();
+}
diff --git a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h
index d01336e..c4e2b15 100644
--- a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h
+++ b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h
@@ -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"
diff --git a/neuralnetworks/1.3/types.hal b/neuralnetworks/1.3/types.hal
index 39ea4c2..3b2b14c 100644
--- a/neuralnetworks/1.3/types.hal
+++ b/neuralnetworks/1.3/types.hal
@@ -5102,11 +5102,15 @@
* 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 @@
* 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 @@
* 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 @@
* . 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
diff --git a/neuralnetworks/1.3/types.t b/neuralnetworks/1.3/types.t
index 0a6e45e..7220e37 100644
--- a/neuralnetworks/1.3/types.t
+++ b/neuralnetworks/1.3/types.t
@@ -264,7 +264,9 @@
* 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 @@
* . 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
diff --git a/neuralnetworks/1.3/vts/functional/Android.bp b/neuralnetworks/1.3/vts/functional/Android.bp
index 771fc54..b17d445 100644
--- a/neuralnetworks/1.3/vts/functional/Android.bp
+++ b/neuralnetworks/1.3/vts/functional/Android.bp
@@ -43,6 +43,7 @@
"MemoryDomainTests.cpp",
"QualityOfServiceTests.cpp",
"TestAssertions.cpp",
+ "TestMain.cpp",
"ValidateBurst.cpp",
"ValidateModel.cpp",
"ValidateRequest.cpp",
diff --git a/neuralnetworks/1.3/vts/functional/AndroidTest.xml b/neuralnetworks/1.3/vts/functional/AndroidTest.xml
index 30cff2e..e5acd90 100644
--- a/neuralnetworks/1.3/vts/functional/AndroidTest.xml
+++ b/neuralnetworks/1.3/vts/functional/AndroidTest.xml
@@ -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>
diff --git a/neuralnetworks/1.3/vts/functional/TestMain.cpp b/neuralnetworks/1.3/vts/functional/TestMain.cpp
new file mode 100644
index 0000000..6bf4e5f
--- /dev/null
+++ b/neuralnetworks/1.3/vts/functional/TestMain.cpp
@@ -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();
+}
diff --git a/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.h
index de082c3..a2e5071 100644
--- a/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.h
+++ b/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.h
@@ -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"
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_cell_broadcast.cpp b/radio/1.0/vts/functional/radio_hidl_hal_cell_broadcast.cpp
index 125ea0c..8e6cf86 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_cell_broadcast.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_cell_broadcast.cpp
@@ -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 @@
* Test IRadio.setGsmBroadcastConfig() for the response returned.
*/
TEST_P(RadioHidlTest, setGsmBroadcastConfig) {
+ LOG(DEBUG) << "setGsmBroadcastConfig";
serial = GetRandomSerialNumber();
// Create GsmBroadcastSmsConfigInfo #1
@@ -79,12 +81,14 @@
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 @@
{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 @@
{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 @@
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 @@
{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 @@
RadioError::INVALID_STATE, RadioError::OPERATION_NOT_ALLOWED},
CHECK_GENERAL_ERROR));
}
+ LOG(DEBUG) << "setGsmBroadcastActivation finished";
}
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_data.cpp b/radio/1.0/vts/functional/radio_hidl_hal_data.cpp
index d937d74..e3ee9d4 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_data.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_data.cpp
@@ -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 @@
* Test IRadio.getDataRegistrationState() for the response returned.
*/
TEST_P(RadioHidlTest, getDataRegistrationState) {
+ LOG(DEBUG) << "getDataRegistrationState";
serial = GetRandomSerialNumber();
radio->getDataRegistrationState(serial);
@@ -94,12 +96,14 @@
}
}
}
+ 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
{RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
RadioError::SIM_ABSENT, RadioError::REQUEST_NOT_SUPPORTED}));
}
+ LOG(DEBUG) << "setDataProfile finished";
}
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_icc.cpp b/radio/1.0/vts/functional/radio_hidl_hal_icc.cpp
index 9568524..8a977a9 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_icc.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_icc.cpp
@@ -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 @@
{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 @@
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 @@
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 @@
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 @@
{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 @@
RadioError::SIM_PUK2}));
}
}
+ LOG(DEBUG) << "changeIccPin2ForApp finished";
}
/*
@@ -182,6 +197,7 @@
* 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 @@
}
}
}
+ 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
RadioError::INVALID_SIM_STATE, RadioError::MODEM_ERR, RadioError::NO_MEMORY,
RadioError::PASSWORD_INCORRECT, RadioError::SIM_ABSENT, RadioError::SYSTEM_ERR}));
}
+ LOG(DEBUG) << "supplyNetworkDepersonalization finished";
}
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp b/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp
index 7228fb0..3f96473 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp
@@ -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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
{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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
{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 @@
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 @@
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 @@
{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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
{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 @@
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 @@
{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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
ASSERT_TRUE(
CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
}
+ LOG(DEBUG) << "getHardwareConfig finished";
}
/*
@@ -651,6 +722,7 @@
* Test IRadio.getRadioCapability() for the response returned.
*/
TEST_P(RadioHidlTest, getRadioCapability) {
+ LOG(DEBUG) << "getRadioCapability";
serial = GetRandomSerialNumber();
radio->getRadioCapability(serial);
@@ -661,12 +733,14 @@
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 @@
{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 @@
{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 @@
{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 @@
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 @@
ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
{RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
}
+ LOG(DEBUG) << "getModemActivityInfo finished";
}
/*
@@ -840,6 +923,7 @@
* Test IRadio.getAllowedCarriers() for the response returned.
*/
TEST_P(RadioHidlTest, getAllowedCarriers) {
+ LOG(DEBUG) << "getAllowedCarriers";
serial = GetRandomSerialNumber();
radio->getAllowedCarriers(serial);
@@ -851,12 +935,14 @@
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 @@
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 @@
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 @@
ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
{RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
}
+ LOG(DEBUG) << "setSimCardPower finished";
}
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_sms.cpp b/radio/1.0/vts/functional/radio_hidl_hal_sms.cpp
index 58c3bbd..0807dee 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_sms.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_sms.cpp
@@ -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 @@
* Test IRadio.sendSms() for the response returned.
*/
TEST_P(RadioHidlTest, sendSms) {
+ LOG(DEBUG) << "sendSms";
serial = GetRandomSerialNumber();
GsmSmsMessage msg;
msg.smscPdu = "";
@@ -40,12 +42,14 @@
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 @@
{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 @@
{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 @@
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 @@
{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 @@
{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 @@
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 @@
{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 @@
{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 @@
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 @@
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 @@
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 @@
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 @@
RadioError::MODEM_ERR, RadioError::SIM_ABSENT},
CHECK_GENERAL_ERROR));
}
+ LOG(DEBUG) << "reportSmsMemoryStatus finished";
}
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_stk.cpp b/radio/1.0/vts/functional/radio_hidl_hal_stk.cpp
index 1170111..193c25d 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_stk.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_stk.cpp
@@ -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 @@
* 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 @@
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 @@
{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 @@
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 @@
ASSERT_TRUE(
CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
}
+ LOG(DEBUG) << "reportStkServiceIsRunning finished";
}
/*
@@ -108,6 +117,7 @@
* string.
*/
TEST_P(RadioHidlTest, sendEnvelopeWithStatus) {
+ LOG(DEBUG) << "sendEnvelopeWithStatus";
serial = GetRandomSerialNumber();
// Test with sending empty string
@@ -125,4 +135,5 @@
{RadioError::INVALID_ARGUMENTS, RadioError::MODEM_ERR, RadioError::SIM_ABSENT},
CHECK_GENERAL_ERROR));
}
+ LOG(DEBUG) << "sendEnvelopeWithStatus finished";
}
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_test.cpp b/radio/1.0/vts/functional/radio_hidl_hal_test.cpp
index 3c833c0..3583514 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_test.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_test.cpp
@@ -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 @@
serial = GetRandomSerialNumber();
radio->getIccCardStatus(serial);
EXPECT_EQ(std::cv_status::no_timeout, wait());
-}
\ No newline at end of file
+}
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp b/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp
index a192a33..f6de2f8 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp
@@ -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 @@
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 @@
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 @@
{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 @@
{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 @@
{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 @@
{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 @@
{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 @@
{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 @@
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 @@
{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 @@
{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 @@
{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 @@
{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 @@
{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 @@
{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 @@
{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 @@
{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 @@
{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 @@
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 @@
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 @@
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 @@
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 @@
{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 @@
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 @@
RadioError::MODEM_ERR, RadioError::OPERATION_NOT_ALLOWED},
CHECK_GENERAL_ERROR));
}
+ LOG(DEBUG) << "sendBurstDtmf finished";
}
diff --git a/radio/1.0/vts/functional/sap_hidl_hal_api.cpp b/radio/1.0/vts/functional/sap_hidl_hal_api.cpp
index 6bd2c88..6c7870d 100644
--- a/radio/1.0/vts/functional/sap_hidl_hal_api.cpp
+++ b/radio/1.0/vts/functional/sap_hidl_hal_api.cpp
@@ -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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
EXPECT_EQ(sapCb->sapResponseToken, token);
EXPECT_EQ(SapResultCode::NOT_SUPPORTED, sapCb->sapResultCode);
+ LOG(DEBUG) << "setTransferProtocolReq finished";
}
diff --git a/radio/1.0/vts/functional/vts_hal_radio_target_test.xml b/radio/1.0/vts/functional/vts_hal_radio_target_test.xml
index b91119d..82af2ee 100644
--- a/radio/1.0/vts/functional/vts_hal_radio_target_test.xml
+++ b/radio/1.0/vts/functional/vts_hal_radio_target_test.xml
@@ -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>
diff --git a/radio/1.0/vts/functional/vts_hal_sap_target_test.xml b/radio/1.0/vts/functional/vts_hal_sap_target_test.xml
index 876e1fb..d7d4477 100644
--- a/radio/1.0/vts/functional/vts_hal_sap_target_test.xml
+++ b/radio/1.0/vts/functional/vts_hal_sap_target_test.xml
@@ -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" />
diff --git a/radio/1.1/vts/functional/AndroidTest.xml b/radio/1.1/vts/functional/AndroidTest.xml
index 3699575..f1bc7a8 100644
--- a/radio/1.1/vts/functional/AndroidTest.xml
+++ b/radio/1.1/vts/functional/AndroidTest.xml
@@ -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>
diff --git a/radio/1.1/vts/functional/radio_hidl_hal_api.cpp b/radio/1.1/vts/functional/radio_hidl_hal_api.cpp
index 02dcbab..08121fd 100644
--- a/radio/1.1/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.1/vts/functional/radio_hidl_hal_api.cpp
@@ -49,7 +49,6 @@
}
EXPECT_EQ(CardState::ABSENT, cardStatus.cardState);
}
-#endif
/* Test setSimCardPower power up */
serial = GetRandomSerialNumber();
@@ -60,6 +59,7 @@
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,
diff --git a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
index c81a8d9..acb1b0e 100644
--- a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
@@ -735,7 +735,7 @@
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,
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
index e4c0877..3ba9b9d 100644
--- a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
@@ -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, 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 @@
{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_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_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_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_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_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_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_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 @@
{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_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 @@
{RadioError::NONE, RadioError::INVALID_ARGUMENTS,
RadioError::REQUEST_NOT_SUPPORTED}));
}
+
+ if (radioRsp_v1_4->rspInfo.error == RadioError::NONE) {
+ ALOGI("Stop Network Scan");
+ stopNetworkScan();
+ }
}
/*
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_test.cpp b/radio/1.4/vts/functional/radio_hidl_hal_test.cpp
index 15a0b24..4ac6cc9 100644
--- a/radio/1.4/vts/functional/radio_hidl_hal_test.cpp
+++ b/radio/1.4/vts/functional/radio_hidl_hal_test.cpp
@@ -107,3 +107,9 @@
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());
+}
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h b/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h
index 31b7e13..53a5845 100644
--- a/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h
+++ b/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h
@@ -721,7 +721,10 @@
/* 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 */
diff --git a/radio/1.5/vts/functional/radio_hidl_hal_api.cpp b/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
index 32c02cb..24b7fd5 100644
--- a/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
@@ -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 @@
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, 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 @@
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, 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 @@
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_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_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_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_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_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_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_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 @@
{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_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 @@
{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 @@
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;
diff --git a/radio/1.5/vts/functional/radio_hidl_hal_test.cpp b/radio/1.5/vts/functional/radio_hidl_hal_test.cpp
index 7313de4..4155550 100644
--- a/radio/1.5/vts/functional/radio_hidl_hal_test.cpp
+++ b/radio/1.5/vts/functional/radio_hidl_hal_test.cpp
@@ -78,3 +78,9 @@
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());
+}
diff --git a/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h b/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h
index 6a369cc..87ce675 100644
--- a/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h
+++ b/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h
@@ -831,6 +831,9 @@
/* Update Sim Card Status */
void updateSimCardStatus();
+ /* Stop Network Scan Command */
+ void stopNetworkScan();
+
public:
virtual void SetUp() override;
diff --git a/radio/1.5/vts/functional/radio_response.cpp b/radio/1.5/vts/functional/radio_response.cpp
index 8cbb2d0..9b6d450 100644
--- a/radio/1.5/vts/functional/radio_response.cpp
+++ b/radio/1.5/vts/functional/radio_response.cpp
@@ -1017,8 +1017,10 @@
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();
}
diff --git a/rebootescrow/aidl/vts/functional/README.md b/rebootescrow/aidl/vts/functional/README.md
new file mode 100644
index 0000000..9ae5caf
--- /dev/null
+++ b/rebootescrow/aidl/vts/functional/README.md
@@ -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.
diff --git a/rebootescrow/aidl/vts/functional/VtsHalRebootEscrowTargetTest.cpp b/rebootescrow/aidl/vts/functional/VtsHalRebootEscrowTargetTest.cpp
index cd8cc3e..809a3b5 100644
--- a/rebootescrow/aidl/vts/functional/VtsHalRebootEscrowTargetTest.cpp
+++ b/rebootescrow/aidl/vts/functional/VtsHalRebootEscrowTargetTest.cpp
@@ -60,7 +60,10 @@
};
};
-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 @@
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 @@
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 @@
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 @@
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)),
diff --git a/renderscript/1.0/Android.bp b/renderscript/1.0/Android.bp
index feae9f7..d3b5abe 100644
--- a/renderscript/1.0/Android.bp
+++ b/renderscript/1.0/Android.bp
@@ -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,
diff --git a/sensors/1.0/vts/functional/Android.bp b/sensors/1.0/vts/functional/Android.bp
index 31424ab..c77733b 100644
--- a/sensors/1.0/vts/functional/Android.bp
+++ b/sensors/1.0/vts/functional/Android.bp
@@ -23,11 +23,6 @@
"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",
],
diff --git a/sensors/2.0/vts/functional/Android.bp b/sensors/2.0/vts/functional/Android.bp
index 598ad15..83ebc6b 100644
--- a/sensors/2.0/vts/functional/Android.bp
+++ b/sensors/2.0/vts/functional/Android.bp
@@ -25,11 +25,6 @@
"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",
diff --git a/sensors/2.1/vts/functional/Android.bp b/sensors/2.1/vts/functional/Android.bp
index 3f01a3e..d257993 100644
--- a/sensors/2.1/vts/functional/Android.bp
+++ b/sensors/2.1/vts/functional/Android.bp
@@ -27,11 +27,6 @@
"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",
diff --git a/sensors/common/vts/2_X/Android.bp b/sensors/common/vts/2_X/Android.bp
index 8cdb5d1..e5eceb5 100644
--- a/sensors/common/vts/2_X/Android.bp
+++ b/sensors/common/vts/2_X/Android.bp
@@ -29,11 +29,6 @@
"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",
diff --git a/sensors/common/vts/utils/Android.bp b/sensors/common/vts/utils/Android.bp
index ca4346a..baaed6c 100644
--- a/sensors/common/vts/utils/Android.bp
+++ b/sensors/common/vts/utils/Android.bp
@@ -31,13 +31,17 @@
"libutils",
],
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@2.0",
"android.hardware.sensors@2.1",
],
+ whole_static_libs: [
+ "android.hardware.graphics.allocator@2.0",
+ "android.hardware.graphics.allocator@3.0",
+ "android.hardware.graphics.allocator@4.0",
+ "android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@2.1",
+ "android.hardware.graphics.mapper@3.0",
+ "android.hardware.graphics.mapper@4.0",
+ ],
}
diff --git a/sensors/common/vts/utils/GrallocWrapper.cpp b/sensors/common/vts/utils/GrallocWrapper.cpp
index e63faa2..47d1f42 100644
--- a/sensors/common/vts/utils/GrallocWrapper.cpp
+++ b/sensors/common/vts/utils/GrallocWrapper.cpp
@@ -18,9 +18,11 @@
#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
#include <android/hardware/graphics/allocator/3.0/IAllocator.h>
+#include <android/hardware/graphics/allocator/4.0/IAllocator.h>
#include <android/hardware/graphics/mapper/2.0/IMapper.h>
#include <android/hardware/graphics/mapper/2.1/IMapper.h>
#include <android/hardware/graphics/mapper/3.0/IMapper.h>
+#include <android/hardware/graphics/mapper/4.0/IMapper.h>
#include <utils/Log.h>
@@ -29,19 +31,19 @@
using IAllocator2 = ::android::hardware::graphics::allocator::V2_0::IAllocator;
using IAllocator3 = ::android::hardware::graphics::allocator::V3_0::IAllocator;
+using IAllocator4 = ::android::hardware::graphics::allocator::V4_0::IAllocator;
using IMapper2 = ::android::hardware::graphics::mapper::V2_0::IMapper;
using IMapper2_1 = ::android::hardware::graphics::mapper::V2_1::IMapper;
using IMapper3 = ::android::hardware::graphics::mapper::V3_0::IMapper;
+using IMapper4 = ::android::hardware::graphics::mapper::V4_0::IMapper;
using Error2 = ::android::hardware::graphics::mapper::V2_0::Error;
using Error3 = ::android::hardware::graphics::mapper::V3_0::Error;
+using Error4 = ::android::hardware::graphics::mapper::V4_0::Error;
using ::android::hardware::graphics::common::V1_0::BufferUsage;
using ::android::hardware::graphics::common::V1_0::PixelFormat;
-// This is a typedef to the same underlying type across v2.0 and v3.0
-using ::android::hardware::graphics::mapper::V2_0::BufferDescriptor;
-
using ::android::hardware::hidl_handle;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
@@ -58,7 +60,6 @@
virtual ~IGrallocHalWrapper() = default;
// IAllocator
- virtual std::string dumpDebugInfo() = 0;
virtual native_handle_t* allocate(uint32_t size) = 0;
virtual void freeBuffer(native_handle_t* bufferHandle) = 0;
@@ -75,6 +76,24 @@
bool failed(Error3 error) {
return (error != Error3::NONE);
}
+bool failed(Error4 error) {
+ return (error != Error4::NONE);
+}
+
+template <typename>
+struct FirstArg;
+
+// Template specialization for pointer to a non-static member function, which exposes
+// the type of the first argument given to said function
+template <typename ReturnType, typename ClassT, typename Arg1, typename... OtherArgs>
+struct FirstArg<ReturnType (ClassT::*)(Arg1, OtherArgs...)> {
+ using type = Arg1;
+};
+
+// Alias to FirstArg which also removes any reference type and const associated
+template <typename T>
+using BaseTypeOfFirstArg = typename std::remove_const<
+ typename std::remove_reference<typename FirstArg<T>::type>::type>::type;
// Since all the type and function names are the same for the things we use across the major HAL
// versions, we use template magic to avoid repeating ourselves.
@@ -88,7 +107,6 @@
}
}
- virtual std::string dumpDebugInfo() override;
virtual native_handle_t* allocate(uint32_t size) override;
virtual void freeBuffer(native_handle_t* bufferHandle) override;
@@ -101,21 +119,19 @@
sp<AllocatorT> mAllocator;
sp<MapperT> mMapper;
- BufferDescriptor getDescriptor(uint32_t size);
+ // v2.0 and v3.0 use vec<uint32_t> for BufferDescriptor, but v4.0 uses vec<uint8_t>, so use
+ // some template magic to deduce the right type based off of the first argument to allocate(),
+ // which is always the version-specific BufferDescriptor type
+ typedef BaseTypeOfFirstArg<decltype(&AllocatorT::allocate)> BufferDescriptorT;
+
+ BufferDescriptorT getDescriptor(uint32_t size);
native_handle_t* importBuffer(const hidl_handle& rawHandle);
};
template <typename AllocatorT, typename MapperT>
-std::string GrallocHalWrapper<AllocatorT, MapperT>::dumpDebugInfo() {
- std::string debugInfo;
- mAllocator->dumpDebugInfo([&](const hidl_string& tmpDebugInfo) { debugInfo = tmpDebugInfo; });
- return debugInfo;
-}
-
-template <typename AllocatorT, typename MapperT>
native_handle_t* GrallocHalWrapper<AllocatorT, MapperT>::allocate(uint32_t size) {
constexpr uint32_t kBufferCount = 1;
- BufferDescriptor descriptor = getDescriptor(size);
+ BufferDescriptorT descriptor = getDescriptor(size);
native_handle_t* bufferHandle = nullptr;
auto callback = [&](auto error, uint32_t /*stride*/, const hidl_vec<hidl_handle>& buffers) {
@@ -142,7 +158,8 @@
}
template <typename AllocatorT, typename MapperT>
-BufferDescriptor GrallocHalWrapper<AllocatorT, MapperT>::getDescriptor(uint32_t size) {
+typename GrallocHalWrapper<AllocatorT, MapperT>::BufferDescriptorT
+GrallocHalWrapper<AllocatorT, MapperT>::getDescriptor(uint32_t size) {
typename MapperT::BufferDescriptorInfo descriptorInfo = {
.width = size,
.height = 1,
@@ -151,8 +168,8 @@
.usage = kBufferUsage,
};
- BufferDescriptor descriptor;
- auto callback = [&](auto error, const BufferDescriptor& tmpDescriptor) {
+ BufferDescriptorT descriptor;
+ auto callback = [&](auto error, const BufferDescriptorT& tmpDescriptor) {
if (failed(error)) {
ALOGE("Failed to create descriptor: %" PRId32, static_cast<int32_t>(error));
} else {
@@ -189,7 +206,7 @@
void* data = nullptr;
mMapper->lock(bufferHandle, kBufferUsage, accessRegion, acquireFenceHandle,
- [&](auto error, void* tmpData, ...) { // V3_0 passes extra args we don't use
+ [&](auto error, void* tmpData, ...) { // V3/4 pass extra args we don't use
if (failed(error)) {
ALOGE("Failed to lock buffer %p: %" PRId32, bufferHandle,
static_cast<int32_t>(error));
@@ -214,28 +231,40 @@
} // anonymous namespace
GrallocWrapper::GrallocWrapper() {
- sp<IAllocator3> allocator3 = IAllocator3::getService();
- sp<IMapper3> mapper3 = IMapper3::getService();
+ sp<IAllocator4> allocator4 = IAllocator4::getService();
+ sp<IMapper4> mapper4 = IMapper4::getService();
- if (allocator3 != nullptr && mapper3 != nullptr) {
+ if (allocator4 != nullptr && mapper4 != nullptr) {
+ ALOGD("Using IAllocator/IMapper v4.0");
mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
- new GrallocHalWrapper<IAllocator3, IMapper3>(allocator3, mapper3));
+ new GrallocHalWrapper<IAllocator4, IMapper4>(allocator4, mapper4));
} else {
- ALOGD("Graphics HALs 3.0 not found (allocator %d mapper %d), falling back to 2.x",
- (allocator3 != nullptr), (mapper3 != nullptr));
+ ALOGD("Graphics HALs 4.0 not found (allocator %d mapper %d), falling back to 3.0",
+ (allocator4 != nullptr), (mapper4 != nullptr));
- sp<IAllocator2> allocator2 = IAllocator2::getService();
- sp<IMapper2> mapper2 = IMapper2_1::getService();
- if (mapper2 == nullptr) {
- mapper2 = IMapper2::getService();
- }
+ sp<IAllocator3> allocator3 = IAllocator3::getService();
+ sp<IMapper3> mapper3 = IMapper3::getService();
- if (allocator2 != nullptr && mapper2 != nullptr) {
+ if (allocator3 != nullptr && mapper3 != nullptr) {
mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
- new GrallocHalWrapper<IAllocator2, IMapper2>(allocator2, mapper2));
+ new GrallocHalWrapper<IAllocator3, IMapper3>(allocator3, mapper3));
} else {
- ALOGE("Couldn't open 2.x/3.0 graphics HALs (2.x allocator %d mapper %d)",
- (allocator2 != nullptr), (mapper2 != nullptr));
+ ALOGD("Graphics HALs 3.0 not found (allocator %d mapper %d), falling back to 2.x",
+ (allocator3 != nullptr), (mapper3 != nullptr));
+
+ sp<IAllocator2> allocator2 = IAllocator2::getService();
+ sp<IMapper2> mapper2 = IMapper2_1::getService();
+ if (mapper2 == nullptr) {
+ mapper2 = IMapper2::getService();
+ }
+
+ if (allocator2 != nullptr && mapper2 != nullptr) {
+ mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
+ new GrallocHalWrapper<IAllocator2, IMapper2>(allocator2, mapper2));
+ } else {
+ ALOGE("Couldn't open graphics HALs (2.x allocator %d mapper %d)",
+ (allocator2 != nullptr), (mapper2 != nullptr));
+ }
}
}
}
@@ -248,10 +277,6 @@
mAllocatedBuffers.clear();
}
-std::string GrallocWrapper::dumpDebugInfo() {
- return mGrallocHal->dumpDebugInfo();
-}
-
std::pair<native_handle_t*, void*> GrallocWrapper::allocate(uint32_t size) {
native_handle_t* bufferHandle = mGrallocHal->allocate(size);
void* buffer = nullptr;
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/GrallocWrapper.h b/sensors/common/vts/utils/include/sensors-vts-utils/GrallocWrapper.h
index 41e6334..ebbcb2c 100644
--- a/sensors/common/vts/utils/include/sensors-vts-utils/GrallocWrapper.h
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/GrallocWrapper.h
@@ -37,8 +37,6 @@
// returns false, other methods are not safe to call.
bool isInitialized() const { return (mGrallocHal != nullptr); };
- std::string dumpDebugInfo();
-
// Allocates a gralloc buffer suitable for direct channel sensors usage with the given size.
// The buffer should be freed using freeBuffer when it's not needed anymore; otherwise it'll
// be freed when this object is destroyed.
diff --git a/tv/tuner/1.0/default/Demux.cpp b/tv/tuner/1.0/default/Demux.cpp
index da56041..67eff1b 100644
--- a/tv/tuner/1.0/default/Demux.cpp
+++ b/tv/tuner/1.0/default/Demux.cpp
@@ -48,8 +48,6 @@
return Result::INVALID_STATE;
}
- mFrontendSourceFile = mFrontend->getSourceFile();
-
mTunerService->setFrontendAsDemuxSource(frontendId, mDemuxId);
return Result::SUCCESS;
@@ -62,8 +60,6 @@
uint32_t filterId;
filterId = ++mLastUsedFilterId;
- mUsedFilterIds.insert(filterId);
-
if (cb == nullptr) {
ALOGW("[Demux] callback can't be null");
_hidl_cb(Result::INVALID_ARGUMENT, new Filter());
@@ -82,8 +78,13 @@
mPcrFilterIds.insert(filterId);
}
bool result = true;
- if (mDvr != nullptr && mDvr->getType() == DvrType::PLAYBACK) {
- result = mDvr->addPlaybackFilter(filter);
+ if (!filter->isRecordFilter()) {
+ // Only save non-record filters for now. Record filters are saved when the
+ // IDvr.attacheFilter is called.
+ mPlaybackFilterIds.insert(filterId);
+ if (mDvrPlayback != nullptr) {
+ result = mDvrPlayback->addPlaybackFilter(filterId, filter);
+ }
}
_hidl_cb(result ? Result::SUCCESS : Result::INVALID_ARGUMENT, filter);
@@ -93,9 +94,9 @@
Return<void> Demux::openTimeFilter(openTimeFilter_cb _hidl_cb) {
ALOGV("%s", __FUNCTION__);
- sp<TimeFilter> timeFilter = new TimeFilter(this);
+ mTimeFilter = new TimeFilter(this);
- _hidl_cb(Result::SUCCESS, timeFilter);
+ _hidl_cb(Result::SUCCESS, mTimeFilter);
return Void();
}
@@ -124,12 +125,12 @@
}
if (!mPcrFilterIds.empty()) {
- ALOGE("[Demux] No PCR filter opened.");
// Return the lowest pcr filter id in the default implementation as the av sync id
_hidl_cb(Result::SUCCESS, *mPcrFilterIds.begin());
return Void();
}
+ ALOGE("[Demux] No PCR filter opened.");
_hidl_cb(Result::INVALID_STATE, avSyncHwId);
return Void();
}
@@ -154,7 +155,13 @@
Return<Result> Demux::close() {
ALOGV("%s", __FUNCTION__);
- mUsedFilterIds.clear();
+ set<uint32_t>::iterator it;
+ for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
+ mDvrPlayback->removePlaybackFilter(*it);
+ }
+ mPlaybackFilterIds.clear();
+ mRecordFilterIds.clear();
+ mFilters.clear();
mLastUsedFilterId = -1;
return Result::SUCCESS;
@@ -170,15 +177,38 @@
return Void();
}
- mDvr = new Dvr(type, bufferSize, cb, this);
+ set<uint32_t>::iterator it;
+ switch (type) {
+ case DvrType::PLAYBACK:
+ mDvrPlayback = new Dvr(type, bufferSize, cb, this);
+ if (!mDvrPlayback->createDvrMQ()) {
+ _hidl_cb(Result::UNKNOWN_ERROR, mDvrPlayback);
+ return Void();
+ }
- if (!mDvr->createDvrMQ()) {
- _hidl_cb(Result::UNKNOWN_ERROR, mDvr);
- return Void();
+ for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
+ if (!mDvrPlayback->addPlaybackFilter(*it, mFilters[*it])) {
+ ALOGE("[Demux] Can't get filter info for DVR playback");
+ _hidl_cb(Result::UNKNOWN_ERROR, mDvrPlayback);
+ return Void();
+ }
+ }
+
+ _hidl_cb(Result::SUCCESS, mDvrPlayback);
+ return Void();
+ case DvrType::RECORD:
+ mDvrRecord = new Dvr(type, bufferSize, cb, this);
+ if (!mDvrRecord->createDvrMQ()) {
+ _hidl_cb(Result::UNKNOWN_ERROR, mDvrRecord);
+ return Void();
+ }
+
+ _hidl_cb(Result::SUCCESS, mDvrRecord);
+ return Void();
+ default:
+ _hidl_cb(Result::INVALID_ARGUMENT, nullptr);
+ return Void();
}
-
- _hidl_cb(Result::SUCCESS, mDvr);
- return Void();
}
Return<Result> Demux::connectCiCam(uint32_t ciCamId) {
@@ -198,8 +228,10 @@
Result Demux::removeFilter(uint32_t filterId) {
ALOGV("%s", __FUNCTION__);
- // resetFilterRecords(filterId);
- mUsedFilterIds.erase(filterId);
+ if (mDvrPlayback != nullptr) {
+ mDvrPlayback->removePlaybackFilter(filterId);
+ }
+ mPlaybackFilterIds.erase(filterId);
mRecordFilterIds.erase(filterId);
mFilters.erase(filterId);
@@ -212,7 +244,7 @@
if (DEBUG_DEMUX) {
ALOGW("[Demux] start ts filter pid: %d", pid);
}
- for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
+ for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
if (pid == mFilters[*it]->getTpid()) {
mFilters[*it]->updateFilterOutput(data);
}
@@ -233,7 +265,7 @@
set<uint32_t>::iterator it;
// Handle the output data per filter type
- for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
+ for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
if (mFilters[*it]->startFilterHandler() != Result::SUCCESS) {
return false;
}
@@ -280,58 +312,27 @@
void Demux::frontendInputThreadLoop() {
std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
mFrontendInputThreadRunning = true;
- mKeepFetchingDataFromFrontend = true;
-
- // open the stream and get its length
- std::ifstream inputData(mFrontendSourceFile, std::ifstream::binary);
- // TODO take the packet size from the frontend setting
- int packetSize = 188;
- int writePacketAmount = 6;
- char* buffer = new char[packetSize];
- ALOGW("[Demux] Frontend input thread loop start %s", mFrontendSourceFile.c_str());
- if (!inputData.is_open()) {
- mFrontendInputThreadRunning = false;
- ALOGW("[Demux] Error %s", strerror(errno));
- }
while (mFrontendInputThreadRunning) {
- // move the stream pointer for packet size * 6 every read until the end
- while (mKeepFetchingDataFromFrontend) {
- for (int i = 0; i < writePacketAmount; i++) {
- inputData.read(buffer, packetSize);
- if (!inputData) {
- mKeepFetchingDataFromFrontend = false;
- mFrontendInputThreadRunning = false;
- break;
- }
- // filter and dispatch filter output
- vector<uint8_t> byteBuffer;
- byteBuffer.resize(packetSize);
- for (int index = 0; index < byteBuffer.size(); index++) {
- byteBuffer[index] = static_cast<uint8_t>(buffer[index]);
- }
- if (mIsRecording) {
- // Feed the data into the Dvr recording input
- sendFrontendInputToRecord(byteBuffer);
- } else {
- // Feed the data into the broadcast demux filter
- startBroadcastTsFilter(byteBuffer);
- }
- }
- if (mIsRecording) {
- // Dispatch the data into the broadcasting filters.
- startRecordFilterDispatcher();
- } else {
- // Dispatch the data into the broadcasting filters.
- startBroadcastFilterDispatcher();
- }
- usleep(100);
+ uint32_t efState = 0;
+ status_t status = mDvrPlayback->getDvrEventFlag()->wait(
+ static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT,
+ true /* retry on spurious wake */);
+ if (status != OK) {
+ ALOGD("[Demux] wait for data ready on the playback FMQ");
+ continue;
+ }
+ // Our current implementation filter the data and write it into the filter FMQ immediately
+ // after the DATA_READY from the VTS/framework
+ if (!mDvrPlayback->readPlaybackFMQ(true /*isVirtualFrontend*/, mIsRecording) ||
+ !mDvrPlayback->startFilterDispatcher(true /*isVirtualFrontend*/, mIsRecording)) {
+ ALOGE("[Demux] playback data failed to be filtered. Ending thread");
+ break;
}
}
+ mFrontendInputThreadRunning = false;
ALOGW("[Demux] Frontend Input thread end.");
- delete[] buffer;
- inputData.close();
}
void Demux::stopFrontendInput() {
@@ -346,18 +347,19 @@
}
bool Demux::attachRecordFilter(int filterId) {
- if (mFilters[filterId] == nullptr || mDvr == nullptr) {
+ if (mFilters[filterId] == nullptr || mDvrRecord == nullptr ||
+ !mFilters[filterId]->isRecordFilter()) {
return false;
}
mRecordFilterIds.insert(filterId);
- mFilters[filterId]->attachFilterToRecord(mDvr);
+ mFilters[filterId]->attachFilterToRecord(mDvrRecord);
return true;
}
bool Demux::detachRecordFilter(int filterId) {
- if (mFilters[filterId] == nullptr || mDvr == nullptr) {
+ if (mFilters[filterId] == nullptr || mDvrRecord == nullptr) {
return false;
}
diff --git a/tv/tuner/1.0/default/Demux.h b/tv/tuner/1.0/default/Demux.h
index 6c46b0d..7f282b2 100644
--- a/tv/tuner/1.0/default/Demux.h
+++ b/tv/tuner/1.0/default/Demux.h
@@ -91,13 +91,23 @@
void setIsRecording(bool isRecording);
void startFrontendInputLoop();
+ /**
+ * A dispatcher to read and dispatch input data to all the started filters.
+ * Each filter handler handles the data filtering/output writing/filterEvent updating.
+ * Note that recording filters are not included.
+ */
+ bool startBroadcastFilterDispatcher();
+ void startBroadcastTsFilter(vector<uint8_t> data);
+
+ void sendFrontendInputToRecord(vector<uint8_t> data);
+ bool startRecordFilterDispatcher();
+
private:
// Tuner service
sp<Tuner> mTunerService;
// Frontend source
sp<Frontend> mFrontend;
- string mFrontendSourceFile;
// A struct that passes the arguments to a newly created filter thread
struct ThreadArgs {
@@ -117,16 +127,6 @@
*/
void deleteEventFlag();
bool readDataFromMQ();
- /**
- * A dispatcher to read and dispatch input data to all the started filters.
- * Each filter handler handles the data filtering/output writing/filterEvent updating.
- * Note that recording filters are not included.
- */
- bool startBroadcastFilterDispatcher();
- void startBroadcastTsFilter(vector<uint8_t> data);
-
- void sendFrontendInputToRecord(vector<uint8_t> data);
- bool startRecordFilterDispatcher();
uint32_t mDemuxId;
uint32_t mCiCamId;
@@ -137,25 +137,31 @@
*/
uint32_t mLastUsedFilterId = -1;
/**
- * Record all the used filter Ids.
+ * Record all the used playback filter Ids.
* Any removed filter id should be removed from this set.
*/
- set<uint32_t> mUsedFilterIds;
+ set<uint32_t> mPlaybackFilterIds;
/**
* Record all the attached record filter Ids.
* Any removed filter id should be removed from this set.
*/
set<uint32_t> mRecordFilterIds;
/**
- * A list of created FilterMQ ptrs.
+ * A list of created Filter sp.
* The array number is the filter ID.
*/
std::map<uint32_t, sp<Filter>> mFilters;
/**
+ * Local reference to the opened Timer Filter instance.
+ */
+ sp<TimeFilter> mTimeFilter;
+
+ /**
* Local reference to the opened DVR object.
*/
- sp<Dvr> mDvr;
+ sp<Dvr> mDvrPlayback;
+ sp<Dvr> mDvrRecord;
// Thread handlers
pthread_t mFrontendInputThread;
diff --git a/tv/tuner/1.0/default/Dvr.cpp b/tv/tuner/1.0/default/Dvr.cpp
index adb2635..68e175c 100644
--- a/tv/tuner/1.0/default/Dvr.cpp
+++ b/tv/tuner/1.0/default/Dvr.cpp
@@ -70,8 +70,7 @@
return status;
}
- // check if the attached filter is a record filter
- mFilters[filterId] = filter;
+ // TODO check if the attached filter is a record filter
if (!mDemux->attachRecordFilter(filterId)) {
return Result::INVALID_ARGUMENT;
}
@@ -94,19 +93,8 @@
return status;
}
- std::map<uint32_t, sp<IFilter>>::iterator it;
-
- it = mFilters.find(filterId);
- if (it != mFilters.end()) {
- mFilters.erase(filterId);
- if (!mDemux->detachRecordFilter(filterId)) {
- return Result::INVALID_ARGUMENT;
- }
- }
-
- // If all the filters are detached, record can't be started
- if (mFilters.empty()) {
- mIsRecordFilterAttached = false;
+ if (!mDemux->detachRecordFilter(filterId)) {
+ return Result::INVALID_ARGUMENT;
}
return Result::SUCCESS;
@@ -183,6 +171,10 @@
return true;
}
+EventFlag* Dvr::getDvrEventFlag() {
+ return mDvrEventFlag;
+}
+
void* Dvr::__threadLoopPlayback(void* user) {
Dvr* const self = static_cast<Dvr*>(user);
self->playbackThreadLoop();
@@ -205,8 +197,9 @@
}
// Our current implementation filter the data and write it into the filter FMQ immediately
// after the DATA_READY from the VTS/framework
- if (!readPlaybackFMQ() || !startFilterDispatcher()) {
- ALOGD("[Dvr] playback data failed to be filtered. Ending thread");
+ if (!readPlaybackFMQ(false /*isVirtualFrontend*/, false /*isRecording*/) ||
+ !startFilterDispatcher(false /*isVirtualFrontend*/, false /*isRecording*/)) {
+ ALOGE("[Dvr] playback data failed to be filtered. Ending thread");
break;
}
@@ -245,7 +238,7 @@
return mPlaybackStatus;
}
-bool Dvr::readPlaybackFMQ() {
+bool Dvr::readPlaybackFMQ(bool isVirtualFrontend, bool isRecording) {
// Read playback data from the input FMQ
int size = mDvrMQ->availableToRead();
int playbackPacketSize = mDvrSettings.playback().packetSize;
@@ -256,7 +249,15 @@
if (!mDvrMQ->read(dataOutputBuffer.data(), playbackPacketSize)) {
return false;
}
- startTpidFilter(dataOutputBuffer);
+ if (isVirtualFrontend) {
+ if (isRecording) {
+ mDemux->sendFrontendInputToRecord(dataOutputBuffer);
+ } else {
+ mDemux->startBroadcastTsFilter(dataOutputBuffer);
+ }
+ } else {
+ startTpidFilter(dataOutputBuffer);
+ }
}
return true;
@@ -275,7 +276,15 @@
}
}
-bool Dvr::startFilterDispatcher() {
+bool Dvr::startFilterDispatcher(bool isVirtualFrontend, bool isRecording) {
+ if (isVirtualFrontend) {
+ if (isRecording) {
+ return mDemux->startRecordFilterDispatcher();
+ } else {
+ return mDemux->startBroadcastFilterDispatcher();
+ }
+ }
+
std::map<uint32_t, sp<IFilter>>::iterator it;
// Handle the output data per filter type
for (it = mFilters.begin(); it != mFilters.end(); it++) {
@@ -329,27 +338,15 @@
return mRecordStatus;
}
-bool Dvr::addPlaybackFilter(sp<IFilter> filter) {
- uint32_t filterId;
- Result status;
-
- filter->getId([&](Result result, uint32_t id) {
- filterId = id;
- status = result;
- });
-
- if (status != Result::SUCCESS) {
- return false;
- }
-
+bool Dvr::addPlaybackFilter(uint32_t filterId, sp<IFilter> filter) {
mFilters[filterId] = filter;
return true;
}
-DvrType Dvr::getType() {
- return mType;
+bool Dvr::removePlaybackFilter(uint32_t filterId) {
+ mFilters.erase(filterId);
+ return true;
}
-
} // namespace implementation
} // namespace V1_0
} // namespace tuner
diff --git a/tv/tuner/1.0/default/Dvr.h b/tv/tuner/1.0/default/Dvr.h
index 08afd5d..a63a256 100644
--- a/tv/tuner/1.0/default/Dvr.h
+++ b/tv/tuner/1.0/default/Dvr.h
@@ -81,8 +81,11 @@
bool createDvrMQ();
void sendBroadcastInputToDvrRecord(vector<uint8_t> byteBuffer);
bool writeRecordFMQ(const std::vector<uint8_t>& data);
- DvrType getType();
- bool addPlaybackFilter(sp<IFilter> filter);
+ bool addPlaybackFilter(uint32_t filterId, sp<IFilter> filter);
+ bool removePlaybackFilter(uint32_t filterId);
+ bool readPlaybackFMQ(bool isVirtualFrontend, bool isRecording);
+ bool startFilterDispatcher(bool isVirtualFrontend, bool isRecording);
+ EventFlag* getDvrEventFlag();
private:
// Demux service
@@ -105,9 +108,7 @@
* A dispatcher to read and dispatch input data to all the started filters.
* Each filter handler handles the data filtering/output writing/filterEvent updating.
*/
- bool readPlaybackFMQ();
void startTpidFilter(vector<uint8_t> data);
- bool startFilterDispatcher();
static void* __threadLoopPlayback(void* user);
static void* __threadLoopRecord(void* user);
void playbackThreadLoop();
@@ -123,7 +124,6 @@
// Thread handlers
pthread_t mDvrThread;
- pthread_t mBroadcastInputThread;
// FMQ status local records
PlaybackStatus mPlaybackStatus;
@@ -132,7 +132,6 @@
* If a specific filter's writing loop is still running
*/
bool mDvrThreadRunning;
- bool mBroadcastInputThreadRunning;
bool mKeepFetchingDataFromFrontend;
/**
* Lock to protect writes to the FMQs
@@ -143,7 +142,6 @@
*/
std::mutex mPlaybackStatusLock;
std::mutex mRecordStatusLock;
- std::mutex mBroadcastInputThreadLock;
std::mutex mDvrThreadLock;
const bool DEBUG_DVR = false;
@@ -151,7 +149,6 @@
// Booleans to check if recording is running.
// Recording is ready when both of the following are set to true.
bool mIsRecordStarted = false;
- bool mIsRecordFilterAttached = false;
};
} // namespace implementation
diff --git a/tv/tuner/1.0/default/Filter.cpp b/tv/tuner/1.0/default/Filter.cpp
index 8bca70c..30b19c0 100644
--- a/tv/tuner/1.0/default/Filter.cpp
+++ b/tv/tuner/1.0/default/Filter.cpp
@@ -47,12 +47,18 @@
if (mType.subType.tsFilterType() == DemuxTsFilterType::PCR) {
mIsPcrFilter = true;
}
+ if (mType.subType.tsFilterType() == DemuxTsFilterType::RECORD) {
+ mIsRecordFilter = true;
+ }
break;
case DemuxFilterMainType::MMTP:
if (mType.subType.mmtpFilterType() == DemuxMmtpFilterType::AUDIO ||
mType.subType.mmtpFilterType() == DemuxMmtpFilterType::VIDEO) {
mIsMediaFilter = true;
}
+ if (mType.subType.mmtpFilterType() == DemuxMmtpFilterType::RECORD) {
+ mIsRecordFilter = true;
+ }
break;
case DemuxFilterMainType::IP:
break;
@@ -535,12 +541,6 @@
}
Result Filter::startRecordFilterHandler() {
- /*DemuxFilterTsRecordEvent tsRecordEvent;
- tsRecordEvent.pid.tPid(0);
- tsRecordEvent.indexMask.tsIndexMask(0x01);
- mFilterEvent.events.resize(1);
- mFilterEvent.events[0].tsRecord(tsRecordEvent);
-*/
std::lock_guard<std::mutex> lock(mRecordFilterOutputLock);
if (mRecordFilterOutput.empty()) {
return Result::SUCCESS;
@@ -567,7 +567,7 @@
bool Filter::writeSectionsAndCreateEvent(vector<uint8_t> data) {
// TODO check how many sections has been read
- ALOGD("[Filter] section hander");
+ ALOGD("[Filter] section handler");
std::lock_guard<std::mutex> lock(mFilterEventLock);
if (!writeDataToFilterMQ(data)) {
return false;
diff --git a/tv/tuner/1.0/default/Filter.h b/tv/tuner/1.0/default/Filter.h
index 09e9604..9386dca 100644
--- a/tv/tuner/1.0/default/Filter.h
+++ b/tv/tuner/1.0/default/Filter.h
@@ -91,6 +91,7 @@
void freeAvHandle();
bool isMediaFilter() { return mIsMediaFilter; };
bool isPcrFilter() { return mIsPcrFilter; };
+ bool isRecordFilter() { return mIsRecordFilter; };
private:
// Tuner service
@@ -107,6 +108,7 @@
DemuxFilterType mType;
bool mIsMediaFilter = false;
bool mIsPcrFilter = false;
+ bool mIsRecordFilter = false;
DemuxFilterSettings mFilterSettings;
uint16_t mTpid;
diff --git a/tv/tuner/1.0/default/Frontend.cpp b/tv/tuner/1.0/default/Frontend.cpp
index 996b6ef..8bf0ec5 100644
--- a/tv/tuner/1.0/default/Frontend.cpp
+++ b/tv/tuner/1.0/default/Frontend.cpp
@@ -66,7 +66,7 @@
mTunerService->frontendStartTune(mId);
mCallback->onEvent(FrontendEventType::LOCKED);
- mIsLocked = false;
+ mIsLocked = true;
return Result::SUCCESS;
}
@@ -254,7 +254,9 @@
Return<Result> Frontend::setLnb(uint32_t /* lnb */) {
ALOGV("%s", __FUNCTION__);
-
+ if (!supportsSatellite()) {
+ return Result::INVALID_STATE;
+ }
return Result::SUCCESS;
}
@@ -266,10 +268,14 @@
return mId;
}
-string Frontend::getSourceFile() {
- return FRONTEND_STREAM_FILE;
+bool Frontend::supportsSatellite() {
+ return mType == FrontendType::DVBS || mType == FrontendType::ISDBS ||
+ mType == FrontendType::ISDBS3;
}
+bool Frontend::isLocked() {
+ return mIsLocked;
+}
} // namespace implementation
} // namespace V1_0
} // namespace tuner
diff --git a/tv/tuner/1.0/default/Frontend.h b/tv/tuner/1.0/default/Frontend.h
index 65537d7..a529b74 100644
--- a/tv/tuner/1.0/default/Frontend.h
+++ b/tv/tuner/1.0/default/Frontend.h
@@ -68,15 +68,17 @@
string getSourceFile();
+ bool isLocked();
+
private:
virtual ~Frontend();
+ bool supportsSatellite();
sp<IFrontendCallback> mCallback;
sp<Tuner> mTunerService;
FrontendType mType = FrontendType::UNDEFINED;
FrontendId mId = 0;
bool mIsLocked = false;
- const string FRONTEND_STREAM_FILE = "/vendor/etc/segment000000.ts";
std::ifstream mFrontendData;
};
diff --git a/tv/tuner/1.0/default/TimeFilter.cpp b/tv/tuner/1.0/default/TimeFilter.cpp
index 0b1fd1c..cec824f 100644
--- a/tv/tuner/1.0/default/TimeFilter.cpp
+++ b/tv/tuner/1.0/default/TimeFilter.cpp
@@ -34,24 +34,32 @@
TimeFilter::~TimeFilter() {}
-Return<Result> TimeFilter::setTimeStamp(uint64_t /* timeStamp */) {
+Return<Result> TimeFilter::setTimeStamp(uint64_t timeStamp) {
ALOGV("%s", __FUNCTION__);
+ if (timeStamp == INVALID_TIME_STAMP) {
+ return Result::INVALID_ARGUMENT;
+ }
+ mTimeStamp = timeStamp;
+ mBeginTime = time(NULL);
return Result::SUCCESS;
}
Return<Result> TimeFilter::clearTimeStamp() {
ALOGV("%s", __FUNCTION__);
+ mTimeStamp = INVALID_TIME_STAMP;
return Result::SUCCESS;
}
Return<void> TimeFilter::getTimeStamp(getTimeStamp_cb _hidl_cb) {
ALOGV("%s", __FUNCTION__);
+ if (mTimeStamp == INVALID_TIME_STAMP) {
+ _hidl_cb(Result::INVALID_STATE, mTimeStamp);
+ }
- uint64_t timeStamp = 0;
-
- _hidl_cb(Result::SUCCESS, timeStamp);
+ uint64_t currentTimeStamp = mTimeStamp + difftime(time(NULL), mBeginTime) * 900000;
+ _hidl_cb(Result::SUCCESS, currentTimeStamp);
return Void();
}
@@ -66,6 +74,7 @@
Return<Result> TimeFilter::close() {
ALOGV("%s", __FUNCTION__);
+ mTimeStamp = INVALID_TIME_STAMP;
return Result::SUCCESS;
}
diff --git a/tv/tuner/1.0/default/TimeFilter.h b/tv/tuner/1.0/default/TimeFilter.h
index 7131df8..cb3f29d 100644
--- a/tv/tuner/1.0/default/TimeFilter.h
+++ b/tv/tuner/1.0/default/TimeFilter.h
@@ -19,6 +19,7 @@
#include <android/hardware/tv/tuner/1.0/ITimeFilter.h>
#include "Demux.h"
+#include "time.h"
using namespace std;
@@ -35,6 +36,8 @@
using FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+#define INVALID_TIME_STAMP -1
+
class Demux;
class TimeFilter : public ITimeFilter {
@@ -57,6 +60,8 @@
private:
sp<Demux> mDemux;
+ uint64_t mTimeStamp = INVALID_TIME_STAMP;
+ time_t mBeginTime;
};
} // namespace implementation
diff --git a/tv/tuner/1.0/default/Tuner.cpp b/tv/tuner/1.0/default/Tuner.cpp
index 821d83f..48ce384 100644
--- a/tv/tuner/1.0/default/Tuner.cpp
+++ b/tv/tuner/1.0/default/Tuner.cpp
@@ -139,6 +139,8 @@
DemuxCapabilities caps;
+ // IP filter can be an MMTP filter's data source.
+ caps.linkCaps = {0x00, 0x00, 0x02, 0x00, 0x00};
_hidl_cb(Result::SUCCESS, caps);
return Void();
}
@@ -229,6 +231,9 @@
void Tuner::setFrontendAsDemuxSource(uint32_t frontendId, uint32_t demuxId) {
mFrontendToDemux[frontendId] = demuxId;
+ if (mFrontends[frontendId] != nullptr && mFrontends[frontendId]->isLocked()) {
+ mDemuxes[demuxId]->startFrontendInputLoop();
+ }
}
void Tuner::frontendStopTune(uint32_t frontendId) {
diff --git a/tv/tuner/1.0/vts/functional/Android.bp b/tv/tuner/1.0/vts/functional/Android.bp
index 8c08873..1765915 100644
--- a/tv/tuner/1.0/vts/functional/Android.bp
+++ b/tv/tuner/1.0/vts/functional/Android.bp
@@ -24,6 +24,7 @@
"FilterTests.cpp",
"DvrTests.cpp",
"DescramblerTests.cpp",
+ "LnbTests.cpp",
],
static_libs: [
"android.hardware.cas@1.0",
diff --git a/tv/tuner/1.0/vts/functional/DemuxTests.cpp b/tv/tuner/1.0/vts/functional/DemuxTests.cpp
index 6c32534..37a47d7 100644
--- a/tv/tuner/1.0/vts/functional/DemuxTests.cpp
+++ b/tv/tuner/1.0/vts/functional/DemuxTests.cpp
@@ -33,6 +33,19 @@
return AssertionResult(status.isOk());
}
+AssertionResult DemuxTests::getDemuxCaps(DemuxCapabilities& demuxCaps) {
+ if (!mDemux) {
+ ALOGW("[vts] Test with openDemux first.");
+ return failure();
+ }
+ Result status;
+ mService->getDemuxCaps([&](Result result, DemuxCapabilities caps) {
+ status = result;
+ demuxCaps = caps;
+ });
+ return AssertionResult(status == Result::SUCCESS);
+}
+
AssertionResult DemuxTests::closeDemux() {
EXPECT_TRUE(mDemux) << "Test with openDemux first.";
auto status = mDemux->close();
@@ -40,23 +53,23 @@
return AssertionResult(status.isOk());
}
-void DemuxTests::getAvSyncId(sp<IFilter> filter, uint32_t& avSyncHwId) {
- ASSERT_TRUE(mDemux) << "Demux is not opened yet.";
+AssertionResult DemuxTests::getAvSyncId(sp<IFilter> filter, uint32_t& avSyncHwId) {
+ EXPECT_TRUE(mDemux) << "Demux is not opened yet.";
Result status;
mDemux->getAvSyncHwId(filter, [&](Result result, uint32_t id) {
status = result;
avSyncHwId = id;
});
- ASSERT_TRUE(status == Result::SUCCESS) << "Fail to get avSyncHwId.";
+ return AssertionResult(status == Result::SUCCESS);
}
-void DemuxTests::getAvSyncTime(uint32_t avSyncId) {
- ASSERT_TRUE(mDemux) << "Demux is not opened yet.";
+AssertionResult DemuxTests::getAvSyncTime(uint32_t avSyncId) {
+ EXPECT_TRUE(mDemux) << "Demux is not opened yet.";
Result status;
uint64_t syncTime;
mDemux->getAvSyncTime(avSyncId, [&](Result result, uint64_t time) {
status = result;
syncTime = time;
});
- ASSERT_TRUE(status == Result::SUCCESS) << "Fail to get avSyncTime.";
+ return AssertionResult(status == Result::SUCCESS);
}
\ No newline at end of file
diff --git a/tv/tuner/1.0/vts/functional/DemuxTests.h b/tv/tuner/1.0/vts/functional/DemuxTests.h
index 0443c67..b249ea8 100644
--- a/tv/tuner/1.0/vts/functional/DemuxTests.h
+++ b/tv/tuner/1.0/vts/functional/DemuxTests.h
@@ -30,6 +30,7 @@
using android::sp;
using android::hardware::Return;
using android::hardware::Void;
+using android::hardware::tv::tuner::V1_0::DemuxCapabilities;
using android::hardware::tv::tuner::V1_0::IDemux;
using android::hardware::tv::tuner::V1_0::IFilter;
using android::hardware::tv::tuner::V1_0::ITuner;
@@ -43,8 +44,9 @@
AssertionResult openDemux(sp<IDemux>& demux, uint32_t& demuxId);
AssertionResult setDemuxFrontendDataSource(uint32_t frontendId);
- void getAvSyncId(sp<IFilter> filter, uint32_t& avSyncHwId);
- void getAvSyncTime(uint32_t avSyncId);
+ AssertionResult getAvSyncId(sp<IFilter> filter, uint32_t& avSyncHwId);
+ AssertionResult getAvSyncTime(uint32_t avSyncId);
+ AssertionResult getDemuxCaps(DemuxCapabilities& demuxCaps);
AssertionResult closeDemux();
protected:
diff --git a/tv/tuner/1.0/vts/functional/DescramblerTests.h b/tv/tuner/1.0/vts/functional/DescramblerTests.h
index 31f4663..16d480d 100644
--- a/tv/tuner/1.0/vts/functional/DescramblerTests.h
+++ b/tv/tuner/1.0/vts/functional/DescramblerTests.h
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
#include <android-base/logging.h>
#include <android/hardware/cas/1.0/types.h>
#include <android/hardware/cas/1.2/ICas.h>
@@ -28,6 +26,8 @@
#include <android/hardware/tv/tuner/1.0/ITuner.h>
#include <android/hardware/tv/tuner/1.0/types.h>
#include <fmq/MessageQueue.h>
+#include <gtest/gtest.h>
+#include <hidl/HidlSupport.h>
#include <hidl/Status.h>
#include <utils/Condition.h>
#include <utils/Mutex.h>
@@ -69,6 +69,8 @@
using ::testing::AssertionResult;
+using namespace std;
+
class MediaCasListener : public ICasListener {
public:
virtual Return<void> onEvent(int32_t /*event*/, int32_t /*arg*/,
diff --git a/tv/tuner/1.0/vts/functional/DvrTests.cpp b/tv/tuner/1.0/vts/functional/DvrTests.cpp
index 7e7f8e6..0dfc032 100644
--- a/tv/tuner/1.0/vts/functional/DvrTests.cpp
+++ b/tv/tuner/1.0/vts/functional/DvrTests.cpp
@@ -49,49 +49,73 @@
EXPECT_TRUE(EventFlag::createEventFlag(mPlaybackMQ->getEventFlagWord(), &playbackMQEventFlag) ==
android::OK);
- // open the stream and get its length
- std::ifstream inputData(mInputDataFile.c_str(), std::ifstream::binary);
- int writeSize = mPlaybackSettings.packetSize * 6;
- char* buffer = new char[writeSize];
- ALOGW("[vts] playback thread loop start %s!", mInputDataFile.c_str());
- if (!inputData.is_open()) {
+ int fd = open(mInputDataFile.c_str(), O_RDONLY | O_LARGEFILE);
+ int readBytes;
+ uint32_t regionSize = 0;
+ uint8_t* buffer;
+ ALOGW("[vts] playback thread loop start %s", mInputDataFile.c_str());
+ if (fd < 0) {
mPlaybackThreadRunning = false;
ALOGW("[vts] Error %s", strerror(errno));
}
while (mPlaybackThreadRunning) {
- // move the stream pointer for packet size * 6 every read until the end
while (mKeepWritingPlaybackFMQ) {
- inputData.read(buffer, writeSize);
- if (!inputData) {
- int leftSize = inputData.gcount();
- if (leftSize == 0) {
- mPlaybackThreadRunning = false;
- break;
- }
- inputData.clear();
- inputData.read(buffer, leftSize);
- // Write the left over of the input data and quit the thread
- if (leftSize > 0) {
- EXPECT_TRUE(mPlaybackMQ->write((unsigned char*)&buffer[0], leftSize));
- playbackMQEventFlag->wake(
- static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
- }
+ int totalWrite = mPlaybackMQ->availableToWrite();
+ if (totalWrite * 4 < mPlaybackMQ->getQuantumCount()) {
+ // Wait for the HAL implementation to read more data then write.
+ continue;
+ }
+ MessageQueue<uint8_t, kSynchronizedReadWrite>::MemTransaction memTx;
+ if (!mPlaybackMQ->beginWrite(totalWrite, &memTx)) {
+ ALOGW("[vts] Fail to write into Playback fmq.");
mPlaybackThreadRunning = false;
break;
}
- // Write input FMQ and notify the Tuner Implementation
- EXPECT_TRUE(mPlaybackMQ->write((unsigned char*)&buffer[0], writeSize));
+ auto first = memTx.getFirstRegion();
+ buffer = first.getAddress();
+ regionSize = first.getLength();
+
+ if (regionSize > 0) {
+ readBytes = read(fd, buffer, regionSize);
+ if (readBytes <= 0) {
+ if (readBytes < 0) {
+ ALOGW("[vts] Read from %s failed.", mInputDataFile.c_str());
+ } else {
+ ALOGW("[vts] playback input EOF.");
+ }
+ mPlaybackThreadRunning = false;
+ break;
+ }
+ }
+ if (regionSize == 0 || (readBytes == regionSize && regionSize < totalWrite)) {
+ auto second = memTx.getSecondRegion();
+ buffer = second.getAddress();
+ regionSize = second.getLength();
+ int ret = read(fd, buffer, regionSize);
+ if (ret <= 0) {
+ if (ret < 0) {
+ ALOGW("[vts] Read from %s failed.", mInputDataFile.c_str());
+ } else {
+ ALOGW("[vts] playback input EOF.");
+ }
+ mPlaybackThreadRunning = false;
+ break;
+ }
+ readBytes += ret;
+ }
+ if (!mPlaybackMQ->commitWrite(readBytes)) {
+ ALOGW("[vts] Failed to commit write playback fmq.");
+ mPlaybackThreadRunning = false;
+ break;
+ }
playbackMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
- inputData.seekg(writeSize, inputData.cur);
- sleep(1);
}
}
+ mPlaybackThreadRunning = false;
ALOGW("[vts] Playback thread end.");
-
- delete[] buffer;
- inputData.close();
+ close(fd);
}
void DvrCallback::testRecordOutput() {
@@ -186,32 +210,65 @@
EXPECT_TRUE(mDemux) << "Test with openDemux first.";
// Create dvr callback
- mDvrCallback = new DvrCallback();
+ if (type == DvrType::PLAYBACK) {
+ mDvrPlaybackCallback = new DvrCallback();
+ mDemux->openDvr(type, bufferSize, mDvrPlaybackCallback,
+ [&](Result result, const sp<IDvr>& dvr) {
+ mDvrPlayback = dvr;
+ status = result;
+ });
+ if (status == Result::SUCCESS) {
+ mDvrPlaybackCallback->setDvr(mDvrPlayback);
+ }
+ }
- mDemux->openDvr(type, bufferSize, mDvrCallback, [&](Result result, const sp<IDvr>& dvr) {
- mDvr = dvr;
+ if (type == DvrType::RECORD) {
+ mDvrRecordCallback = new DvrCallback();
+ mDemux->openDvr(type, bufferSize, mDvrRecordCallback,
+ [&](Result result, const sp<IDvr>& dvr) {
+ mDvrRecord = dvr;
+ status = result;
+ });
+ if (status == Result::SUCCESS) {
+ mDvrRecordCallback->setDvr(mDvrRecord);
+ }
+ }
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::configDvrPlayback(DvrSettings setting) {
+ Result status = mDvrPlayback->configure(setting);
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::configDvrRecord(DvrSettings setting) {
+ Result status = mDvrRecord->configure(setting);
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::getDvrPlaybackMQDescriptor() {
+ Result status;
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+ EXPECT_TRUE(mDvrPlayback) << "Test with openDvr first.";
+
+ mDvrPlayback->getQueueDesc([&](Result result, const MQDesc& dvrMQDesc) {
+ mDvrPlaybackMQDescriptor = dvrMQDesc;
status = result;
});
- if (status == Result::SUCCESS) {
- mDvrCallback->setDvr(mDvr);
- }
return AssertionResult(status == Result::SUCCESS);
}
-AssertionResult DvrTests::configDvr(DvrSettings setting) {
- Result status = mDvr->configure(setting);
-
- return AssertionResult(status == Result::SUCCESS);
-}
-
-AssertionResult DvrTests::getDvrMQDescriptor() {
+AssertionResult DvrTests::getDvrRecordMQDescriptor() {
Result status;
EXPECT_TRUE(mDemux) << "Test with openDemux first.";
- EXPECT_TRUE(mDvr) << "Test with openDvr first.";
+ EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
- mDvr->getQueueDesc([&](Result result, const MQDesc& dvrMQDesc) {
- mDvrMQDescriptor = dvrMQDesc;
+ mDvrRecord->getQueueDesc([&](Result result, const MQDesc& dvrMQDesc) {
+ mDvrRecordMQDescriptor = dvrMQDesc;
status = result;
});
@@ -221,9 +278,9 @@
AssertionResult DvrTests::attachFilterToDvr(sp<IFilter> filter) {
Result status;
EXPECT_TRUE(mDemux) << "Test with openDemux first.";
- EXPECT_TRUE(mDvr) << "Test with openDvr first.";
+ EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
- status = mDvr->attachFilter(filter);
+ status = mDvrRecord->attachFilter(filter);
return AssertionResult(status == Result::SUCCESS);
}
@@ -231,35 +288,61 @@
AssertionResult DvrTests::detachFilterToDvr(sp<IFilter> filter) {
Result status;
EXPECT_TRUE(mDemux) << "Test with openDemux first.";
- EXPECT_TRUE(mDvr) << "Test with openDvr first.";
+ EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
- status = mDvr->detachFilter(filter);
+ status = mDvrRecord->detachFilter(filter);
return AssertionResult(status == Result::SUCCESS);
}
-AssertionResult DvrTests::startDvr() {
+AssertionResult DvrTests::startDvrPlayback() {
Result status;
EXPECT_TRUE(mDemux) << "Test with openDemux first.";
- EXPECT_TRUE(mDvr) << "Test with openDvr first.";
+ EXPECT_TRUE(mDvrPlayback) << "Test with openDvr first.";
- status = mDvr->start();
+ status = mDvrPlayback->start();
return AssertionResult(status == Result::SUCCESS);
}
-AssertionResult DvrTests::stopDvr() {
+AssertionResult DvrTests::stopDvrPlayback() {
Result status;
EXPECT_TRUE(mDemux) << "Test with openDemux first.";
- EXPECT_TRUE(mDvr) << "Test with openDvr first.";
+ EXPECT_TRUE(mDvrPlayback) << "Test with openDvr first.";
- status = mDvr->stop();
+ status = mDvrPlayback->stop();
return AssertionResult(status == Result::SUCCESS);
}
-void DvrTests::closeDvr() {
+void DvrTests::closeDvrPlayback() {
ASSERT_TRUE(mDemux);
- ASSERT_TRUE(mDvr);
- ASSERT_TRUE(mDvr->close() == Result::SUCCESS);
+ ASSERT_TRUE(mDvrPlayback);
+ ASSERT_TRUE(mDvrPlayback->close() == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::startDvrRecord() {
+ Result status;
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+ EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
+
+ status = mDvrRecord->start();
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::stopDvrRecord() {
+ Result status;
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+ EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
+
+ status = mDvrRecord->stop();
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+void DvrTests::closeDvrRecord() {
+ ASSERT_TRUE(mDemux);
+ ASSERT_TRUE(mDvrRecord);
+ ASSERT_TRUE(mDvrRecord->close() == Result::SUCCESS);
}
diff --git a/tv/tuner/1.0/vts/functional/DvrTests.h b/tv/tuner/1.0/vts/functional/DvrTests.h
index dd00c27..3997839 100644
--- a/tv/tuner/1.0/vts/functional/DvrTests.h
+++ b/tv/tuner/1.0/vts/functional/DvrTests.h
@@ -14,14 +14,15 @@
* limitations under the License.
*/
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
#include <android-base/logging.h>
#include <android/hardware/tv/tuner/1.0/IDvr.h>
#include <android/hardware/tv/tuner/1.0/IDvrCallback.h>
#include <android/hardware/tv/tuner/1.0/ITuner.h>
#include <android/hardware/tv/tuner/1.0/types.h>
+#include <fcntl.h>
#include <fmq/MessageQueue.h>
+#include <gtest/gtest.h>
+#include <hidl/HidlSupport.h>
#include <hidl/Status.h>
#include <utils/Condition.h>
#include <utils/Mutex.h>
@@ -52,6 +53,8 @@
using android::hardware::tv::tuner::V1_0::RecordStatus;
using android::hardware::tv::tuner::V1_0::Result;
+using namespace std;
+
#define WAIT_TIMEOUT 3000000000
class DvrCallback : public IDvrCallback {
@@ -149,25 +152,31 @@
void setDemux(sp<IDemux> demux) { mDemux = demux; }
void startPlaybackInputThread(string& dataInputFile, PlaybackSettings& settings) {
- mDvrCallback->startPlaybackInputThread(dataInputFile, settings, mDvrMQDescriptor);
+ mDvrPlaybackCallback->startPlaybackInputThread(dataInputFile, settings,
+ mDvrPlaybackMQDescriptor);
};
void startRecordOutputThread(RecordSettings settings) {
- mDvrCallback->startRecordOutputThread(settings, mDvrMQDescriptor);
+ mDvrRecordCallback->startRecordOutputThread(settings, mDvrRecordMQDescriptor);
};
- void stopPlaybackThread() { mDvrCallback->stopPlaybackThread(); }
- void testRecordOutput() { mDvrCallback->testRecordOutput(); }
- void stopRecordThread() { mDvrCallback->stopPlaybackThread(); }
+ void stopPlaybackThread() { mDvrPlaybackCallback->stopPlaybackThread(); }
+ void testRecordOutput() { mDvrRecordCallback->testRecordOutput(); }
+ void stopRecordThread() { mDvrRecordCallback->stopRecordThread(); }
AssertionResult openDvrInDemux(DvrType type, uint32_t bufferSize);
- AssertionResult configDvr(DvrSettings setting);
- AssertionResult getDvrMQDescriptor();
+ AssertionResult configDvrPlayback(DvrSettings setting);
+ AssertionResult configDvrRecord(DvrSettings setting);
+ AssertionResult getDvrPlaybackMQDescriptor();
+ AssertionResult getDvrRecordMQDescriptor();
AssertionResult attachFilterToDvr(sp<IFilter> filter);
AssertionResult detachFilterToDvr(sp<IFilter> filter);
- AssertionResult stopDvr();
- AssertionResult startDvr();
- void closeDvr();
+ AssertionResult stopDvrPlayback();
+ AssertionResult startDvrPlayback();
+ AssertionResult stopDvrRecord();
+ AssertionResult startDvrRecord();
+ void closeDvrPlayback();
+ void closeDvrRecord();
protected:
static AssertionResult failure() { return ::testing::AssertionFailure(); }
@@ -175,11 +184,11 @@
static AssertionResult success() { return ::testing::AssertionSuccess(); }
sp<ITuner> mService;
- sp<IDvr> mDvr;
+ sp<IDvr> mDvrPlayback;
+ sp<IDvr> mDvrRecord;
sp<IDemux> mDemux;
- sp<DvrCallback> mDvrCallback;
- MQDesc mDvrMQDescriptor;
-
- pthread_t mPlaybackshread;
- bool mPlaybackThreadRunning;
+ sp<DvrCallback> mDvrPlaybackCallback;
+ sp<DvrCallback> mDvrRecordCallback;
+ MQDesc mDvrPlaybackMQDescriptor;
+ MQDesc mDvrRecordMQDescriptor;
};
diff --git a/tv/tuner/1.0/vts/functional/FilterTests.cpp b/tv/tuner/1.0/vts/functional/FilterTests.cpp
index 4639e59..0ecdf73 100644
--- a/tv/tuner/1.0/vts/functional/FilterTests.cpp
+++ b/tv/tuner/1.0/vts/functional/FilterTests.cpp
@@ -149,6 +149,44 @@
return AssertionResult(status == Result::SUCCESS);
}
+AssertionResult FilterTests::openTimeFilterInDemux() {
+ if (!mDemux) {
+ ALOGW("[vts] Test with openDemux first.");
+ return failure();
+ }
+
+ // Add time filter to the local demux
+ Result status;
+ mDemux->openTimeFilter([&](Result result, const sp<ITimeFilter>& filter) {
+ mTimeFilter = filter;
+ status = result;
+ });
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FilterTests::setTimeStamp(uint64_t timeStamp) {
+ if (!mTimeFilter) {
+ ALOGW("[vts] Test with openTimeFilterInDemux first.");
+ return failure();
+ }
+
+ mBeginTimeStamp = timeStamp;
+ return AssertionResult(mTimeFilter->setTimeStamp(timeStamp) == Result::SUCCESS);
+}
+
+AssertionResult FilterTests::getTimeStamp() {
+ if (!mTimeFilter) {
+ ALOGW("[vts] Test with openTimeFilterInDemux first.");
+ return failure();
+ }
+
+ Result status;
+ mTimeFilter->getTimeStamp([&](Result result, uint64_t /*timeStamp*/) { status = result; });
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
AssertionResult FilterTests::getNewlyOpenedFilterId(uint32_t& filterId) {
Result status;
EXPECT_TRUE(mDemux) << "Test with openDemux first.";
@@ -197,6 +235,26 @@
return AssertionResult(status == Result::SUCCESS);
}
+AssertionResult FilterTests::setFilterDataSource(uint32_t sourceFilterId, uint32_t sinkFilterId) {
+ if (!mFilters[sourceFilterId] || !mFilters[sinkFilterId]) {
+ ALOGE("[vts] setFilterDataSource filter not opened.");
+ return failure();
+ }
+
+ auto status = mFilters[sinkFilterId]->setDataSource(mFilters[sourceFilterId]);
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FilterTests::setFilterDataSourceToDemux(uint32_t filterId) {
+ if (!mFilters[filterId]) {
+ ALOGE("[vts] setFilterDataSourceToDemux filter not opened.");
+ return failure();
+ }
+
+ auto status = mFilters[filterId]->setDataSource(NULL);
+ return AssertionResult(status == Result::SUCCESS);
+}
+
AssertionResult FilterTests::startFilter(uint32_t filterId) {
EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
Result status = mFilters[filterId]->start();
@@ -209,6 +267,15 @@
return AssertionResult(status == Result::SUCCESS);
}
+AssertionResult FilterTests::clearTimeStamp() {
+ if (!mTimeFilter) {
+ ALOGW("[vts] Test with openTimeFilterInDemux first.");
+ return failure();
+ }
+
+ return AssertionResult(mTimeFilter->clearTimeStamp() == Result::SUCCESS);
+}
+
AssertionResult FilterTests::closeFilter(uint32_t filterId) {
EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
Result status = mFilters[filterId]->close();
@@ -224,3 +291,12 @@
}
return AssertionResult(status == Result::SUCCESS);
}
+
+AssertionResult FilterTests::closeTimeFilter() {
+ if (!mTimeFilter) {
+ ALOGW("[vts] Test with openTimeFilterInDemux first.");
+ return failure();
+ }
+
+ return AssertionResult(mTimeFilter->close() == Result::SUCCESS);
+}
diff --git a/tv/tuner/1.0/vts/functional/FilterTests.h b/tv/tuner/1.0/vts/functional/FilterTests.h
index 71efce4..a76a6b9 100644
--- a/tv/tuner/1.0/vts/functional/FilterTests.h
+++ b/tv/tuner/1.0/vts/functional/FilterTests.h
@@ -57,6 +57,7 @@
using android::hardware::tv::tuner::V1_0::IDemux;
using android::hardware::tv::tuner::V1_0::IFilter;
using android::hardware::tv::tuner::V1_0::IFilterCallback;
+using android::hardware::tv::tuner::V1_0::ITimeFilter;
using android::hardware::tv::tuner::V1_0::ITuner;
using android::hardware::tv::tuner::V1_0::Result;
@@ -151,12 +152,19 @@
std::map<uint32_t, sp<FilterCallback>> getFilterCallbacks() { return mFilterCallbacks; }
AssertionResult openFilterInDemux(DemuxFilterType type, uint32_t bufferSize);
+ AssertionResult openTimeFilterInDemux();
+ AssertionResult setTimeStamp(uint64_t timeStamp);
+ AssertionResult getTimeStamp();
AssertionResult getNewlyOpenedFilterId(uint32_t& filterId);
AssertionResult configFilter(DemuxFilterSettings setting, uint32_t filterId);
AssertionResult getFilterMQDescriptor(uint32_t filterId);
+ AssertionResult setFilterDataSource(uint32_t sourceFilterId, uint32_t sinkFilterId);
+ AssertionResult setFilterDataSourceToDemux(uint32_t filterId);
AssertionResult startFilter(uint32_t filterId);
+ AssertionResult clearTimeStamp();
AssertionResult stopFilter(uint32_t filterId);
AssertionResult closeFilter(uint32_t filterId);
+ AssertionResult closeTimeFilter();
FilterEventType getFilterEventType(DemuxFilterType type) {
FilterEventType eventType = FilterEventType::UNDEFINED;
@@ -212,6 +220,7 @@
sp<ITuner> mService;
sp<IFilter> mFilter;
+ sp<ITimeFilter> mTimeFilter;
sp<IDemux> mDemux;
std::map<uint32_t, sp<IFilter>> mFilters;
std::map<uint32_t, sp<FilterCallback>> mFilterCallbacks;
@@ -221,4 +230,5 @@
vector<uint32_t> mUsedFilterIds;
uint32_t mFilterId = -1;
+ uint64_t mBeginTimeStamp;
};
diff --git a/tv/tuner/1.0/vts/functional/FrontendTests.cpp b/tv/tuner/1.0/vts/functional/FrontendTests.cpp
index d54a959..45951d2 100644
--- a/tv/tuner/1.0/vts/functional/FrontendTests.cpp
+++ b/tv/tuner/1.0/vts/functional/FrontendTests.cpp
@@ -360,21 +360,48 @@
ASSERT_TRUE(status == Result::SUCCESS);
}
-AssertionResult FrontendTests::tuneFrontend(FrontendConfig config) {
+AssertionResult FrontendTests::tuneFrontend(FrontendConfig config, bool testWithDemux) {
EXPECT_TRUE(mFrontendCallback)
<< "test with openFrontendById/setFrontendCallback/getFrontendInfo first.";
EXPECT_TRUE(mFrontendInfo.type == config.type)
<< "FrontendConfig does not match the frontend info of the given id.";
+ mIsSoftwareFe = config.isSoftwareFe;
+ bool result = true;
+ if (mIsSoftwareFe && testWithDemux) {
+ DvrConfig dvrConfig;
+ getSoftwareFrontendPlaybackConfig(dvrConfig);
+ result &= mDvrTests.openDvrInDemux(dvrConfig.type, dvrConfig.bufferSize) == success();
+ result &= mDvrTests.configDvrPlayback(dvrConfig.settings) == success();
+ result &= mDvrTests.getDvrPlaybackMQDescriptor() == success();
+ mDvrTests.startPlaybackInputThread(dvrConfig.playbackInputFile,
+ dvrConfig.settings.playback());
+ if (!result) {
+ ALOGW("[vts] Software frontend dvr configure failed.");
+ return failure();
+ }
+ }
mFrontendCallback->tuneTestOnLock(mFrontend, config.settings);
return AssertionResult(true);
}
-AssertionResult FrontendTests::stopTuneFrontend() {
+AssertionResult FrontendTests::setLnb(uint32_t lnbId) {
+ if (!mFrontendCallback) {
+ ALOGW("[vts] open and set frontend callback first.");
+ return failure();
+ }
+ return AssertionResult(mFrontend->setLnb(lnbId) == Result::SUCCESS);
+}
+
+AssertionResult FrontendTests::stopTuneFrontend(bool testWithDemux) {
EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
Result status;
status = mFrontend->stopTune();
+ if (mIsSoftwareFe && testWithDemux) {
+ mDvrTests.stopPlaybackThread();
+ mDvrTests.closeDvrPlayback();
+ }
return AssertionResult(status == Result::SUCCESS);
}
@@ -407,9 +434,9 @@
ASSERT_TRUE(feId != INVALID_ID);
ASSERT_TRUE(openFrontendById(feId));
ASSERT_TRUE(setFrontendCallback());
- ASSERT_TRUE(tuneFrontend(frontendConf));
+ ASSERT_TRUE(tuneFrontend(frontendConf, false /*testWithDemux*/));
verifyFrontendStatus(frontendConf.tuneStatusTypes, frontendConf.expectTuneStatuses);
- ASSERT_TRUE(stopTuneFrontend());
+ ASSERT_TRUE(stopTuneFrontend(false /*testWithDemux*/));
ASSERT_TRUE(closeFrontend());
}
diff --git a/tv/tuner/1.0/vts/functional/FrontendTests.h b/tv/tuner/1.0/vts/functional/FrontendTests.h
index 2bdc8fd..c536325 100644
--- a/tv/tuner/1.0/vts/functional/FrontendTests.h
+++ b/tv/tuner/1.0/vts/functional/FrontendTests.h
@@ -31,6 +31,7 @@
#include <utils/Mutex.h>
#include <map>
+#include "DvrTests.h"
#include "VtsHalTvTunerV1_0TestConfigurations.h"
#define WAIT_TIMEOUT 3000000000
@@ -100,7 +101,10 @@
public:
sp<ITuner> mService;
- void setService(sp<ITuner> tuner) { mService = tuner; }
+ void setService(sp<ITuner> tuner) {
+ mService = tuner;
+ mDvrTests.setService(tuner);
+ }
AssertionResult getFrontendIds();
AssertionResult getFrontendInfo(uint32_t frontendId);
@@ -108,19 +112,43 @@
AssertionResult setFrontendCallback();
AssertionResult scanFrontend(FrontendConfig config, FrontendScanType type);
AssertionResult stopScanFrontend();
- AssertionResult tuneFrontend(FrontendConfig config);
+ AssertionResult tuneFrontend(FrontendConfig config, bool testWithDemux);
+ AssertionResult setLnb(uint32_t lnbId);
void verifyFrontendStatus(vector<FrontendStatusType> statusTypes,
vector<FrontendStatus> expectStatuses);
- AssertionResult stopTuneFrontend();
+ AssertionResult stopTuneFrontend(bool testWithDemux);
AssertionResult closeFrontend();
void getFrontendIdByType(FrontendType feType, uint32_t& feId);
void tuneTest(FrontendConfig frontendConf);
void scanTest(FrontendConfig frontend, FrontendScanType type);
+ void setDvrTests(DvrTests dvrTests) { mDvrTests = dvrTests; }
+ void setDemux(sp<IDemux> demux) { mDvrTests.setDemux(demux); }
+
protected:
+ static AssertionResult failure() { return ::testing::AssertionFailure(); }
+ static AssertionResult success() { return ::testing::AssertionSuccess(); }
+
+ void getSoftwareFrontendPlaybackConfig(DvrConfig& dvrConfig) {
+ PlaybackSettings playbackSettings{
+ .statusMask = 0xf,
+ .lowThreshold = 0x1000,
+ .highThreshold = 0x07fff,
+ .dataFormat = DataFormat::TS,
+ .packetSize = 188,
+ };
+ dvrConfig.type = DvrType::PLAYBACK;
+ dvrConfig.playbackInputFile = "/data/local/tmp/segment000000.ts";
+ dvrConfig.bufferSize = FMQ_SIZE_4M;
+ dvrConfig.settings.playback(playbackSettings);
+ }
+
sp<IFrontend> mFrontend;
FrontendInfo mFrontendInfo;
sp<FrontendCallback> mFrontendCallback;
hidl_vec<FrontendId> mFeIds;
+
+ DvrTests mDvrTests;
+ bool mIsSoftwareFe = false;
};
diff --git a/tv/tuner/1.0/vts/functional/LnbTests.cpp b/tv/tuner/1.0/vts/functional/LnbTests.cpp
new file mode 100644
index 0000000..9080f59
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/LnbTests.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright 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 "LnbTests.h"
+
+Return<void> LnbCallback::onEvent(LnbEventType lnbEventType) {
+ android::Mutex::Autolock autoLock(mMsgLock);
+ ALOGD("[vts] lnb event received. Type: %d", lnbEventType);
+ mEventReceived = true;
+ mMsgCondition.signal();
+ return Void();
+}
+
+Return<void> LnbCallback::onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage) {
+ string msg(diseqcMessage.begin(), diseqcMessage.end());
+ ALOGD("[vts] onDiseqcMessage %s", msg.c_str());
+ return Void();
+}
+
+AssertionResult LnbTests::getLnbIds(vector<uint32_t>& ids) {
+ Result status;
+ mService->getLnbIds([&](Result result, const hidl_vec<uint32_t>& lnbIds) {
+ status = result;
+ ids = lnbIds;
+ });
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult LnbTests::openLnbById(uint32_t lnbId) {
+ Result status;
+ mService->openLnbById(lnbId, [&](Result result, const sp<ILnb>& lnb) {
+ mLnb = lnb;
+ status = result;
+ });
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult LnbTests::openLnbByName(string lnbName) {
+ Result status;
+ mService->openLnbByName(lnbName, [&](Result result, uint32_t /*lnbId*/, const sp<ILnb>& lnb) {
+ mLnb = lnb;
+ status = result;
+ });
+
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult LnbTests::setLnbCallback() {
+ if (!mLnb) {
+ ALOGW("[vts] Open Lnb first");
+ return failure();
+ }
+ mLnbCallback = new LnbCallback();
+ auto callbackStatus = mLnb->setCallback(mLnbCallback);
+ return AssertionResult(callbackStatus.isOk());
+}
+
+AssertionResult LnbTests::setVoltage(LnbVoltage voltage) {
+ if (!mLnb) {
+ ALOGW("[vts] Open Lnb first");
+ return failure();
+ }
+ Result status = mLnb->setVoltage(voltage);
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult LnbTests::setTone(LnbTone tone) {
+ if (!mLnb) {
+ ALOGW("[vts] Open Lnb first");
+ return failure();
+ }
+ Result status = mLnb->setTone(tone);
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult LnbTests::setSatellitePosition(LnbPosition position) {
+ if (!mLnb) {
+ ALOGW("[vts] Open Lnb first");
+ return failure();
+ }
+ Result status = mLnb->setSatellitePosition(position);
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult LnbTests::sendDiseqcMessage(vector<uint8_t> diseqcMsg) {
+ if (!mLnb) {
+ ALOGW("[vts] Open Lnb first");
+ return failure();
+ }
+ Result status = mLnb->sendDiseqcMessage(diseqcMsg);
+ return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult LnbTests::closeLnb() {
+ if (!mLnb) {
+ ALOGW("[vts] Open Lnb first");
+ return failure();
+ }
+ Result status = mLnb->close();
+ mLnb = nullptr;
+ mLnbCallback = nullptr;
+ return AssertionResult(status == Result::SUCCESS);
+}
diff --git a/tv/tuner/1.0/vts/functional/LnbTests.h b/tv/tuner/1.0/vts/functional/LnbTests.h
new file mode 100644
index 0000000..2fdbe2c
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/LnbTests.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright 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 <android-base/logging.h>
+#include <android/hardware/tv/tuner/1.0/ILnb.h>
+#include <android/hardware/tv/tuner/1.0/ITuner.h>
+#include <android/hardware/tv/tuner/1.0/types.h>
+#include <gtest/gtest.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/ServiceManagement.h>
+#include <hidl/Status.h>
+#include <hidlmemory/FrameworkUtils.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <map>
+
+using android::Condition;
+using android::Mutex;
+using android::sp;
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::tv::tuner::V1_0::ILnb;
+using android::hardware::tv::tuner::V1_0::ILnbCallback;
+using android::hardware::tv::tuner::V1_0::ITuner;
+using android::hardware::tv::tuner::V1_0::LnbEventType;
+using android::hardware::tv::tuner::V1_0::LnbPosition;
+using android::hardware::tv::tuner::V1_0::LnbTone;
+using android::hardware::tv::tuner::V1_0::LnbVoltage;
+using android::hardware::tv::tuner::V1_0::Result;
+
+using ::testing::AssertionResult;
+
+using namespace std;
+
+class LnbCallback : public ILnbCallback {
+ public:
+ virtual Return<void> onEvent(LnbEventType lnbEventType) override;
+ virtual Return<void> onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage) override;
+
+ private:
+ bool mEventReceived = false;
+ android::Mutex mMsgLock;
+ android::Condition mMsgCondition;
+};
+
+class LnbTests {
+ public:
+ void setService(sp<ITuner> tuner) { mService = tuner; }
+
+ AssertionResult getLnbIds(vector<uint32_t>& ids);
+ AssertionResult openLnbById(uint32_t lnbId);
+ AssertionResult openLnbByName(string lnbName);
+ AssertionResult setLnbCallback();
+ AssertionResult setVoltage(LnbVoltage voltage);
+ AssertionResult setTone(LnbTone tone);
+ AssertionResult setSatellitePosition(LnbPosition position);
+ AssertionResult sendDiseqcMessage(vector<uint8_t> diseqcMsg);
+ AssertionResult closeLnb();
+
+ protected:
+ static AssertionResult failure() { return ::testing::AssertionFailure(); }
+
+ static AssertionResult success() { return ::testing::AssertionSuccess(); }
+
+ sp<ITuner> mService;
+ sp<ILnb> mLnb;
+ sp<LnbCallback> mLnbCallback;
+ hidl_vec<uint32_t> mLnbIds;
+};
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
index a365282..6819659 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
@@ -56,6 +56,23 @@
ASSERT_TRUE(mFrontendTests.closeFrontend());
}
+void TunerFilterHidlTest::testTimeFilter(TimeFilterConfig filterConf) {
+ if (!filterConf.supportTimeFilter) {
+ return;
+ }
+ uint32_t demuxId;
+ sp<IDemux> demux;
+
+ ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+ mFilterTests.setDemux(demux);
+ ASSERT_TRUE(mFilterTests.openTimeFilterInDemux());
+ ASSERT_TRUE(mFilterTests.setTimeStamp(filterConf.timeStamp));
+ ASSERT_TRUE(mFilterTests.getTimeStamp());
+ ASSERT_TRUE(mFilterTests.clearTimeStamp());
+ ASSERT_TRUE(mFilterTests.closeTimeFilter());
+ ASSERT_TRUE(mDemuxTests.closeDemux());
+}
+
void TunerBroadcastHidlTest::broadcastSingleFilterTest(FilterConfig filterConf,
FrontendConfig frontendConf) {
uint32_t feId;
@@ -72,8 +89,12 @@
}
ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+ if (mLnbId) {
+ ASSERT_TRUE(mFrontendTests.setLnb(*mLnbId));
+ }
ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+ mFrontendTests.setDemux(demux);
mFilterTests.setDemux(demux);
ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
@@ -81,15 +102,35 @@
ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
ASSERT_TRUE(mFilterTests.startFilter(filterId));
// tune test
- ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf));
+ ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
ASSERT_TRUE(filterDataOutputTest(goldenOutputFiles));
- ASSERT_TRUE(mFrontendTests.stopTuneFrontend());
+ ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
ASSERT_TRUE(mFilterTests.stopFilter(filterId));
ASSERT_TRUE(mFilterTests.closeFilter(filterId));
ASSERT_TRUE(mDemuxTests.closeDemux());
ASSERT_TRUE(mFrontendTests.closeFrontend());
}
+void TunerBroadcastHidlTest::broadcastSingleFilterTestWithLnb(FilterConfig filterConf,
+ FrontendConfig frontendConf,
+ LnbConfig lnbConf) {
+ vector<uint32_t> ids;
+ ASSERT_TRUE(mLnbTests.getLnbIds(ids));
+ if (!lnbConf.usingLnb) {
+ return;
+ }
+ ASSERT_TRUE(ids.size() > 0);
+ ASSERT_TRUE(mLnbTests.openLnbById(ids[0]));
+ *mLnbId = ids[0];
+ ASSERT_TRUE(mLnbTests.setLnbCallback());
+ ASSERT_TRUE(mLnbTests.setVoltage(lnbConf.voltage));
+ ASSERT_TRUE(mLnbTests.setTone(lnbConf.tone));
+ ASSERT_TRUE(mLnbTests.setSatellitePosition(lnbConf.position));
+ broadcastSingleFilterTest(filterConf, frontendConf);
+ ASSERT_TRUE(mLnbTests.closeLnb());
+ mLnbId = nullptr;
+}
+
void TunerPlaybackHidlTest::playbackSingleFilterTest(FilterConfig filterConf, DvrConfig dvrConf) {
uint32_t demuxId;
sp<IDemux> demux;
@@ -99,21 +140,21 @@
mFilterTests.setDemux(demux);
mDvrTests.setDemux(demux);
ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrConf.type, dvrConf.bufferSize));
- ASSERT_TRUE(mDvrTests.configDvr(dvrConf.settings));
- ASSERT_TRUE(mDvrTests.getDvrMQDescriptor());
+ ASSERT_TRUE(mDvrTests.configDvrPlayback(dvrConf.settings));
+ ASSERT_TRUE(mDvrTests.getDvrPlaybackMQDescriptor());
ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
mDvrTests.startPlaybackInputThread(dvrConf.playbackInputFile, dvrConf.settings.playback());
- ASSERT_TRUE(mDvrTests.startDvr());
+ ASSERT_TRUE(mDvrTests.startDvrPlayback());
ASSERT_TRUE(mFilterTests.startFilter(filterId));
ASSERT_TRUE(filterDataOutputTest(goldenOutputFiles));
mDvrTests.stopPlaybackThread();
ASSERT_TRUE(mFilterTests.stopFilter(filterId));
- ASSERT_TRUE(mDvrTests.stopDvr());
+ ASSERT_TRUE(mDvrTests.stopDvrPlayback());
ASSERT_TRUE(mFilterTests.closeFilter(filterId));
- mDvrTests.closeDvr();
+ mDvrTests.closeDvrPlayback();
ASSERT_TRUE(mDemuxTests.closeDemux());
}
@@ -129,13 +170,17 @@
ASSERT_TRUE(feId != INVALID_ID);
ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+ if (mLnbId) {
+ ASSERT_TRUE(mFrontendTests.setLnb(*mLnbId));
+ }
ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
mFilterTests.setDemux(demux);
mDvrTests.setDemux(demux);
+ mFrontendTests.setDvrTests(mDvrTests);
ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrConf.type, dvrConf.bufferSize));
- ASSERT_TRUE(mDvrTests.configDvr(dvrConf.settings));
- ASSERT_TRUE(mDvrTests.getDvrMQDescriptor());
+ ASSERT_TRUE(mDvrTests.configDvrRecord(dvrConf.settings));
+ ASSERT_TRUE(mDvrTests.getDvrRecordMQDescriptor());
ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
@@ -144,21 +189,41 @@
ASSERT_TRUE(filter != nullptr);
mDvrTests.startRecordOutputThread(dvrConf.settings.record());
ASSERT_TRUE(mDvrTests.attachFilterToDvr(filter));
- ASSERT_TRUE(mDvrTests.startDvr());
+ ASSERT_TRUE(mDvrTests.startDvrRecord());
ASSERT_TRUE(mFilterTests.startFilter(filterId));
- ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf));
+ ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
mDvrTests.testRecordOutput();
mDvrTests.stopRecordThread();
- ASSERT_TRUE(mFrontendTests.stopTuneFrontend());
+ ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
ASSERT_TRUE(mFilterTests.stopFilter(filterId));
- ASSERT_TRUE(mDvrTests.stopDvr());
+ ASSERT_TRUE(mDvrTests.stopDvrRecord());
ASSERT_TRUE(mDvrTests.detachFilterToDvr(filter));
ASSERT_TRUE(mFilterTests.closeFilter(filterId));
- mDvrTests.closeDvr();
+ mDvrTests.closeDvrRecord();
ASSERT_TRUE(mDemuxTests.closeDemux());
ASSERT_TRUE(mFrontendTests.closeFrontend());
}
+void TunerRecordHidlTest::recordSingleFilterTestWithLnb(FilterConfig filterConf,
+ FrontendConfig frontendConf,
+ DvrConfig dvrConf, LnbConfig lnbConf) {
+ vector<uint32_t> ids;
+ ASSERT_TRUE(mLnbTests.getLnbIds(ids));
+ if (!lnbConf.usingLnb) {
+ return;
+ }
+ ASSERT_TRUE(ids.size() > 0);
+ ASSERT_TRUE(mLnbTests.openLnbById(ids[0]));
+ *mLnbId = ids[0];
+ ASSERT_TRUE(mLnbTests.setLnbCallback());
+ ASSERT_TRUE(mLnbTests.setVoltage(lnbConf.voltage));
+ ASSERT_TRUE(mLnbTests.setTone(lnbConf.tone));
+ ASSERT_TRUE(mLnbTests.setSatellitePosition(lnbConf.position));
+ recordSingleFilterTest(filterConf, frontendConf, dvrConf);
+ ASSERT_TRUE(mLnbTests.closeLnb());
+ mLnbId = nullptr;
+}
+
void TunerRecordHidlTest::attachSingleFilterToRecordDvrTest(FilterConfig filterConf,
FrontendConfig frontendConf,
DvrConfig dvrConf) {
@@ -177,8 +242,8 @@
mFilterTests.setDemux(demux);
mDvrTests.setDemux(demux);
ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrConf.type, dvrConf.bufferSize));
- ASSERT_TRUE(mDvrTests.configDvr(dvrConf.settings));
- ASSERT_TRUE(mDvrTests.getDvrMQDescriptor());
+ ASSERT_TRUE(mDvrTests.configDvrRecord(dvrConf.settings));
+ ASSERT_TRUE(mDvrTests.getDvrRecordMQDescriptor());
ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
@@ -186,13 +251,13 @@
filter = mFilterTests.getFilterById(filterId);
ASSERT_TRUE(filter != nullptr);
ASSERT_TRUE(mDvrTests.attachFilterToDvr(filter));
- ASSERT_TRUE(mDvrTests.startDvr());
+ ASSERT_TRUE(mDvrTests.startDvrRecord());
ASSERT_TRUE(mFilterTests.startFilter(filterId));
ASSERT_TRUE(mFilterTests.stopFilter(filterId));
- ASSERT_TRUE(mDvrTests.stopDvr());
+ ASSERT_TRUE(mDvrTests.stopDvrRecord());
ASSERT_TRUE(mDvrTests.detachFilterToDvr(filter));
ASSERT_TRUE(mFilterTests.closeFilter(filterId));
- mDvrTests.closeDvr();
+ mDvrTests.closeDvrRecord();
ASSERT_TRUE(mDemuxTests.closeDemux());
ASSERT_TRUE(mFrontendTests.closeFrontend());
}
@@ -220,6 +285,7 @@
ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
mFilterTests.setDemux(demux);
+ mFrontendTests.setDemux(demux);
for (config = mediaFilterConfs.begin(); config != mediaFilterConfs.end(); config++) {
ASSERT_TRUE(mFilterTests.openFilterInDemux((*config).type, (*config).bufferSize));
ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
@@ -243,9 +309,9 @@
ASSERT_TRUE(mFilterTests.startFilter(*id));
}
// tune test
- ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf));
+ ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
ASSERT_TRUE(filterDataOutputTest(goldenOutputFiles));
- ASSERT_TRUE(mFrontendTests.stopTuneFrontend());
+ ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
for (id = filterIds.begin(); id != filterIds.end(); id++) {
ASSERT_TRUE(mFilterTests.stopFilter(*id));
}
@@ -275,6 +341,34 @@
mFrontendTests.scanTest(frontendScanArray[SCAN_DVBT], FrontendScanType::SCAN_BLIND);
}
+TEST_P(TunerLnbHidlTest, OpenLnbByName) {
+ description("Open and configure an Lnb with name then send a diseqc msg to it.");
+ ASSERT_TRUE(mLnbTests.openLnbByName(lnbArray[LNB_EXTERNAL].name));
+ ASSERT_TRUE(mLnbTests.setLnbCallback());
+ ASSERT_TRUE(mLnbTests.setVoltage(lnbArray[LNB_EXTERNAL].voltage));
+ ASSERT_TRUE(mLnbTests.setTone(lnbArray[LNB_EXTERNAL].tone));
+ ASSERT_TRUE(mLnbTests.setSatellitePosition(lnbArray[LNB_EXTERNAL].position));
+ ASSERT_TRUE(mLnbTests.sendDiseqcMessage(diseqcMsgArray[DISEQC_POWER_ON]));
+ ASSERT_TRUE(mLnbTests.closeLnb());
+}
+
+TEST_P(TunerLnbHidlTest, SendDiseqcMessageToLnb) {
+ description("Open and configure an Lnb with specific settings then send a diseqc msg to it.");
+ vector<uint32_t> ids;
+ ASSERT_TRUE(mLnbTests.getLnbIds(ids));
+ if (!lnbArray[LNB0].usingLnb) {
+ return;
+ }
+ ASSERT_TRUE(ids.size() > 0);
+ ASSERT_TRUE(mLnbTests.openLnbById(ids[0]));
+ ASSERT_TRUE(mLnbTests.setLnbCallback());
+ ASSERT_TRUE(mLnbTests.setVoltage(lnbArray[LNB0].voltage));
+ ASSERT_TRUE(mLnbTests.setTone(lnbArray[LNB0].tone));
+ ASSERT_TRUE(mLnbTests.setSatellitePosition(lnbArray[LNB0].position));
+ ASSERT_TRUE(mLnbTests.sendDiseqcMessage(diseqcMsgArray[DISEQC_POWER_ON]));
+ ASSERT_TRUE(mLnbTests.closeLnb());
+}
+
TEST_P(TunerDemuxHidlTest, openDemux) {
description("Open and close a Demux.");
uint32_t feId;
@@ -331,23 +425,64 @@
configSingleFilterInDemuxTest(filterArray[TS_VIDEO0], frontendArray[DVBT]);
}
+TEST_P(TunerFilterHidlTest, SetFilterLinkage) {
+ description("Pick up all the possible linkages from the demux caps and set them up.");
+ DemuxCapabilities caps;
+ uint32_t demuxId;
+ sp<IDemux> demux;
+ ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+ ASSERT_TRUE(mDemuxTests.getDemuxCaps(caps));
+ mFilterTests.setDemux(demux);
+ for (int i = 0; i < caps.linkCaps.size(); i++) {
+ uint32_t bitMask = 1;
+ for (int j = 0; j < FILTER_MAIN_TYPE_BIT_COUNT; j++) {
+ if (caps.linkCaps[i] & (bitMask << j)) {
+ uint32_t sourceFilterId;
+ uint32_t sinkFilterId;
+ ASSERT_TRUE(mFilterTests.openFilterInDemux(filterLinkageTypes[SOURCE][i],
+ FMQ_SIZE_16M));
+ ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(sourceFilterId));
+ ASSERT_TRUE(
+ mFilterTests.openFilterInDemux(filterLinkageTypes[SINK][j], FMQ_SIZE_16M));
+ ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(sinkFilterId));
+ ASSERT_TRUE(mFilterTests.setFilterDataSource(sourceFilterId, sinkFilterId));
+ ASSERT_TRUE(mFilterTests.setFilterDataSourceToDemux(sinkFilterId));
+ ASSERT_TRUE(mFilterTests.closeFilter(sinkFilterId));
+ ASSERT_TRUE(mFilterTests.closeFilter(sourceFilterId));
+ }
+ }
+ }
+ ASSERT_TRUE(mDemuxTests.closeDemux());
+}
+
+TEST_P(TunerFilterHidlTest, testTimeFilter) {
+ description("Open a timer filter in Demux and set time stamp.");
+ // TODO use paramterized tests
+ testTimeFilter(timeFilterArray[TIMER0]);
+}
+
TEST_P(TunerBroadcastHidlTest, BroadcastDataFlowVideoFilterTest) {
description("Test Video Filter functionality in Broadcast use case.");
- broadcastSingleFilterTest(filterArray[TS_VIDEO1], frontendArray[DVBS]);
+ broadcastSingleFilterTest(filterArray[TS_VIDEO1], frontendArray[DVBT]);
}
TEST_P(TunerBroadcastHidlTest, BroadcastDataFlowAudioFilterTest) {
description("Test Audio Filter functionality in Broadcast use case.");
- broadcastSingleFilterTest(filterArray[TS_AUDIO0], frontendArray[DVBS]);
+ broadcastSingleFilterTest(filterArray[TS_AUDIO0], frontendArray[DVBT]);
}
TEST_P(TunerBroadcastHidlTest, BroadcastDataFlowSectionFilterTest) {
description("Test Section Filter functionality in Broadcast use case.");
- broadcastSingleFilterTest(filterArray[TS_SECTION0], frontendArray[DVBS]);
+ broadcastSingleFilterTest(filterArray[TS_SECTION0], frontendArray[DVBT]);
}
TEST_P(TunerBroadcastHidlTest, IonBufferTest) {
description("Test the av filter data bufferring.");
+ broadcastSingleFilterTest(filterArray[TS_VIDEO0], frontendArray[DVBT]);
+}
+
+TEST_P(TunerBroadcastHidlTest, LnbBroadcastDataFlowVideoFilterTest) {
+ description("Test Video Filter functionality in Broadcast with Lnb use case.");
broadcastSingleFilterTest(filterArray[TS_VIDEO0], frontendArray[DVBS]);
}
@@ -368,6 +503,11 @@
recordSingleFilterTest(filterArray[TS_RECORD0], frontendArray[DVBT], dvrArray[DVR_RECORD0]);
}
+TEST_P(TunerRecordHidlTest, LnbRecordDataFlowWithTsRecordFilterTest) {
+ description("Feed ts data from Fe with Lnb to recording and test with ts record filter");
+ recordSingleFilterTest(filterArray[TS_RECORD0], frontendArray[DVBS], dvrArray[DVR_RECORD0]);
+}
+
TEST_P(TunerDescramblerHidlTest, CreateDescrambler) {
description("Create Descrambler");
uint32_t feId;
@@ -393,12 +533,17 @@
scrambledBroadcastTest(filterConfs, frontendArray[DVBT], descramblerArray[DESC_0]);
}
-/*INSTANTIATE_TEST_SUITE_P(
+INSTANTIATE_TEST_SUITE_P(
PerInstance, TunerFrontendHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
android::hardware::PrintInstanceNameToString);
INSTANTIATE_TEST_SUITE_P(
+ PerInstance, TunerLnbHidlTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
+ android::hardware::PrintInstanceNameToString);
+
+INSTANTIATE_TEST_SUITE_P(
PerInstance, TunerDemuxHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
android::hardware::PrintInstanceNameToString);
@@ -421,7 +566,7 @@
INSTANTIATE_TEST_SUITE_P(
PerInstance, TunerRecordHidlTest,
testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
- android::hardware::PrintInstanceNameToString);*/
+ android::hardware::PrintInstanceNameToString);
INSTANTIATE_TEST_SUITE_P(
PerInstance, TunerDescramblerHidlTest,
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
index 2bdb537..6804f3c 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
@@ -16,8 +16,8 @@
#include "DemuxTests.h"
#include "DescramblerTests.h"
-#include "DvrTests.h"
#include "FrontendTests.h"
+#include "LnbTests.h"
using android::hardware::tv::tuner::V1_0::DataFormat;
using android::hardware::tv::tuner::V1_0::IDescrambler;
@@ -31,7 +31,9 @@
void initConfiguration() {
initFrontendConfig();
initFrontendScanConfig();
+ initLnbConfig();
initFilterConfig();
+ initTimeFilterConfig();
initDvrConfig();
initDescramblerConfig();
}
@@ -65,6 +67,25 @@
FrontendTests mFrontendTests;
};
+class TunerLnbHidlTest : public testing::TestWithParam<std::string> {
+ public:
+ virtual void SetUp() override {
+ mService = ITuner::getService(GetParam());
+ ASSERT_NE(mService, nullptr);
+ initConfiguration();
+
+ mLnbTests.setService(mService);
+ }
+
+ protected:
+ static void description(const std::string& description) {
+ RecordProperty("description", description);
+ }
+
+ sp<ITuner> mService;
+ LnbTests mLnbTests;
+};
+
class TunerDemuxHidlTest : public testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
@@ -106,6 +127,7 @@
}
void configSingleFilterInDemuxTest(FilterConfig filterConf, FrontendConfig frontendConf);
+ void testTimeFilter(TimeFilterConfig filterConf);
sp<ITuner> mService;
FrontendTests mFrontendTests;
@@ -123,6 +145,8 @@
mFrontendTests.setService(mService);
mDemuxTests.setService(mService);
mFilterTests.setService(mService);
+ mLnbTests.setService(mService);
+ mDvrTests.setService(mService);
}
protected:
@@ -134,10 +158,17 @@
FrontendTests mFrontendTests;
DemuxTests mDemuxTests;
FilterTests mFilterTests;
+ LnbTests mLnbTests;
+ DvrTests mDvrTests;
AssertionResult filterDataOutputTest(vector<string> goldenOutputFiles);
void broadcastSingleFilterTest(FilterConfig filterConf, FrontendConfig frontendConf);
+ void broadcastSingleFilterTestWithLnb(FilterConfig filterConf, FrontendConfig frontendConf,
+ LnbConfig lnbConf);
+
+ private:
+ uint32_t* mLnbId = nullptr;
};
class TunerPlaybackHidlTest : public testing::TestWithParam<std::string> {
@@ -180,6 +211,7 @@
mDemuxTests.setService(mService);
mFilterTests.setService(mService);
mDvrTests.setService(mService);
+ mLnbTests.setService(mService);
}
protected:
@@ -191,12 +223,18 @@
DvrConfig dvrConf);
void recordSingleFilterTest(FilterConfig filterConf, FrontendConfig frontendConf,
DvrConfig dvrConf);
+ void recordSingleFilterTestWithLnb(FilterConfig filterConf, FrontendConfig frontendConf,
+ DvrConfig dvrConf, LnbConfig lnbConf);
sp<ITuner> mService;
FrontendTests mFrontendTests;
DemuxTests mDemuxTests;
FilterTests mFilterTests;
DvrTests mDvrTests;
+ LnbTests mLnbTests;
+
+ private:
+ uint32_t* mLnbId = nullptr;
};
class TunerDescramblerHidlTest : public testing::TestWithParam<std::string> {
@@ -210,6 +248,7 @@
mFrontendTests.setService(mService);
mDemuxTests.setService(mService);
+ mDvrTests.setService(mService);
mDescramblerTests.setService(mService);
mDescramblerTests.setCasService(mCasService);
}
@@ -229,5 +268,6 @@
DemuxTests mDemuxTests;
FilterTests mFilterTests;
DescramblerTests mDescramblerTests;
+ DvrTests mDvrTests;
};
} // namespace
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
index f2dd197..6c68e35 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
@@ -22,11 +22,15 @@
#include <hidlmemory/FrameworkUtils.h>
using android::hardware::tv::tuner::V1_0::DataFormat;
+using android::hardware::tv::tuner::V1_0::DemuxAlpFilterType;
using android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
using android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
using android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
using android::hardware::tv::tuner::V1_0::DemuxFilterType;
+using android::hardware::tv::tuner::V1_0::DemuxIpFilterType;
+using android::hardware::tv::tuner::V1_0::DemuxMmtpFilterType;
using android::hardware::tv::tuner::V1_0::DemuxRecordScIndexType;
+using android::hardware::tv::tuner::V1_0::DemuxTlvFilterType;
using android::hardware::tv::tuner::V1_0::DemuxTpid;
using android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
using android::hardware::tv::tuner::V1_0::DvrSettings;
@@ -43,6 +47,9 @@
using android::hardware::tv::tuner::V1_0::FrontendStatus;
using android::hardware::tv::tuner::V1_0::FrontendStatusType;
using android::hardware::tv::tuner::V1_0::FrontendType;
+using android::hardware::tv::tuner::V1_0::LnbPosition;
+using android::hardware::tv::tuner::V1_0::LnbTone;
+using android::hardware::tv::tuner::V1_0::LnbVoltage;
using android::hardware::tv::tuner::V1_0::PlaybackSettings;
using android::hardware::tv::tuner::V1_0::RecordSettings;
@@ -53,6 +60,7 @@
const uint32_t FMQ_SIZE_16M = 0x1000000;
#define CLEAR_KEY_SYSTEM_ID 0xF6D8
+#define FILTER_MAIN_TYPE_BIT_COUNT 32
#define PROVISION_STR \
"{ " \
" \"id\": 21140844, " \
@@ -78,12 +86,34 @@
} Filter;
typedef enum {
+ TIMER0,
+ TIMER_MAX,
+} TimeFilter;
+
+typedef enum {
+ SOURCE,
+ SINK,
+ LINKAGE_DIR,
+} Linkage;
+
+typedef enum {
DVBT,
DVBS,
FRONTEND_MAX,
} Frontend;
typedef enum {
+ LNB0,
+ LNB_EXTERNAL,
+ LNB_MAX,
+} Lnb;
+
+typedef enum {
+ DISEQC_POWER_ON,
+ DISEQC_MAX,
+} Diseqc;
+
+typedef enum {
SCAN_DVBT,
SCAN_MAX,
} FrontendScan;
@@ -91,6 +121,7 @@
typedef enum {
DVR_RECORD0,
DVR_PLAYBACK0,
+ DVR_SOFTWARE_FE,
DVR_MAX,
} Dvr;
@@ -107,13 +138,27 @@
bool operator<(const FilterConfig& /*c*/) const { return false; }
};
+struct TimeFilterConfig {
+ bool supportTimeFilter;
+ uint64_t timeStamp;
+};
+
struct FrontendConfig {
+ bool isSoftwareFe;
FrontendType type;
FrontendSettings settings;
vector<FrontendStatusType> tuneStatusTypes;
vector<FrontendStatus> expectTuneStatuses;
};
+struct LnbConfig {
+ bool usingLnb;
+ string name;
+ LnbVoltage voltage;
+ LnbTone tone;
+ LnbPosition position;
+};
+
struct ChannelConfig {
int32_t frontendId;
int32_t channelId;
@@ -137,8 +182,12 @@
static FrontendConfig frontendArray[FILTER_MAX];
static FrontendConfig frontendScanArray[SCAN_MAX];
+static LnbConfig lnbArray[LNB_MAX];
+static vector<uint8_t> diseqcMsgArray[DISEQC_MAX];
static ChannelConfig channelArray[FRONTEND_MAX];
static FilterConfig filterArray[FILTER_MAX];
+static TimeFilterConfig timeFilterArray[TIMER_MAX];
+static DemuxFilterType filterLinkageTypes[LINKAGE_DIR][FILTER_MAIN_TYPE_BIT_COUNT];
static DvrConfig dvrArray[DVR_MAX];
static DescramblerConfig descramblerArray[DESC_MAX];
static vector<string> goldenOutputFiles;
@@ -166,7 +215,9 @@
statuses.push_back(status);
frontendArray[DVBT].tuneStatusTypes = types;
frontendArray[DVBT].expectTuneStatuses = statuses;
+ frontendArray[DVBT].isSoftwareFe = true;
frontendArray[DVBS].type = FrontendType::DVBS;
+ frontendArray[DVBS].isSoftwareFe = true;
};
/** Configuration array for the frontend scan test */
@@ -186,6 +237,24 @@
});
};
+/** Configuration array for the Lnb test */
+inline void initLnbConfig() {
+ lnbArray[LNB0].usingLnb = true;
+ lnbArray[LNB0].voltage = LnbVoltage::VOLTAGE_12V;
+ lnbArray[LNB0].tone = LnbTone::NONE;
+ lnbArray[LNB0].position = LnbPosition::UNDEFINED;
+ lnbArray[LNB_EXTERNAL].usingLnb = true;
+ lnbArray[LNB_EXTERNAL].name = "default_lnb_external";
+ lnbArray[LNB_EXTERNAL].voltage = LnbVoltage::VOLTAGE_5V;
+ lnbArray[LNB_EXTERNAL].tone = LnbTone::NONE;
+ lnbArray[LNB_EXTERNAL].position = LnbPosition::UNDEFINED;
+};
+
+/** Diseqc messages array for the Lnb test */
+inline void initDiseqcMsg() {
+ diseqcMsgArray[DISEQC_POWER_ON] = {0xE, 0x0, 0x0, 0x0, 0x0, 0x3};
+};
+
/** Configuration array for the filter test */
inline void initFilterConfig() {
// TS VIDEO filter setting for default implementation testing
@@ -241,8 +310,35 @@
filterArray[TS_RECORD0].settings.ts().filterSettings.record({
.scIndexType = DemuxRecordScIndexType::NONE,
});
+
+ // TS Linkage filter setting
+ filterLinkageTypes[SOURCE][0].mainType = DemuxFilterMainType::TS;
+ filterLinkageTypes[SOURCE][0].subType.tsFilterType(DemuxTsFilterType::TS);
+ filterLinkageTypes[SINK][0] = filterLinkageTypes[SOURCE][0];
+ // MMTP Linkage filter setting
+ filterLinkageTypes[SOURCE][1].mainType = DemuxFilterMainType::MMTP;
+ filterLinkageTypes[SOURCE][1].subType.mmtpFilterType(DemuxMmtpFilterType::AUDIO);
+ filterLinkageTypes[SINK][1] = filterLinkageTypes[SOURCE][1];
+ // IP Linkage filter setting
+ filterLinkageTypes[SOURCE][2].mainType = DemuxFilterMainType::IP;
+ filterLinkageTypes[SOURCE][2].subType.ipFilterType(DemuxIpFilterType::IP);
+ filterLinkageTypes[SINK][2] = filterLinkageTypes[SOURCE][2];
+ // TLV Linkage filter setting
+ filterLinkageTypes[SOURCE][3].mainType = DemuxFilterMainType::TLV;
+ filterLinkageTypes[SOURCE][3].subType.tlvFilterType(DemuxTlvFilterType::TLV);
+ filterLinkageTypes[SINK][3] = filterLinkageTypes[SOURCE][3];
+ // ALP Linkage PTP filter setting
+ filterLinkageTypes[SOURCE][4].mainType = DemuxFilterMainType::ALP;
+ filterLinkageTypes[SOURCE][4].subType.alpFilterType(DemuxAlpFilterType::PTP);
+ filterLinkageTypes[SINK][4] = filterLinkageTypes[SOURCE][4];
};
+/** Configuration array for the timer filter test */
+inline void initTimeFilterConfig() {
+ timeFilterArray[TIMER0].supportTimeFilter = true;
+ timeFilterArray[TIMER0].timeStamp = 1;
+}
+
/** Configuration array for the dvr test */
inline void initDvrConfig() {
RecordSettings recordSettings{
@@ -263,9 +359,20 @@
.packetSize = 188,
};
dvrArray[DVR_PLAYBACK0].type = DvrType::PLAYBACK;
- dvrArray[DVR_PLAYBACK0].playbackInputFile = "/vendor/etc/segment000000.ts";
+ dvrArray[DVR_PLAYBACK0].playbackInputFile = "/data/local/tmp/segment000000.ts";
dvrArray[DVR_PLAYBACK0].bufferSize = FMQ_SIZE_4M;
dvrArray[DVR_PLAYBACK0].settings.playback(playbackSettings);
+ PlaybackSettings softwareFePlaybackSettings{
+ .statusMask = 0xf,
+ .lowThreshold = 0x1000,
+ .highThreshold = 0x07fff,
+ .dataFormat = DataFormat::TS,
+ .packetSize = 188,
+ };
+ dvrArray[DVR_SOFTWARE_FE].type = DvrType::PLAYBACK;
+ dvrArray[DVR_SOFTWARE_FE].playbackInputFile = "/data/local/tmp/segment000000.ts";
+ dvrArray[DVR_SOFTWARE_FE].bufferSize = FMQ_SIZE_4M;
+ dvrArray[DVR_SOFTWARE_FE].settings.playback(softwareFePlaybackSettings);
};
/** Configuration array for the descrambler test */
diff --git a/wifi/1.4/vts/functional/wifi_rtt_controller_hidl_test.cpp b/wifi/1.4/vts/functional/wifi_rtt_controller_hidl_test.cpp
index 9d84223..a099c8a 100644
--- a/wifi/1.4/vts/functional/wifi_rtt_controller_hidl_test.cpp
+++ b/wifi/1.4/vts/functional/wifi_rtt_controller_hidl_test.cpp
@@ -225,8 +225,8 @@
int cmdId = 55;
WifiChannelInfo channelInfo;
channelInfo.width = WifiChannelWidthInMhz::WIDTH_80;
- channelInfo.centerFreq = 5690;
- channelInfo.centerFreq0 = 5690;
+ channelInfo.centerFreq = 5660;
+ channelInfo.centerFreq0 = 5660;
channelInfo.centerFreq1 = 0;
// Get the responder first