Merge "Disable framework for some VTS tests" into rvc-dev
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..f712ea2 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:
@@ -67,6 +76,8 @@
     switch (prop) {
         case INITIAL_USER_INFO:
         case SWITCH_USER:
+        case CREATE_USER:
+        case REMOVE_USER:
             ALOGE("onGetProperty(): %d is only supported on SET", prop);
             return android::base::Error(static_cast<int>(StatusCode::INVALID_ARG))
                    << "only supported on SET";
@@ -162,6 +173,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) {
@@ -247,6 +293,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..5243b96 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
@@ -105,6 +105,12 @@
             const VehiclePropValue& value);
 
     /**
+     * Used to emulate CREATE_USER - see onSetInitialUserInfoResponse() for usage.
+     */
+    android::base::Result<std::unique_ptr<VehiclePropValue>> onSetCreateUserResponse(
+            const VehiclePropValue& value);
+
+    /**
      * Used to emulate USER_IDENTIFICATION_ASSOCIATION - see onSetInitialUserInfoResponse() for
      * usage.
      */
@@ -116,6 +122,7 @@
 
     std::unique_ptr<VehiclePropValue> mInitialUserResponseFromCmd;
     std::unique_ptr<VehiclePropValue> mSwitchUserResponseFromCmd;
+    std::unique_ptr<VehiclePropValue> mCreateUserResponseFromCmd;
     std::unique_ptr<VehiclePropValue> mSetUserIdentificationAssociationResponseFromCmd;
 };
 
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 550a2e0..f6860cf 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -575,7 +575,10 @@
  }
  virtual void TearDown() override {}
 
- hidl_vec<hidl_string> getCameraDeviceNames(sp<ICameraProvider> provider);
+ hidl_vec<hidl_string> getCameraDeviceNames(sp<ICameraProvider> provider,
+                                            bool addSecureOnly = false);
+
+ bool isSecureOnly(sp<ICameraProvider> provider, const hidl_string& name);
 
  std::map<hidl_string, hidl_string> getCameraDeviceIdToNameMap(sp<ICameraProvider> provider);
 
@@ -799,6 +802,16 @@
             bool *useHalBufManager /*out*/,
             sp<DeviceCb> *cb /*out*/,
             uint32_t streamConfigCounter = 0);
+    void configureSingleStream(const std::string& name, int32_t deviceVersion,
+            sp<ICameraProvider> provider,
+            const AvailableStream* previewThreshold, uint64_t bufferUsage,
+            RequestTemplate reqTemplate,
+            sp<ICameraDeviceSession>* session /*out*/,
+            V3_2::Stream* previewStream /*out*/,
+            HalStreamConfiguration* halStreamConfig /*out*/,
+            bool* supportsPartialResults /*out*/,
+            uint32_t* partialResultCount /*out*/, bool* useHalBufManager /*out*/,
+            sp<DeviceCb>* cb /*out*/, uint32_t streamConfigCounter = 0);
 
     void verifyLogicalCameraMetadata(const std::string& cameraName,
             const ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice>& device,
@@ -875,6 +888,9 @@
     static Status getSystemCameraKind(const camera_metadata_t* staticMeta,
                                       SystemCameraKind* systemCameraKind);
 
+    void processCaptureRequestInternal(uint64_t bufferusage, RequestTemplate reqTemplate,
+                                       bool useSecureOnlyCameras);
+
     // Used by switchToOffline where a new result queue is created for offline reqs
     void updateInflightResultQueue(std::shared_ptr<ResultMetadataQueue> resultQueue);
 
@@ -1585,7 +1601,8 @@
     return idToNameMap;
 }
 
-hidl_vec<hidl_string> CameraHidlTest::getCameraDeviceNames(sp<ICameraProvider> provider) {
+hidl_vec<hidl_string> CameraHidlTest::getCameraDeviceNames(sp<ICameraProvider> provider,
+                                                           bool addSecureOnly) {
     std::vector<std::string> cameraDeviceNames;
     Return<void> ret;
     ret = provider->getCameraIdList(
@@ -1634,11 +1651,51 @@
         }
     }
 
-    hidl_vec<hidl_string> retList(cameraDeviceNames.size());
+    std::vector<hidl_string> retList;
     for (size_t i = 0; i < cameraDeviceNames.size(); i++) {
-        retList[i] = cameraDeviceNames[i];
+        bool isSecureOnlyCamera = isSecureOnly(mProvider, cameraDeviceNames[i]);
+        if (addSecureOnly) {
+            if (isSecureOnlyCamera) {
+                retList.emplace_back(cameraDeviceNames[i]);
+            }
+        } else if (!isSecureOnlyCamera) {
+            retList.emplace_back(cameraDeviceNames[i]);
+        }
     }
-    return retList;
+    hidl_vec<hidl_string> finalRetList = std::move(retList);
+    return finalRetList;
+}
+
+bool CameraHidlTest::isSecureOnly(sp<ICameraProvider> provider, const hidl_string& name) {
+    Return<void> ret;
+    ::android::sp<ICameraDevice> device3_x;
+    bool retVal = false;
+    if (getCameraDeviceVersion(mProviderType, name) == CAMERA_DEVICE_API_VERSION_1_0) {
+        return false;
+    }
+    ret = provider->getCameraDeviceInterface_V3_x(name, [&](auto status, const auto& device) {
+        ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status);
+        ASSERT_EQ(Status::OK, status);
+        ASSERT_NE(device, nullptr);
+        device3_x = device;
+    });
+    if (!ret.isOk()) {
+        ADD_FAILURE() << "Failed to get camera device interface for " << name;
+    }
+    ret = device3_x->getCameraCharacteristics([&](Status s, CameraMetadata metadata) {
+        ASSERT_EQ(Status::OK, s);
+        camera_metadata_t* chars = (camera_metadata_t*)metadata.data();
+        SystemCameraKind systemCameraKind = SystemCameraKind::PUBLIC;
+        Status status = getSystemCameraKind(chars, &systemCameraKind);
+        ASSERT_EQ(status, Status::OK);
+        if (systemCameraKind == SystemCameraKind::HIDDEN_SECURE_CAMERA) {
+            retVal = true;
+        }
+    });
+    if (!ret.isOk()) {
+        ADD_FAILURE() << "Failed to get camera characteristics for device " << name;
+    }
+    return retVal;
 }
 
 hidl_vec<hidl_vec<hidl_string>> CameraHidlTest::getConcurrentDeviceCombinations(
@@ -4316,8 +4373,21 @@
 
 // Generate and verify a camera capture request
 TEST_P(CameraHidlTest, processCaptureRequestPreview) {
-    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
-    AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
+    processCaptureRequestInternal(GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, RequestTemplate::PREVIEW,
+                                  false /*secureOnlyCameras*/);
+}
+
+// Generate and verify a secure camera capture request
+TEST_P(CameraHidlTest, processSecureCaptureRequest) {
+    processCaptureRequestInternal(GRALLOC1_PRODUCER_USAGE_PROTECTED, RequestTemplate::STILL_CAPTURE,
+                                  true /*secureOnlyCameras*/);
+}
+
+void CameraHidlTest::processCaptureRequestInternal(uint64_t bufferUsage,
+                                                   RequestTemplate reqTemplate,
+                                                   bool useSecureOnlyCameras) {
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider, useSecureOnlyCameras);
+    AvailableStream streamThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
                                         static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
     uint64_t bufferId = 1;
     uint32_t frameNumber = 1;
@@ -4333,17 +4403,17 @@
             return;
         }
 
-        V3_2::Stream previewStream;
+        V3_2::Stream testStream;
         HalStreamConfiguration halStreamConfig;
         sp<ICameraDeviceSession> session;
         sp<DeviceCb> cb;
         bool supportsPartialResults = false;
         bool useHalBufManager = false;
         uint32_t partialResultCount = 0;
-        configurePreviewStream(name, deviceVersion, mProvider, &previewThreshold, &session /*out*/,
-                &previewStream /*out*/, &halStreamConfig /*out*/,
-                &supportsPartialResults /*out*/,
-                &partialResultCount /*out*/, &useHalBufManager /*out*/, &cb /*out*/);
+        configureSingleStream(name, deviceVersion, mProvider, &streamThreshold, bufferUsage,
+                              reqTemplate, &session /*out*/, &testStream /*out*/,
+                              &halStreamConfig /*out*/, &supportsPartialResults /*out*/,
+                              &partialResultCount /*out*/, &useHalBufManager /*out*/, &cb /*out*/);
 
         std::shared_ptr<ResultMetadataQueue> resultQueue;
         auto resultQueueRet =
@@ -4364,7 +4434,6 @@
         InFlightRequest inflightReq = {1, false, supportsPartialResults,
                                        partialResultCount, resultQueue};
 
-        RequestTemplate reqTemplate = RequestTemplate::PREVIEW;
         Return<void> ret;
         ret = session->constructDefaultRequestSettings(reqTemplate,
                                                        [&](auto status, const auto& req) {
@@ -4383,7 +4452,7 @@
                             nullptr,
                             nullptr};
         } else {
-            allocateGraphicBuffer(previewStream.width, previewStream.height,
+            allocateGraphicBuffer(testStream.width, testStream.height,
                     android_convertGralloc1To0Usage(halStreamConfig.streams[0].producerUsage,
                         halStreamConfig.streams[0].consumerUsage),
                     halStreamConfig.streams[0].overrideFormat, &buffer_handle);
@@ -4432,7 +4501,7 @@
 
             ASSERT_FALSE(inflightReq.errorCodeValid);
             ASSERT_NE(inflightReq.resultOutputBuffers.size(), 0u);
-            ASSERT_EQ(previewStream.id, inflightReq.resultOutputBuffers[0].streamId);
+            ASSERT_EQ(testStream.id, inflightReq.resultOutputBuffers[0].streamId);
 
             request.frameNumber++;
             // Empty settings should be supported after the first call
@@ -4470,11 +4539,11 @@
 
             ASSERT_FALSE(inflightReq.errorCodeValid);
             ASSERT_NE(inflightReq.resultOutputBuffers.size(), 0u);
-            ASSERT_EQ(previewStream.id, inflightReq.resultOutputBuffers[0].streamId);
+            ASSERT_EQ(testStream.id, inflightReq.resultOutputBuffers[0].streamId);
         }
 
         if (useHalBufManager) {
-            verifyBuffersReturned(session, deviceVersion, previewStream.id, cb);
+            verifyBuffersReturned(session, deviceVersion, testStream.id, cb);
         }
 
         ret = session->close();
@@ -6278,6 +6347,19 @@
         bool *useHalBufManager /*out*/,
         sp<DeviceCb> *outCb /*out*/,
         uint32_t streamConfigCounter) {
+    configureSingleStream(name, deviceVersion, provider, previewThreshold,
+                          GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, RequestTemplate::PREVIEW, session,
+                          previewStream, halStreamConfig, supportsPartialResults,
+                          partialResultCount, useHalBufManager, outCb, streamConfigCounter);
+}
+// Open a device session and configure a preview stream.
+void CameraHidlTest::configureSingleStream(
+        const std::string& name, int32_t deviceVersion, sp<ICameraProvider> provider,
+        const AvailableStream* previewThreshold, uint64_t bufferUsage, RequestTemplate reqTemplate,
+        sp<ICameraDeviceSession>* session /*out*/, V3_2::Stream* previewStream /*out*/,
+        HalStreamConfiguration* halStreamConfig /*out*/, bool* supportsPartialResults /*out*/,
+        uint32_t* partialResultCount /*out*/, bool* useHalBufManager /*out*/,
+        sp<DeviceCb>* outCb /*out*/, uint32_t streamConfigCounter) {
     ASSERT_NE(nullptr, session);
     ASSERT_NE(nullptr, previewStream);
     ASSERT_NE(nullptr, halStreamConfig);
@@ -6366,11 +6448,14 @@
             dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::UNKNOWN);
     }
 
-    V3_2::Stream stream3_2 = {0, StreamType::OUTPUT,
-            static_cast<uint32_t> (outputPreviewStreams[0].width),
-            static_cast<uint32_t> (outputPreviewStreams[0].height),
-            static_cast<PixelFormat> (outputPreviewStreams[0].format),
-            GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, dataspaceFlag, StreamRotation::ROTATION_0};
+    V3_2::Stream stream3_2 = {0,
+                              StreamType::OUTPUT,
+                              static_cast<uint32_t>(outputPreviewStreams[0].width),
+                              static_cast<uint32_t>(outputPreviewStreams[0].height),
+                              static_cast<PixelFormat>(outputPreviewStreams[0].format),
+                              bufferUsage,
+                              dataspaceFlag,
+                              StreamRotation::ROTATION_0};
     ::android::hardware::hidl_vec<V3_2::Stream> streams3_2 = {stream3_2};
     ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2;
     ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4;
@@ -6378,7 +6463,6 @@
     createStreamConfiguration(streams3_2, StreamConfigurationMode::NORMAL_MODE,
                               &config3_2, &config3_4, &config3_5, jpegBufferSize);
     if (session3_5 != nullptr) {
-        RequestTemplate reqTemplate = RequestTemplate::PREVIEW;
         ret = session3_5->constructDefaultRequestSettings(reqTemplate,
                                                        [&config3_5](auto status, const auto& req) {
                                                            ASSERT_EQ(Status::OK, status);
@@ -6401,7 +6485,6 @@
                     }
                 });
     } else if (session3_4 != nullptr) {
-        RequestTemplate reqTemplate = RequestTemplate::PREVIEW;
         ret = session3_4->constructDefaultRequestSettings(reqTemplate,
                                                        [&config3_4](auto status, const auto& req) {
                                                            ASSERT_EQ(Status::OK, status);
diff --git a/identity/aidl/vts/Android.bp b/identity/aidl/vts/Android.bp
index e4780bf..5b075c6 100644
--- a/identity/aidl/vts/Android.bp
+++ b/identity/aidl/vts/Android.bp
@@ -8,10 +8,16 @@
         "VtsHalIdentityEndToEndTest.cpp",
         "VtsIWritableIdentityCredentialTests.cpp",
         "VtsIdentityTestUtils.cpp",
+        "VtsAttestationTests.cpp",
+        "VtsAttestationParserSupport.cpp",
     ],
     shared_libs: [
+        "android.hardware.keymaster@4.0",
         "libbinder",
         "libcrypto",
+        "libkeymaster_portable",
+        "libsoft_attestation_cert",
+        "libpuresoftkeymasterdevice",
     ],
     static_libs: [
         "libcppbor",
diff --git a/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp b/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp
index 17145b4..464ab0c 100644
--- a/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp
+++ b/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#define LOG_TAG "VtsHalIdentityTargetTest"
+#define LOG_TAG "VtsHalIdentityEndToEndTest"
 
 #include <aidl/Gtest.h>
 #include <aidl/Vintf.h>
@@ -45,6 +45,8 @@
 using ::android::hardware::keymaster::HardwareAuthToken;
 using ::android::hardware::keymaster::VerificationToken;
 
+using test_utils::validateAttestationCertificate;
+
 class IdentityAidl : public testing::TestWithParam<std::string> {
   public:
     virtual void SetUp() override {
@@ -69,13 +71,13 @@
     // part of the request data.
     vector<uint8_t> readerKey;
     optional<vector<uint8_t>> readerCertificate =
-            test_utils::GenerateReaderCertificate("1234", readerKey);
+            test_utils::generateReaderCertificate("1234", &readerKey);
     ASSERT_TRUE(readerCertificate);
 
     // Make the portrait image really big (just shy of 256 KiB) to ensure that
     // the chunking code gets exercised.
     vector<uint8_t> portraitImage;
-    test_utils::SetImageData(portraitImage);
+    test_utils::setImageData(portraitImage);
 
     // Access control profiles:
     const vector<test_utils::TestProfile> testProfiles = {// Profile 0 (reader authentication)
@@ -114,17 +116,16 @@
 
     string cborPretty;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     string challenge = "attestationChallenge";
     test_utils::AttestationData attData(writableCredential, challenge, {});
     ASSERT_TRUE(attData.result.isOk())
             << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
-    ASSERT_EQ(binder::Status::EX_NONE, attData.result.exceptionCode());
-    ASSERT_EQ(IIdentityCredentialStore::STATUS_OK, attData.result.serviceSpecificErrorCode());
 
-    // TODO: set it to something random and check it's in the cert chain
-    ASSERT_GE(attData.attestationCertificate.size(), 2);
+    EXPECT_TRUE(validateAttestationCertificate(attData.attestationCertificate,
+                                               attData.attestationChallenge,
+                                               attData.attestationApplicationId, hwInfo));
 
     // This is kinda of a hack but we need to give the size of
     // ProofOfProvisioning that we'll expect to receive.
@@ -136,7 +137,7 @@
                     .isOk());
 
     optional<vector<SecureAccessControlProfile>> secureProfiles =
-            test_utils::AddAccessControlProfiles(writableCredential, testProfiles);
+            test_utils::addAccessControlProfiles(writableCredential, testProfiles);
     ASSERT_TRUE(secureProfiles);
 
     // Uses TestEntryData* pointer as key and values are the encrypted blobs. This
@@ -144,7 +145,7 @@
     map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
 
     for (const auto& entry : testEntries) {
-        ASSERT_TRUE(test_utils::AddEntry(writableCredential, entry, hwInfo.dataChunkSize,
+        ASSERT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
                                          encryptedBlobs, true));
     }
 
diff --git a/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp b/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
index 724aaa1..8b0c050 100644
--- a/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
+++ b/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
@@ -56,8 +56,12 @@
 
 TEST_P(IdentityCredentialTests, verifyAttestationWithEmptyChallenge) {
     Status result;
+
+    HardwareInformation hwInfo;
+    ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
+
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     vector<uint8_t> attestationChallenge;
     vector<Certificate> attestationCertificate;
@@ -68,13 +72,18 @@
     EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
                                << endl;
 
-    EXPECT_TRUE(test_utils::ValidateAttestationCertificate(attestationCertificate));
+    EXPECT_TRUE(test_utils::validateAttestationCertificate(
+            attestationCertificate, attestationChallenge, attestationApplicationId, hwInfo));
 }
 
 TEST_P(IdentityCredentialTests, verifyAttestationSuccessWithChallenge) {
     Status result;
+
+    HardwareInformation hwInfo;
+    ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
+
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     string challenge = "NotSoRandomChallenge1NotSoRandomChallenge1NotSoRandomChallenge1";
     vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
@@ -87,17 +96,24 @@
     EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
                                << endl;
 
-    EXPECT_TRUE(test_utils::ValidateAttestationCertificate(attestationCertificate));
+    EXPECT_TRUE(test_utils::validateAttestationCertificate(
+            attestationCertificate, attestationChallenge, attestationApplicationId, hwInfo));
 }
 
 TEST_P(IdentityCredentialTests, verifyAttestationDoubleCallFails) {
     Status result;
+
+    HardwareInformation hwInfo;
+    ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
+
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     string challenge = "NotSoRandomChallenge1";
     test_utils::AttestationData attData(writableCredential, challenge, {});
-    ASSERT_TRUE(test_utils::ValidateAttestationCertificate(attData.attestationCertificate));
+    ASSERT_TRUE(test_utils::validateAttestationCertificate(
+            attData.attestationCertificate, attData.attestationChallenge,
+            attData.attestationApplicationId, hwInfo));
 
     string challenge2 = "NotSoRandomChallenge2";
     test_utils::AttestationData attData2(writableCredential, challenge2, {});
@@ -110,7 +126,7 @@
 TEST_P(IdentityCredentialTests, verifyStartPersonalization) {
     Status result;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     // First call should go through
     const vector<int32_t> entryCounts = {2, 4};
@@ -131,7 +147,7 @@
 TEST_P(IdentityCredentialTests, verifyStartPersonalizationMin) {
     Status result;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     // Verify minimal number of profile count and entry count
     const vector<int32_t> entryCounts = {1, 1};
@@ -143,7 +159,7 @@
 TEST_P(IdentityCredentialTests, verifyStartPersonalizationZero) {
     Status result;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     const vector<int32_t> entryCounts = {0};
     writableCredential->startPersonalization(0, entryCounts);
@@ -154,7 +170,7 @@
 TEST_P(IdentityCredentialTests, verifyStartPersonalizationOne) {
     Status result;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     // Verify minimal number of profile count and entry count
     const vector<int32_t> entryCounts = {1};
@@ -166,7 +182,7 @@
 TEST_P(IdentityCredentialTests, verifyStartPersonalizationLarge) {
     Status result;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     // Verify set a large number of profile count and entry count is ok
     const vector<int32_t> entryCounts = {3000};
@@ -178,7 +194,7 @@
 TEST_P(IdentityCredentialTests, verifyProfileNumberMismatchShouldFail) {
     Status result;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     // Enter mismatched entry and profile numbers
     const vector<int32_t> entryCounts = {5, 6};
@@ -186,7 +202,7 @@
     ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
                                << endl;
 
-    optional<vector<uint8_t>> readerCertificate = test_utils::GenerateReaderCertificate("12345");
+    optional<vector<uint8_t>> readerCertificate = test_utils::generateReaderCertificate("12345");
     ASSERT_TRUE(readerCertificate);
 
     const vector<test_utils::TestProfile> testProfiles = {// Profile 0 (reader authentication)
@@ -196,7 +212,7 @@
                                                           {4, {}, false, 0}};
 
     optional<vector<SecureAccessControlProfile>> secureProfiles =
-            test_utils::AddAccessControlProfiles(writableCredential, testProfiles);
+            test_utils::addAccessControlProfiles(writableCredential, testProfiles);
     ASSERT_TRUE(secureProfiles);
 
     vector<uint8_t> credentialData;
@@ -205,7 +221,7 @@
             writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
 
     // finishAddingEntries should fail because the number of addAccessControlProfile mismatched with
-    // startPersonalization, and begintest_utils::AddEntry was not called.
+    // startPersonalization, and begintest_utils::addEntry was not called.
     EXPECT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
                                 << endl;
     EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
@@ -215,7 +231,7 @@
 TEST_P(IdentityCredentialTests, verifyDuplicateProfileId) {
     Status result;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     const vector<int32_t> entryCounts = {3, 6};
     writableCredential->startPersonalization(3, entryCounts);
@@ -272,14 +288,14 @@
     ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
 
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     string challenge = "NotSoRandomChallenge1";
     test_utils::AttestationData attData(writableCredential, challenge, {});
     EXPECT_TRUE(attData.result.isOk())
             << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
 
-    optional<vector<uint8_t>> readerCertificate1 = test_utils::GenerateReaderCertificate("123456");
+    optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
     ASSERT_TRUE(readerCertificate1);
 
     const vector<int32_t> entryCounts = {1u};
@@ -293,7 +309,7 @@
     const vector<test_utils::TestProfile> testProfiles = {{1, readerCertificate1.value(), true, 1}};
 
     optional<vector<SecureAccessControlProfile>> secureProfiles =
-            test_utils::AddAccessControlProfiles(writableCredential, testProfiles);
+            test_utils::addAccessControlProfiles(writableCredential, testProfiles);
     ASSERT_TRUE(secureProfiles);
 
     const vector<test_utils::TestEntryData> testEntries1 = {
@@ -302,7 +318,7 @@
 
     map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
     for (const auto& entry : testEntries1) {
-        ASSERT_TRUE(test_utils::AddEntry(writableCredential, entry, hwInfo.dataChunkSize,
+        ASSERT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
                                          encryptedBlobs, true));
     }
 
@@ -359,17 +375,17 @@
     ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
 
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     string challenge = "NotSoRandomChallenge";
     test_utils::AttestationData attData(writableCredential, challenge, {});
     EXPECT_TRUE(attData.result.isOk())
             << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
 
-    optional<vector<uint8_t>> readerCertificate1 = test_utils::GenerateReaderCertificate("123456");
+    optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
     ASSERT_TRUE(readerCertificate1);
 
-    optional<vector<uint8_t>> readerCertificate2 = test_utils::GenerateReaderCertificate("1256");
+    optional<vector<uint8_t>> readerCertificate2 = test_utils::generateReaderCertificate("1256");
     ASSERT_TRUE(readerCertificate2);
 
     const vector<test_utils::TestProfile> testProfiles = {
@@ -386,14 +402,14 @@
                                << endl;
 
     optional<vector<SecureAccessControlProfile>> secureProfiles =
-            test_utils::AddAccessControlProfiles(writableCredential, testProfiles);
+            test_utils::addAccessControlProfiles(writableCredential, testProfiles);
     ASSERT_TRUE(secureProfiles);
 
     vector<uint8_t> portraitImage1;
-    test_utils::SetImageData(portraitImage1);
+    test_utils::setImageData(portraitImage1);
 
     vector<uint8_t> portraitImage2;
-    test_utils::SetImageData(portraitImage2);
+    test_utils::setImageData(portraitImage2);
 
     const vector<test_utils::TestEntryData> testEntries1 = {
             {"Name Space 1", "Last name", string("Turing"), vector<int32_t>{1, 2}},
@@ -411,7 +427,7 @@
 
     map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
     for (const auto& entry : testEntries1) {
-        EXPECT_TRUE(test_utils::AddEntry(writableCredential, entry, hwInfo.dataChunkSize,
+        EXPECT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
                                          encryptedBlobs, true));
     }
 
@@ -518,18 +534,18 @@
     ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
 
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     string challenge = "NotSoRandomChallenge";
     test_utils::AttestationData attData(writableCredential, challenge, {});
     ASSERT_TRUE(attData.result.isOk())
             << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
 
-    optional<vector<uint8_t>> readerCertificate1 = test_utils::GenerateReaderCertificate("123456");
+    optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
     ASSERT_TRUE(readerCertificate1);
 
     optional<vector<uint8_t>> readerCertificate2 =
-            test_utils::GenerateReaderCertificate("123456987987987987987987");
+            test_utils::generateReaderCertificate("123456987987987987987987");
     ASSERT_TRUE(readerCertificate2);
 
     const vector<int32_t> entryCounts = {2u, 2u};
@@ -547,7 +563,7 @@
                                                           {2, {}, false, 0}};
 
     optional<vector<SecureAccessControlProfile>> secureProfiles =
-            test_utils::AddAccessControlProfiles(writableCredential, testProfiles);
+            test_utils::addAccessControlProfiles(writableCredential, testProfiles);
     ASSERT_TRUE(secureProfiles);
 
     const vector<test_utils::TestEntryData> testEntries1 = {
@@ -560,7 +576,7 @@
 
     map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
     for (const auto& entry : testEntries1) {
-        EXPECT_TRUE(test_utils::AddEntry(writableCredential, entry, hwInfo.dataChunkSize,
+        EXPECT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
                                          encryptedBlobs, true));
     }
 
@@ -580,7 +596,7 @@
     ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
 
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     string challenge = "NotSoRandomChallenge";
     test_utils::AttestationData attData(writableCredential, challenge, {});
@@ -596,11 +612,11 @@
     ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
                                << endl;
 
-    optional<vector<uint8_t>> readerCertificate1 = test_utils::GenerateReaderCertificate("123456");
+    optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
     ASSERT_TRUE(readerCertificate1);
 
     optional<vector<uint8_t>> readerCertificate2 =
-            test_utils::GenerateReaderCertificate("123456987987987987987987");
+            test_utils::generateReaderCertificate("123456987987987987987987");
     ASSERT_TRUE(readerCertificate2);
 
     const vector<test_utils::TestProfile> testProfiles = {{0, readerCertificate1.value(), false, 0},
@@ -608,7 +624,7 @@
                                                           {2, {}, false, 0}};
 
     optional<vector<SecureAccessControlProfile>> secureProfiles =
-            test_utils::AddAccessControlProfiles(writableCredential, testProfiles);
+            test_utils::addAccessControlProfiles(writableCredential, testProfiles);
     ASSERT_TRUE(secureProfiles);
 
     const vector<test_utils::TestEntryData> testEntries1 = {
@@ -619,13 +635,13 @@
 
     map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
     for (const auto& entry : testEntries1) {
-        EXPECT_TRUE(test_utils::AddEntry(writableCredential, entry, hwInfo.dataChunkSize,
+        EXPECT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
                                          encryptedBlobs, true));
     }
     const test_utils::TestEntryData testEntry2 = {"Image", "Portrait image", string("asdfs"),
                                                   vector<int32_t>{0, 1}};
 
-    EXPECT_TRUE(test_utils::AddEntry(writableCredential, testEntry2, hwInfo.dataChunkSize,
+    EXPECT_TRUE(test_utils::addEntry(writableCredential, testEntry2, hwInfo.dataChunkSize,
                                      encryptedBlobs, true));
 
     // We expect this to fail because the namespace is out of order, all "Name Space"
@@ -637,7 +653,7 @@
     };
 
     for (const auto& entry : testEntries3) {
-        EXPECT_FALSE(test_utils::AddEntry(writableCredential, entry, hwInfo.dataChunkSize,
+        EXPECT_FALSE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
                                           encryptedBlobs, false));
     }
 
@@ -646,7 +662,7 @@
     result =
             writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
 
-    // should fail because test_utils::AddEntry should have failed earlier.
+    // should fail because test_utils::addEntry should have failed earlier.
     EXPECT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
                                 << endl;
     EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
@@ -655,7 +671,7 @@
 
 TEST_P(IdentityCredentialTests, verifyAccessControlProfileIdOutOfRange) {
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     const vector<int32_t> entryCounts = {1};
     Status result = writableCredential->startPersonalization(1, entryCounts);
diff --git a/identity/aidl/vts/VtsIdentityTestUtils.cpp b/identity/aidl/vts/VtsIdentityTestUtils.cpp
index 48e47dc..aaebcbe 100644
--- a/identity/aidl/vts/VtsIdentityTestUtils.cpp
+++ b/identity/aidl/vts/VtsIdentityTestUtils.cpp
@@ -19,6 +19,8 @@
 #include <aidl/Gtest.h>
 #include <map>
 
+#include "VtsAttestationParserSupport.h"
+
 namespace android::hardware::identity::test_utils {
 
 using std::endl;
@@ -31,7 +33,7 @@
 using ::android::String16;
 using ::android::binder::Status;
 
-bool SetupWritableCredential(sp<IWritableIdentityCredential>& writableCredential,
+bool setupWritableCredential(sp<IWritableIdentityCredential>& writableCredential,
                              sp<IIdentityCredentialStore>& credentialStore) {
     if (credentialStore == nullptr) {
         return false;
@@ -48,13 +50,13 @@
     }
 }
 
-optional<vector<uint8_t>> GenerateReaderCertificate(string serialDecimal) {
+optional<vector<uint8_t>> generateReaderCertificate(string serialDecimal) {
     vector<uint8_t> privKey;
-    return GenerateReaderCertificate(serialDecimal, privKey);
+    return generateReaderCertificate(serialDecimal, &privKey);
 }
 
-optional<vector<uint8_t>> GenerateReaderCertificate(string serialDecimal,
-                                                    vector<uint8_t>& readerPrivateKey) {
+optional<vector<uint8_t>> generateReaderCertificate(string serialDecimal,
+                                                    vector<uint8_t>* outReaderPrivateKey) {
     optional<vector<uint8_t>> readerKeyPKCS8 = support::createEcKeyPair();
     if (!readerKeyPKCS8) {
         return {};
@@ -67,7 +69,11 @@
         return {};
     }
 
-    readerPrivateKey = readerKey.value();
+    if (outReaderPrivateKey == nullptr) {
+        return {};
+    }
+
+    *outReaderPrivateKey = readerKey.value();
 
     string issuer = "Android Open Source Project";
     string subject = "Android IdentityCredential VTS Test";
@@ -79,7 +85,7 @@
                                                    validityNotBefore, validityNotAfter);
 }
 
-optional<vector<SecureAccessControlProfile>> AddAccessControlProfiles(
+optional<vector<SecureAccessControlProfile>> addAccessControlProfiles(
         sp<IWritableIdentityCredential>& writableCredential,
         const vector<TestProfile>& testProfiles) {
     Status result;
@@ -120,7 +126,7 @@
 
 // Most test expects this function to pass. So we will print out additional
 // value if failed so more debug data can be provided.
-bool AddEntry(sp<IWritableIdentityCredential>& writableCredential, const TestEntryData& entry,
+bool addEntry(sp<IWritableIdentityCredential>& writableCredential, const TestEntryData& entry,
               int dataChunkSize, map<const TestEntryData*, vector<vector<uint8_t>>>& encryptedBlobs,
               bool expectSuccess) {
     Status result;
@@ -164,18 +170,70 @@
     return true;
 }
 
-bool ValidateAttestationCertificate(vector<Certificate>& inputCertificates) {
-    return (inputCertificates.size() >= 2);
-    // TODO: add parsing of the certificate and make sure it is genuine.
-}
-
-void SetImageData(vector<uint8_t>& image) {
+void setImageData(vector<uint8_t>& image) {
     image.resize(256 * 1024 - 10);
     for (size_t n = 0; n < image.size(); n++) {
         image[n] = (uint8_t)n;
     }
 }
 
+bool validateAttestationCertificate(const vector<Certificate>& inputCertificates,
+                                    const vector<uint8_t>& expectedChallenge,
+                                    const vector<uint8_t>& expectedAppId,
+                                    const HardwareInformation& hwInfo) {
+    AttestationCertificateParser certParser_(inputCertificates);
+    bool ret = certParser_.parse();
+    EXPECT_TRUE(ret);
+    if (!ret) {
+        return false;
+    }
+
+    // As per the IC HAL, the version of the Identity
+    // Credential HAL is 1.0 - and this is encoded as major*10 + minor. This field is used by
+    // Keymaster which is known to report integers less than or equal to 4 (for KM up to 4.0)
+    // and integers greater or equal than 41 (for KM starting with 4.1).
+    //
+    // Since we won't get to version 4.0 of the IC HAL for a while, let's also check that a KM
+    // version isn't errornously returned.
+    EXPECT_LE(10, certParser_.getKeymasterVersion());
+    EXPECT_GT(40, certParser_.getKeymasterVersion());
+    EXPECT_LE(3, certParser_.getAttestationVersion());
+
+    // Verify the app id matches to whatever we set it to be.
+    optional<vector<uint8_t>> appId =
+            certParser_.getSwEnforcedBlob(::keymaster::TAG_ATTESTATION_APPLICATION_ID);
+    if (appId) {
+        EXPECT_EQ(expectedAppId.size(), appId.value().size());
+        EXPECT_EQ(0, memcmp(expectedAppId.data(), appId.value().data(), expectedAppId.size()));
+    } else {
+        // app id not found
+        EXPECT_EQ(0, expectedAppId.size());
+    }
+
+    EXPECT_TRUE(certParser_.getHwEnforcedBool(::keymaster::TAG_IDENTITY_CREDENTIAL_KEY));
+    EXPECT_FALSE(certParser_.getHwEnforcedBool(::keymaster::TAG_INCLUDE_UNIQUE_ID));
+
+    // Verify the challenge always matches in size and data of what is passed
+    // in.
+    vector<uint8_t> attChallenge = certParser_.getAttestationChallenge();
+    EXPECT_EQ(expectedChallenge.size(), attChallenge.size());
+    EXPECT_EQ(0, memcmp(expectedChallenge.data(), attChallenge.data(), expectedChallenge.size()));
+
+    // Ensure the attestation conveys that it's implemented in secure hardware (with carve-out
+    // for the reference implementation which cannot be implemented in secure hardware).
+    if (hwInfo.credentialStoreName == "Identity Credential Reference Implementation" &&
+        hwInfo.credentialStoreAuthorName == "Google") {
+        EXPECT_LE(KM_SECURITY_LEVEL_SOFTWARE, certParser_.getKeymasterSecurityLevel());
+        EXPECT_LE(KM_SECURITY_LEVEL_SOFTWARE, certParser_.getAttestationSecurityLevel());
+
+    } else {
+        // Actual devices should use TrustedEnvironment or StrongBox.
+        EXPECT_LE(KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT, certParser_.getKeymasterSecurityLevel());
+        EXPECT_LE(KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT, certParser_.getAttestationSecurityLevel());
+    }
+    return true;
+}
+
 vector<RequestNamespace> buildRequestNamespaces(const vector<TestEntryData> entries) {
     vector<RequestNamespace> ret;
     RequestNamespace curNs;
diff --git a/identity/aidl/vts/VtsIdentityTestUtils.h b/identity/aidl/vts/VtsIdentityTestUtils.h
index 9e1f352..673b736 100644
--- a/identity/aidl/vts/VtsIdentityTestUtils.h
+++ b/identity/aidl/vts/VtsIdentityTestUtils.h
@@ -93,25 +93,28 @@
     uint64_t timeoutMillis;
 };
 
-bool SetupWritableCredential(sp<IWritableIdentityCredential>& writableCredential,
+bool setupWritableCredential(sp<IWritableIdentityCredential>& writableCredential,
                              sp<IIdentityCredentialStore>& credentialStore);
 
-optional<vector<uint8_t>> GenerateReaderCertificate(string serialDecimal);
+optional<vector<uint8_t>> generateReaderCertificate(string serialDecimal);
 
-optional<vector<uint8_t>> GenerateReaderCertificate(string serialDecimal,
-                                                    vector<uint8_t>& readerPrivateKey);
+optional<vector<uint8_t>> generateReaderCertificate(string serialDecimal,
+                                                    vector<uint8_t>* outReaderPrivateKey);
 
-optional<vector<SecureAccessControlProfile>> AddAccessControlProfiles(
+optional<vector<SecureAccessControlProfile>> addAccessControlProfiles(
         sp<IWritableIdentityCredential>& writableCredential,
         const vector<TestProfile>& testProfiles);
 
-bool AddEntry(sp<IWritableIdentityCredential>& writableCredential, const TestEntryData& entry,
+bool addEntry(sp<IWritableIdentityCredential>& writableCredential, const TestEntryData& entry,
               int dataChunkSize, map<const TestEntryData*, vector<vector<uint8_t>>>& encryptedBlobs,
               bool expectSuccess);
 
-bool ValidateAttestationCertificate(vector<Certificate>& inputCertificates);
+void setImageData(vector<uint8_t>& image);
 
-void SetImageData(vector<uint8_t>& image);
+bool validateAttestationCertificate(const vector<Certificate>& inputCertificates,
+                                    const vector<uint8_t>& expectedChallenge,
+                                    const vector<uint8_t>& expectedAppId,
+                                    const HardwareInformation& hwInfo);
 
 vector<RequestNamespace> buildRequestNamespaces(const vector<TestEntryData> entries);
 
diff --git a/tv/tuner/1.0/vts/functional/Android.bp b/tv/tuner/1.0/vts/functional/Android.bp
index b152a29..8c08873 100644
--- a/tv/tuner/1.0/vts/functional/Android.bp
+++ b/tv/tuner/1.0/vts/functional/Android.bp
@@ -23,8 +23,12 @@
         "DemuxTests.cpp",
         "FilterTests.cpp",
         "DvrTests.cpp",
+        "DescramblerTests.cpp",
     ],
     static_libs: [
+        "android.hardware.cas@1.0",
+        "android.hardware.cas@1.1",
+        "android.hardware.cas@1.2",
         "android.hardware.tv.tuner@1.0",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
diff --git a/tv/tuner/1.0/vts/functional/DescramblerTests.cpp b/tv/tuner/1.0/vts/functional/DescramblerTests.cpp
new file mode 100644
index 0000000..d7440bc
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/DescramblerTests.cpp
@@ -0,0 +1,195 @@
+/*
+ * 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 "DescramblerTests.h"
+
+AssertionResult DescramblerTests::createCasPlugin(int32_t caSystemId) {
+    auto status = mMediaCasService->isSystemIdSupported(caSystemId);
+    if (!status.isOk() || !status) {
+        ALOGW("[vts] Failed to check isSystemIdSupported.");
+        return failure();
+    }
+
+    mCasListener = new MediaCasListener();
+    auto pluginStatus = mMediaCasService->createPluginExt(caSystemId, mCasListener);
+    if (!pluginStatus.isOk()) {
+        ALOGW("[vts] Failed to createPluginExt.");
+        return failure();
+    }
+    mCas = ICas::castFrom(pluginStatus);
+    if (mCas == nullptr) {
+        ALOGW("[vts] Failed to get ICas.");
+        return failure();
+    }
+    return success();
+}
+
+AssertionResult DescramblerTests::openCasSession(TunerKeyToken& sessionId,
+                                                 vector<uint8_t> hidlPvtData) {
+    Status sessionStatus;
+    SessionIntent intent = SessionIntent::LIVE;
+    ScramblingMode mode = ScramblingMode::RESERVED;
+    auto returnVoid =
+            mCas->openSession_1_2(intent, mode, [&](Status status, const hidl_vec<uint8_t>& id) {
+                sessionStatus = status;
+                sessionId = id;
+            });
+    if (!returnVoid.isOk() || (sessionStatus != Status::OK)) {
+        ALOGW("[vts] Failed to open cas session.");
+        mCas->closeSession(sessionId);
+        return failure();
+    }
+
+    auto status = mCas->setSessionPrivateData(sessionId, hidlPvtData);
+    if (status != android::hardware::cas::V1_0::Status::OK) {
+        ALOGW("[vts] Failed to set session private data");
+        mCas->closeSession(sessionId);
+        return failure();
+    }
+    return success();
+}
+
+AssertionResult DescramblerTests::getKeyToken(int32_t caSystemId, string provisonStr,
+                                              hidl_vec<uint8_t> hidlPvtData, TunerKeyToken& token) {
+    if (createCasPlugin(caSystemId) != success()) {
+        ALOGW("[vts] createCasPlugin failed.");
+        return failure();
+    }
+
+    if (provisonStr.size() > 0) {
+        auto returnStatus = mCas->provision(hidl_string(provisonStr));
+        if (returnStatus != android::hardware::cas::V1_0::Status::OK) {
+            ALOGW("[vts] provision failed.");
+            return failure();
+        }
+    }
+
+    return openCasSession(token, hidlPvtData);
+}
+
+AssertionResult DescramblerTests::openDescrambler(uint32_t demuxId) {
+    Result status;
+    mService->openDescrambler([&](Result result, const sp<IDescrambler>& descrambler) {
+        mDescrambler = descrambler;
+        status = result;
+    });
+    if (status != Result::SUCCESS) {
+        ALOGW("[vts] openDescrambler failed.");
+        return failure();
+    }
+
+    status = mDescrambler->setDemuxSource(demuxId);
+    if (status != Result::SUCCESS) {
+        ALOGW("[vts] setDemuxSource failed.");
+        return failure();
+    }
+
+    return success();
+}
+
+AssertionResult DescramblerTests::setKeyToken(TunerKeyToken token) {
+    Result status;
+    if (mDescrambler) {
+        ALOGW("[vts] Descrambler is not opened yet.");
+        return failure();
+    }
+
+    status = mDescrambler->setKeyToken(token);
+    if (status == Result::SUCCESS) {
+        ALOGW("[vts] setKeyToken failed.");
+        return failure();
+    }
+
+    return success();
+}
+
+AssertionResult DescramblerTests::addPid(DemuxPid pid, sp<IFilter> optionalSourceFilter) {
+    Result status;
+    if (mDescrambler) {
+        ALOGW("[vts] Descrambler is not opened yet.");
+        return failure();
+    }
+
+    status = mDescrambler->addPid(pid, optionalSourceFilter);
+    if (status == Result::SUCCESS) {
+        ALOGW("[vts] addPid failed.");
+        return failure();
+    }
+
+    return success();
+}
+
+AssertionResult DescramblerTests::removePid(DemuxPid pid, sp<IFilter> optionalSourceFilter) {
+    Result status;
+    if (mDescrambler) {
+        ALOGW("[vts] Descrambler is not opened yet.");
+        return failure();
+    }
+
+    status = mDescrambler->removePid(pid, optionalSourceFilter);
+    if (status == Result::SUCCESS) {
+        ALOGW("[vts] removePid failed.");
+        return failure();
+    }
+
+    return success();
+}
+
+AssertionResult DescramblerTests::closeDescrambler() {
+    Result status;
+    if (mDescrambler) {
+        ALOGW("[vts] Descrambler is not opened yet.");
+        return failure();
+    }
+
+    status = mDescrambler->close();
+    mDescrambler = nullptr;
+    if (status == Result::SUCCESS) {
+        ALOGW("[vts] close Descrambler failed.");
+        return failure();
+    }
+
+    return success();
+}
+
+AssertionResult DescramblerTests::getDemuxPidFromFilterSettings(DemuxFilterType type,
+                                                                DemuxFilterSettings settings,
+                                                                DemuxPid& pid) {
+    switch (type.mainType) {
+        case DemuxFilterMainType::TS:
+            if (type.subType.tsFilterType() == DemuxTsFilterType::AUDIO ||
+                type.subType.tsFilterType() == DemuxTsFilterType::VIDEO) {
+                pid.tPid(settings.ts().tpid);
+            } else {
+                ALOGW("[vts] Not a media ts filter!");
+                return failure();
+            }
+            break;
+        case DemuxFilterMainType::MMTP:
+            if (type.subType.mmtpFilterType() == DemuxMmtpFilterType::AUDIO ||
+                type.subType.mmtpFilterType() == DemuxMmtpFilterType::VIDEO) {
+                pid.mmtpPid(settings.mmtp().mmtpPid);
+            } else {
+                ALOGW("[vts] Not a media mmtp filter!");
+                return failure();
+            }
+            break;
+        default:
+            ALOGW("[vts] Not a media filter!");
+            return failure();
+    }
+    return success();
+}
diff --git a/tv/tuner/1.0/vts/functional/DescramblerTests.h b/tv/tuner/1.0/vts/functional/DescramblerTests.h
new file mode 100644
index 0000000..31f4663
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/DescramblerTests.h
@@ -0,0 +1,119 @@
+/*
+ * 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 <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>
+#include <android/hardware/cas/1.2/ICasListener.h>
+#include <android/hardware/cas/1.2/IMediaCasService.h>
+#include <android/hardware/cas/1.2/types.h>
+#include <android/hardware/tv/tuner/1.0/IDescrambler.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 <fmq/MessageQueue.h>
+#include <hidl/Status.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <fstream>
+#include <iostream>
+#include <map>
+
+using android::Condition;
+using android::Mutex;
+using android::sp;
+using android::hardware::EventFlag;
+using android::hardware::hidl_handle;
+using android::hardware::hidl_string;
+using android::hardware::hidl_vec;
+using android::hardware::kSynchronizedReadWrite;
+using android::hardware::MessageQueue;
+using android::hardware::MQDescriptorSync;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::cas::V1_2::ICas;
+using android::hardware::cas::V1_2::ICasListener;
+using android::hardware::cas::V1_2::IMediaCasService;
+using android::hardware::cas::V1_2::ScramblingMode;
+using android::hardware::cas::V1_2::SessionIntent;
+using android::hardware::cas::V1_2::Status;
+using android::hardware::cas::V1_2::StatusEvent;
+using android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
+using android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
+using android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
+using android::hardware::tv::tuner::V1_0::DemuxFilterType;
+using android::hardware::tv::tuner::V1_0::DemuxMmtpFilterType;
+using android::hardware::tv::tuner::V1_0::DemuxPid;
+using android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
+using android::hardware::tv::tuner::V1_0::IDescrambler;
+using android::hardware::tv::tuner::V1_0::IFilter;
+using android::hardware::tv::tuner::V1_0::ITuner;
+using android::hardware::tv::tuner::V1_0::Result;
+using android::hardware::tv::tuner::V1_0::TunerKeyToken;
+
+using ::testing::AssertionResult;
+
+class MediaCasListener : public ICasListener {
+  public:
+    virtual Return<void> onEvent(int32_t /*event*/, int32_t /*arg*/,
+                                 const hidl_vec<uint8_t>& /*data*/) override {
+        return Void();
+    }
+
+    virtual Return<void> onSessionEvent(const hidl_vec<uint8_t>& /*sessionId*/, int32_t /*event*/,
+                                        int32_t /*arg*/,
+                                        const hidl_vec<uint8_t>& /*data*/) override {
+        return Void();
+    }
+
+    virtual Return<void> onStatusUpdate(StatusEvent /*event*/, int32_t /*arg*/) override {
+        return Void();
+    }
+};
+
+class DescramblerTests {
+  public:
+    void setService(sp<ITuner> tuner) { mService = tuner; }
+    void setCasService(sp<IMediaCasService> casService) { mMediaCasService = casService; }
+
+    AssertionResult setKeyToken(TunerKeyToken token);
+    AssertionResult openDescrambler(uint32_t demuxId);
+    AssertionResult addPid(DemuxPid pid, sp<IFilter> optionalSourceFilter);
+    AssertionResult removePid(DemuxPid pid, sp<IFilter> optionalSourceFilter);
+    AssertionResult closeDescrambler();
+    AssertionResult getKeyToken(int32_t caSystemId, string provisonStr,
+                                hidl_vec<uint8_t> hidlPvtData, TunerKeyToken& token);
+    AssertionResult getDemuxPidFromFilterSettings(DemuxFilterType type,
+                                                  DemuxFilterSettings settings, DemuxPid& pid);
+
+  protected:
+    static AssertionResult failure() { return ::testing::AssertionFailure(); }
+
+    static AssertionResult success() { return ::testing::AssertionSuccess(); }
+
+    sp<ITuner> mService;
+    sp<ICas> mCas;
+    sp<IMediaCasService> mMediaCasService;
+    sp<MediaCasListener> mCasListener;
+    sp<IDescrambler> mDescrambler;
+
+  private:
+    AssertionResult openCasSession(TunerKeyToken& sessionId, vector<uint8_t> hidlPvtData);
+    AssertionResult createCasPlugin(int32_t caSystemId);
+};
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
index 9ac42da..a365282 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
@@ -18,53 +18,17 @@
 
 namespace {
 
-AssertionResult TunerHidlTest::createDescrambler(uint32_t demuxId) {
-    Result status;
-    mService->openDescrambler([&](Result result, const sp<IDescrambler>& descrambler) {
-        mDescrambler = descrambler;
-        status = result;
-    });
-    if (status != Result::SUCCESS) {
-        return failure();
-    }
-
-    status = mDescrambler->setDemuxSource(demuxId);
-    if (status != Result::SUCCESS) {
-        return failure();
-    }
-
-    // Test if demux source can be set more than once.
-    status = mDescrambler->setDemuxSource(demuxId);
-    return AssertionResult(status == Result::INVALID_STATE);
-}
-
-AssertionResult TunerHidlTest::closeDescrambler() {
-    Result status;
-    EXPECT_TRUE(mDescrambler);
-
-    status = mDescrambler->close();
-    mDescrambler = nullptr;
-    return AssertionResult(status == Result::SUCCESS);
-}
-
 AssertionResult TunerBroadcastHidlTest::filterDataOutputTest(vector<string> /*goldenOutputFiles*/) {
-    // Data Verify Module
-    std::map<uint32_t, sp<FilterCallback>>::iterator it;
-    std::map<uint32_t, sp<FilterCallback>> filterCallbacks = mFilterTests.getFilterCallbacks();
-    for (it = filterCallbacks.begin(); it != filterCallbacks.end(); it++) {
-        it->second->testFilterDataOutput();
-    }
-    return success();
+    return filterDataOutputTestBase(mFilterTests);
 }
 
 AssertionResult TunerPlaybackHidlTest::filterDataOutputTest(vector<string> /*goldenOutputFiles*/) {
-    // Data Verify Module
-    std::map<uint32_t, sp<FilterCallback>>::iterator it;
-    std::map<uint32_t, sp<FilterCallback>> filterCallbacks = mFilterTests.getFilterCallbacks();
-    for (it = filterCallbacks.begin(); it != filterCallbacks.end(); it++) {
-        it->second->testFilterDataOutput();
-    }
-    return success();
+    return filterDataOutputTestBase(mFilterTests);
+}
+
+AssertionResult TunerDescramblerHidlTest::filterDataOutputTest(
+        vector<string> /*goldenOutputFiles*/) {
+    return filterDataOutputTestBase(mFilterTests);
 }
 
 void TunerFilterHidlTest::configSingleFilterInDemuxTest(FilterConfig filterConf,
@@ -233,6 +197,69 @@
     ASSERT_TRUE(mFrontendTests.closeFrontend());
 }
 
+void TunerDescramblerHidlTest::scrambledBroadcastTest(set<struct FilterConfig> mediaFilterConfs,
+                                                      FrontendConfig frontendConf,
+                                                      DescramblerConfig descConfig) {
+    uint32_t feId;
+    uint32_t demuxId;
+    sp<IDemux> demux;
+    set<uint32_t> filterIds;
+    uint32_t filterId;
+    set<struct FilterConfig>::iterator config;
+    set<uint32_t>::iterator id;
+
+    mFrontendTests.getFrontendIdByType(frontendConf.type, feId);
+    if (feId == INVALID_ID) {
+        // TODO broadcast test on Cuttlefish needs licensed ts input,
+        // these tests are runnable on vendor device with real frontend module
+        // or with manual ts installing and use DVBT frontend.
+        return;
+    }
+    ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
+    ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+    ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+    ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+    mFilterTests.setDemux(demux);
+    for (config = mediaFilterConfs.begin(); config != mediaFilterConfs.end(); config++) {
+        ASSERT_TRUE(mFilterTests.openFilterInDemux((*config).type, (*config).bufferSize));
+        ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
+        ASSERT_TRUE(mFilterTests.configFilter((*config).settings, filterId));
+        filterIds.insert(filterId);
+    }
+    mDescramblerTests.openDescrambler(demuxId);
+    TunerKeyToken token;
+    ASSERT_TRUE(mDescramblerTests.getKeyToken(descConfig.casSystemId, descConfig.provisionStr,
+                                              descConfig.hidlPvtData, token));
+    mDescramblerTests.setKeyToken(token);
+    vector<DemuxPid> pids;
+    DemuxPid pid;
+    for (config = mediaFilterConfs.begin(); config != mediaFilterConfs.end(); config++) {
+        ASSERT_TRUE(mDescramblerTests.getDemuxPidFromFilterSettings((*config).type,
+                                                                    (*config).settings, pid));
+        pids.push_back(pid);
+        mDescramblerTests.addPid(pid, nullptr);
+    }
+    for (id = filterIds.begin(); id != filterIds.end(); id++) {
+        ASSERT_TRUE(mFilterTests.startFilter(*id));
+    }
+    // tune test
+    ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf));
+    ASSERT_TRUE(filterDataOutputTest(goldenOutputFiles));
+    ASSERT_TRUE(mFrontendTests.stopTuneFrontend());
+    for (id = filterIds.begin(); id != filterIds.end(); id++) {
+        ASSERT_TRUE(mFilterTests.stopFilter(*id));
+    }
+    for (auto pid : pids) {
+        mDescramblerTests.removePid(pid, nullptr);
+    }
+    mDescramblerTests.closeDescrambler();
+    for (id = filterIds.begin(); id != filterIds.end(); id++) {
+        ASSERT_TRUE(mFilterTests.closeFilter(*id));
+    }
+    ASSERT_TRUE(mDemuxTests.closeDemux());
+    ASSERT_TRUE(mFrontendTests.closeFrontend());
+}
+
 TEST_P(TunerFrontendHidlTest, TuneFrontend) {
     description("Tune one Frontend with specific setting and check Lock event");
     mFrontendTests.tuneTest(frontendArray[DVBT]);
@@ -341,7 +368,7 @@
     recordSingleFilterTest(filterArray[TS_RECORD0], frontendArray[DVBT], dvrArray[DVR_RECORD0]);
 }
 
-TEST_P(TunerHidlTest, CreateDescrambler) {
+TEST_P(TunerDescramblerHidlTest, CreateDescrambler) {
     description("Create Descrambler");
     uint32_t feId;
     uint32_t demuxId;
@@ -352,13 +379,21 @@
     ASSERT_TRUE(mFrontendTests.setFrontendCallback());
     ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
     ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
-    ASSERT_TRUE(createDescrambler(demuxId));
-    ASSERT_TRUE(closeDescrambler());
+    mDescramblerTests.openDescrambler(demuxId);
+    mDescramblerTests.closeDescrambler();
     ASSERT_TRUE(mDemuxTests.closeDemux());
     ASSERT_TRUE(mFrontendTests.closeFrontend());
 }
 
-INSTANTIATE_TEST_SUITE_P(
+TEST_P(TunerDescramblerHidlTest, ScrambledBroadcastDataFlowMediaFiltersTest) {
+    description("Test ts audio filter in scrambled broadcast use case");
+    set<FilterConfig> filterConfs;
+    filterConfs.insert(filterArray[TS_AUDIO0]);
+    filterConfs.insert(filterArray[TS_VIDEO1]);
+    scrambledBroadcastTest(filterConfs, frontendArray[DVBT], descramblerArray[DESC_0]);
+}
+
+/*INSTANTIATE_TEST_SUITE_P(
         PerInstance, TunerFrontendHidlTest,
         testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
         android::hardware::PrintInstanceNameToString);
@@ -386,10 +421,10 @@
 INSTANTIATE_TEST_SUITE_P(
         PerInstance, TunerRecordHidlTest,
         testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
-        android::hardware::PrintInstanceNameToString);
+        android::hardware::PrintInstanceNameToString);*/
 
 INSTANTIATE_TEST_SUITE_P(
-        PerInstance, TunerHidlTest,
+        PerInstance, TunerDescramblerHidlTest,
         testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
         android::hardware::PrintInstanceNameToString);
 }  // namespace
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
index 6dddc38..2bdb537 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
@@ -14,19 +14,14 @@
  * limitations under the License.
  */
 
-#include <android/hardware/tv/tuner/1.0/IDescrambler.h>
-
 #include "DemuxTests.h"
+#include "DescramblerTests.h"
 #include "DvrTests.h"
 #include "FrontendTests.h"
 
 using android::hardware::tv::tuner::V1_0::DataFormat;
 using android::hardware::tv::tuner::V1_0::IDescrambler;
 
-static AssertionResult failure() {
-    return ::testing::AssertionFailure();
-}
-
 static AssertionResult success() {
     return ::testing::AssertionSuccess();
 }
@@ -38,6 +33,17 @@
     initFrontendScanConfig();
     initFilterConfig();
     initDvrConfig();
+    initDescramblerConfig();
+}
+
+AssertionResult filterDataOutputTestBase(FilterTests tests) {
+    // Data Verify Module
+    std::map<uint32_t, sp<FilterCallback>>::iterator it;
+    std::map<uint32_t, sp<FilterCallback>> filterCallbacks = tests.getFilterCallbacks();
+    for (it = filterCallbacks.begin(); it != filterCallbacks.end(); it++) {
+        it->second->testFilterDataOutput();
+    }
+    return success();
 }
 
 class TunerFrontendHidlTest : public testing::TestWithParam<std::string> {
@@ -193,15 +199,19 @@
     DvrTests mDvrTests;
 };
 
-class TunerHidlTest : public testing::TestWithParam<std::string> {
+class TunerDescramblerHidlTest : public testing::TestWithParam<std::string> {
   public:
     virtual void SetUp() override {
         mService = ITuner::getService(GetParam());
+        mCasService = IMediaCasService::getService();
         ASSERT_NE(mService, nullptr);
+        ASSERT_NE(mCasService, nullptr);
         initConfiguration();
 
         mFrontendTests.setService(mService);
         mDemuxTests.setService(mService);
+        mDescramblerTests.setService(mService);
+        mDescramblerTests.setCasService(mCasService);
     }
 
   protected:
@@ -209,13 +219,15 @@
         RecordProperty("description", description);
     }
 
+    void scrambledBroadcastTest(set<struct FilterConfig> mediaFilterConfs,
+                                FrontendConfig frontendConf, DescramblerConfig descConfig);
+    AssertionResult filterDataOutputTest(vector<string> /*goldenOutputFiles*/);
+
     sp<ITuner> mService;
+    sp<IMediaCasService> mCasService;
     FrontendTests mFrontendTests;
     DemuxTests mDemuxTests;
-
-    sp<IDescrambler> mDescrambler;
-
-    AssertionResult createDescrambler(uint32_t demuxId);
-    AssertionResult closeDescrambler();
+    FilterTests mFilterTests;
+    DescramblerTests mDescramblerTests;
 };
 }  // namespace
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
index 287f673..f2dd197 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
@@ -52,6 +52,19 @@
 const uint32_t FMQ_SIZE_4M = 0x400000;
 const uint32_t FMQ_SIZE_16M = 0x1000000;
 
+#define CLEAR_KEY_SYSTEM_ID 0xF6D8
+#define PROVISION_STR                                      \
+    "{                                                   " \
+    "  \"id\": 21140844,                                 " \
+    "  \"name\": \"Test Title\",                         " \
+    "  \"lowercase_organization_name\": \"Android\",     " \
+    "  \"asset_key\": {                                  " \
+    "  \"encryption_key\": \"nezAr3CHFrmBR9R8Tedotw==\"  " \
+    "  },                                                " \
+    "  \"cas_type\": 1,                                  " \
+    "  \"track_types\": [ ]                              " \
+    "}                                                   "
+
 typedef enum {
     TS_VIDEO0,
     TS_VIDEO1,
@@ -81,10 +94,17 @@
     DVR_MAX,
 } Dvr;
 
+typedef enum {
+    DESC_0,
+    DESC_MAX,
+} Descrambler;
+
 struct FilterConfig {
     uint32_t bufferSize;
     DemuxFilterType type;
     DemuxFilterSettings settings;
+
+    bool operator<(const FilterConfig& /*c*/) const { return false; }
 };
 
 struct FrontendConfig {
@@ -109,11 +129,18 @@
     string playbackInputFile;
 };
 
+struct DescramblerConfig {
+    uint32_t casSystemId;
+    string provisionStr;
+    vector<uint8_t> hidlPvtData;
+};
+
 static FrontendConfig frontendArray[FILTER_MAX];
 static FrontendConfig frontendScanArray[SCAN_MAX];
 static ChannelConfig channelArray[FRONTEND_MAX];
 static FilterConfig filterArray[FILTER_MAX];
 static DvrConfig dvrArray[DVR_MAX];
+static DescramblerConfig descramblerArray[DESC_MAX];
 static vector<string> goldenOutputFiles;
 
 /** Configuration array for the frontend tune test */
@@ -240,3 +267,10 @@
     dvrArray[DVR_PLAYBACK0].bufferSize = FMQ_SIZE_4M;
     dvrArray[DVR_PLAYBACK0].settings.playback(playbackSettings);
 };
+
+/** Configuration array for the descrambler test */
+inline void initDescramblerConfig() {
+    descramblerArray[DESC_0].casSystemId = CLEAR_KEY_SYSTEM_ID;
+    descramblerArray[DESC_0].provisionStr = PROVISION_STR;
+    descramblerArray[DESC_0].hidlPvtData.resize(256);
+};