drm_hal_vendor_test.cpp revision 4e7a3077309d33a21b08e9380573019cc7a8cffb
10ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/*
20ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Copyright (C) 2017 The Android Open Source Project
30ea406920af8313875866f13c9104129c08b2d76Jeff Tinker *
40ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Licensed under the Apache License, Version 2.0 (the "License");
50ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * you may not use this file except in compliance with the License.
60ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * You may obtain a copy of the License at
70ea406920af8313875866f13c9104129c08b2d76Jeff Tinker *
80ea406920af8313875866f13c9104129c08b2d76Jeff Tinker *      http://www.apache.org/licenses/LICENSE-2.0
90ea406920af8313875866f13c9104129c08b2d76Jeff Tinker *
100ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Unless required by applicable law or agreed to in writing, software
110ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * distributed under the License is distributed on an "AS IS" BASIS,
120ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * See the License for the specific language governing permissions and
140ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * limitations under the License.
150ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
160ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
170ea406920af8313875866f13c9104129c08b2d76Jeff Tinker#define LOG_TAG "drm_hal_vendor_test@1.0"
180ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
190ea406920af8313875866f13c9104129c08b2d76Jeff Tinker#include <android-base/logging.h>
200ea406920af8313875866f13c9104129c08b2d76Jeff Tinker#include <android/hardware/drm/1.0/ICryptoFactory.h>
210ea406920af8313875866f13c9104129c08b2d76Jeff Tinker#include <android/hardware/drm/1.0/ICryptoPlugin.h>
220ea406920af8313875866f13c9104129c08b2d76Jeff Tinker#include <android/hardware/drm/1.0/IDrmFactory.h>
230ea406920af8313875866f13c9104129c08b2d76Jeff Tinker#include <android/hardware/drm/1.0/IDrmPlugin.h>
24f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker#include <android/hardware/drm/1.0/IDrmPluginListener.h>
250ea406920af8313875866f13c9104129c08b2d76Jeff Tinker#include <android/hardware/drm/1.0/types.h>
260ea406920af8313875866f13c9104129c08b2d76Jeff Tinker#include <android/hidl/allocator/1.0/IAllocator.h>
270ea406920af8313875866f13c9104129c08b2d76Jeff Tinker#include <gtest/gtest.h>
280ea406920af8313875866f13c9104129c08b2d76Jeff Tinker#include <hidlmemory/mapping.h>
294e7a3077309d33a21b08e9380573019cc7a8cffbSteven Moreland#include <log/log.h>
30f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker#include <openssl/aes.h>
314e7a3077309d33a21b08e9380573019cc7a8cffbSteven Moreland#include <memory>
320ea406920af8313875866f13c9104129c08b2d76Jeff Tinker#include <random>
330ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
340ea406920af8313875866f13c9104129c08b2d76Jeff Tinker#include "drm_hal_vendor_module_api.h"
350ea406920af8313875866f13c9104129c08b2d76Jeff Tinker#include "vendor_modules.h"
36f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker#include "VtsHalHidlTargetTestBase.h"
370ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
380ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing ::android::hardware::drm::V1_0::BufferType;
390ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing ::android::hardware::drm::V1_0::DestinationBuffer;
40f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinkerusing ::android::hardware::drm::V1_0::EventType;
410ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing ::android::hardware::drm::V1_0::ICryptoFactory;
420ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing ::android::hardware::drm::V1_0::ICryptoPlugin;
430ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing ::android::hardware::drm::V1_0::IDrmFactory;
440ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing ::android::hardware::drm::V1_0::IDrmPlugin;
45f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinkerusing ::android::hardware::drm::V1_0::IDrmPluginListener;
460ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing ::android::hardware::drm::V1_0::KeyedVector;
470ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing ::android::hardware::drm::V1_0::KeyRequestType;
48f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinkerusing ::android::hardware::drm::V1_0::KeyStatus;
49f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinkerusing ::android::hardware::drm::V1_0::KeyStatusType;
500ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing ::android::hardware::drm::V1_0::KeyType;
51f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinkerusing ::android::hardware::drm::V1_0::KeyValue;
520ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing ::android::hardware::drm::V1_0::Mode;
530ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing ::android::hardware::drm::V1_0::Pattern;
540ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing ::android::hardware::drm::V1_0::SecureStop;
550ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing ::android::hardware::drm::V1_0::SecureStopId;
560ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing ::android::hardware::drm::V1_0::SessionId;
570ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing ::android::hardware::drm::V1_0::SharedBuffer;
580ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing ::android::hardware::drm::V1_0::Status;
590ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing ::android::hardware::drm::V1_0::SubSample;
600ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
610ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing ::android::hardware::hidl_array;
620ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing ::android::hardware::hidl_memory;
630ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing ::android::hardware::hidl_string;
640ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing ::android::hardware::hidl_vec;
650ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing ::android::hardware::Return;
66f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinkerusing ::android::hardware::Void;
670ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing ::android::hidl::allocator::V1_0::IAllocator;
680ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing ::android::hidl::memory::V1_0::IMemory;
690ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing ::android::sp;
700ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
710ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing std::string;
720ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing std::unique_ptr;
730ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing std::random_device;
740ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing std::map;
750ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing std::mt19937;
760ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerusing std::vector;
770ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
78f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinkerusing ContentConfiguration = ::DrmHalVTSVendorModule_V1::ContentConfiguration;
79f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinkerusing Key = ::DrmHalVTSVendorModule_V1::ContentConfiguration::Key;
80f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
810ea406920af8313875866f13c9104129c08b2d76Jeff Tinker#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
820ea406920af8313875866f13c9104129c08b2d76Jeff Tinker#define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk())
830ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
840ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerstatic const uint8_t kInvalidUUID[16] = {
850ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
860ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
870ea406920af8313875866f13c9104129c08b2d76Jeff Tinker};
880ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
890ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerstatic drm_vts::VendorModules* gVendorModules = nullptr;
900ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
910ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerclass DrmHalVendorFactoryTest : public testing::TestWithParam<std::string> {
920ea406920af8313875866f13c9104129c08b2d76Jeff Tinker   public:
930ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    DrmHalVendorFactoryTest()
94f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        : vendorModule(static_cast<DrmHalVTSVendorModule_V1*>(
95f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                        gVendorModules->getModule(GetParam()))),
96f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker          contentConfigurations(vendorModule->getContentConfigurations()) {}
970ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
980ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    virtual ~DrmHalVendorFactoryTest() {}
990ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
1000ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    virtual void SetUp() {
1010ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        const ::testing::TestInfo* const test_info =
1020ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                ::testing::UnitTest::GetInstance()->current_test_info();
1030ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        ALOGD("Running test %s.%s from vendor module %s",
1040ea406920af8313875866f13c9104129c08b2d76Jeff Tinker              test_info->test_case_name(), test_info->name(),
1050ea406920af8313875866f13c9104129c08b2d76Jeff Tinker              GetParam().c_str());
1060ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
1070ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        ASSERT_NE(vendorModule, nullptr);
1080ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        string name = vendorModule->getServiceName();
1090ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        drmFactory =
1100ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                ::testing::VtsHalHidlTargetTestBase::getService<IDrmFactory>(
1110ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                        name != "default" ? name : "drm");
1120ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        ASSERT_NE(drmFactory, nullptr);
1130ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        cryptoFactory =
1140ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                ::testing::VtsHalHidlTargetTestBase::getService<ICryptoFactory>(
1150ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                        name != "default" ? name : "crypto");
1160ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        ASSERT_NE(cryptoFactory, nullptr);
1170ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    }
1180ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
1190ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    virtual void TearDown() override {}
1200ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
1210ea406920af8313875866f13c9104129c08b2d76Jeff Tinker   protected:
1220ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_array<uint8_t, 16> getVendorUUID() {
1230ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        vector<uint8_t> uuid = vendorModule->getUUID();
1240ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        return hidl_array<uint8_t, 16>(&uuid[0]);
1250ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    }
1260ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
1270ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    sp<IDrmFactory> drmFactory;
1280ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    sp<ICryptoFactory> cryptoFactory;
1290ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    unique_ptr<DrmHalVTSVendorModule_V1> vendorModule;
130f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    const vector<ContentConfiguration> contentConfigurations;
1310ea406920af8313875866f13c9104129c08b2d76Jeff Tinker};
1320ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
133f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff TinkerTEST_P(DrmHalVendorFactoryTest, ValidateConfigurations) {
134f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    const char* kVendorStr = "Vendor module ";
135f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    for (auto config : contentConfigurations) {
136f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        ASSERT_TRUE(config.name.size() > 0) << kVendorStr << "has no name";
137f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        ASSERT_TRUE(config.serverUrl.size() > 0) << kVendorStr
138f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                                                 << "has no serverUrl";
139f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        ASSERT_TRUE(config.initData.size() > 0) << kVendorStr
140f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                                                << "has no init data";
141f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        ASSERT_TRUE(config.mimeType.size() > 0) << kVendorStr
142f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                                                << "has no mime type";
143f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        ASSERT_TRUE(config.keys.size() >= 1) << kVendorStr << "has no keys";
144f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        for (auto key : config.keys) {
145f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            ASSERT_TRUE(key.keyId.size() > 0) << kVendorStr
146f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                                              << " has zero length keyId";
147f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            ASSERT_TRUE(key.keyId.size() > 0) << kVendorStr
148f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                                              << " has zero length key value";
149f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        }
150f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    }
1510ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
1520ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
1530ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
1540ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Ensure the factory doesn't support an invalid scheme UUID
1550ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
1560ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorFactoryTest, InvalidPluginNotSupported) {
1570ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_FALSE(drmFactory->isCryptoSchemeSupported(kInvalidUUID));
1580ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_FALSE(cryptoFactory->isCryptoSchemeSupported(kInvalidUUID));
1590ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
1600ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
1610ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
162f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * Ensure the factory doesn't support an empty UUID
163f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker */
164f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff TinkerTEST_P(DrmHalVendorFactoryTest, EmptyPluginUUIDNotSupported) {
165f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    hidl_array<uint8_t, 16> emptyUUID;
166f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    EXPECT_FALSE(drmFactory->isCryptoSchemeSupported(emptyUUID));
167f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    EXPECT_FALSE(cryptoFactory->isCryptoSchemeSupported(emptyUUID));
168f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker}
169f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
170f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker/**
171f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * Ensure the factory supports the scheme uuid in the config
172f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker */
173f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff TinkerTEST_P(DrmHalVendorFactoryTest, EmptyPluginConfigUUIDSupported) {
174f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    EXPECT_TRUE(drmFactory->isCryptoSchemeSupported(getVendorUUID()));
175f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    EXPECT_TRUE(cryptoFactory->isCryptoSchemeSupported(getVendorUUID()));
176f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker}
177f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
178f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker/**
179f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * Ensure empty content type is not supported
180f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker */
181f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff TinkerTEST_P(DrmHalVendorFactoryTest, EmptyContentTypeNotSupported) {
182f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    hidl_string empty;
183f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    EXPECT_FALSE(drmFactory->isContentTypeSupported(empty));
184f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker}
185f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
186f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker/**
187f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * Ensure invalid content type is not supported
188f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker */
189f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff TinkerTEST_P(DrmHalVendorFactoryTest, InvalidContentTypeNotSupported) {
190f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    hidl_string invalid("abcdabcd");
191f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    EXPECT_FALSE(drmFactory->isContentTypeSupported(invalid));
192f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker}
193f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
194f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker/**
195f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * Ensure valid content types in the configs are supported
196f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker */
197f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff TinkerTEST_P(DrmHalVendorFactoryTest, ValidContentTypeSupported) {
198f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    for (auto config : contentConfigurations) {
199f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        EXPECT_TRUE(drmFactory->isContentTypeSupported(config.mimeType));
200f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    }
201f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker}
202f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
203f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker/**
2040ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Ensure vendor drm plugin can be created
2050ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
2060ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorFactoryTest, CreateVendorDrmPlugin) {
2070ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_string packageName("android.hardware.drm.test");
2080ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto res = drmFactory->createPlugin(
2090ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            getVendorUUID(), packageName,
2100ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            [&](Status status, const sp<IDrmPlugin>& plugin) {
2110ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_EQ(Status::OK, status);
2120ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_NE(plugin, nullptr);
2130ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            });
2140ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_OK(res);
2150ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
2160ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
2170ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
2180ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Ensure vendor crypto plugin can be created
2190ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
2200ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorFactoryTest, CreateVendorCryptoPlugin) {
2210ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_vec<uint8_t> initVec;
2220ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto res = cryptoFactory->createPlugin(
2230ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            getVendorUUID(), initVec,
2240ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            [&](Status status, const sp<ICryptoPlugin>& plugin) {
2250ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_EQ(Status::OK, status);
2260ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_NE(plugin, nullptr);
2270ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            });
2280ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_OK(res);
2290ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
2300ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
2310ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
2320ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Ensure invalid drm plugin can't be created
2330ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
2340ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorFactoryTest, CreateInvalidDrmPlugin) {
2350ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_string packageName("android.hardware.drm.test");
2360ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto res = drmFactory->createPlugin(
2370ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            kInvalidUUID, packageName,
2380ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            [&](Status status, const sp<IDrmPlugin>& plugin) {
2390ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
2400ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_EQ(plugin, nullptr);
2410ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            });
2420ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_OK(res);
2430ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
2440ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
2450ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
2460ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Ensure invalid crypto plugin can't be created
2470ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
2480ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorFactoryTest, CreateInvalidCryptoPlugin) {
2490ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_vec<uint8_t> initVec;
2500ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto res = cryptoFactory->createPlugin(
2510ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            kInvalidUUID, initVec,
2520ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            [&](Status status, const sp<ICryptoPlugin>& plugin) {
2530ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
2540ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_EQ(plugin, nullptr);
2550ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            });
2560ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_OK(res);
2570ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
2580ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
2590ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerclass DrmHalVendorPluginTest : public DrmHalVendorFactoryTest {
2600ea406920af8313875866f13c9104129c08b2d76Jeff Tinker   public:
2610ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    virtual ~DrmHalVendorPluginTest() {}
2620ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    virtual void SetUp() override {
2630ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        // Create factories
2640ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        DrmHalVendorFactoryTest::SetUp();
2650ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
2660ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        hidl_string packageName("android.hardware.drm.test");
2670ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        auto res = drmFactory->createPlugin(
2680ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                getVendorUUID(), packageName,
2690ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                [this](Status status, const sp<IDrmPlugin>& plugin) {
2700ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                    EXPECT_EQ(Status::OK, status);
2710ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                    ASSERT_NE(plugin, nullptr);
2720ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                    drmPlugin = plugin;
2730ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                });
2740ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        ASSERT_OK(res);
2750ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
2760ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        hidl_vec<uint8_t> initVec;
2770ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        res = cryptoFactory->createPlugin(
2780ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                getVendorUUID(), initVec,
2790ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                [this](Status status, const sp<ICryptoPlugin>& plugin) {
2800ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                    EXPECT_EQ(Status::OK, status);
2810ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                    ASSERT_NE(plugin, nullptr);
2820ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                    cryptoPlugin = plugin;
2830ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                });
2840ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        ASSERT_OK(res);
2850ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    }
2860ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
2870ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    virtual void TearDown() override {}
2880ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
2890ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    SessionId openSession();
2900ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    void closeSession(const SessionId& sessionId);
2910ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    sp<IMemory> getDecryptMemory(size_t size, size_t index);
2920ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
2930ea406920af8313875866f13c9104129c08b2d76Jeff Tinker   protected:
2940ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    sp<IDrmPlugin> drmPlugin;
2950ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    sp<ICryptoPlugin> cryptoPlugin;
2960ea406920af8313875866f13c9104129c08b2d76Jeff Tinker};
2970ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
2980ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
2990ea406920af8313875866f13c9104129c08b2d76Jeff Tinker *  DrmPlugin tests
3000ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
3010ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
3020ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
3030ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Test that a DRM plugin can handle provisioning.  While
3040ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * it is not required that a DRM scheme require provisioning,
3050ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * it should at least return appropriate status values. If
3060ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * a provisioning request is returned, it is passed to the
3070ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * vendor module which should provide a provisioning response
3080ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * that is delivered back to the HAL.
3090ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
3100ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
3110ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, DoProvisioning) {
3120ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_string certificateType;
3130ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_string certificateAuthority;
3140ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_vec<uint8_t> provisionRequest;
3150ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_string defaultUrl;
3160ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto res = drmPlugin->getProvisionRequest(
3170ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            certificateType, certificateAuthority,
3180ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            [&](Status status, const hidl_vec<uint8_t>& request,
3190ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                const hidl_string& url) {
3200ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                if (status == Status::OK) {
3210ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                    EXPECT_NE(request.size(), 0u);
3220ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                    provisionRequest = request;
3230ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                    defaultUrl = url;
3240ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                } else if (status == Status::ERROR_DRM_CANNOT_HANDLE) {
3250ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                    EXPECT_EQ(0u, request.size());
3260ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                }
3270ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            });
3280ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_OK(res);
3290ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
3300ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    if (provisionRequest.size() > 0) {
3310ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        vector<uint8_t> response = vendorModule->handleProvisioningRequest(
3320ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                provisionRequest, defaultUrl);
3330ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        ASSERT_NE(0u, response.size());
3340ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
3350ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        auto res = drmPlugin->provideProvisionResponse(
3360ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                response, [&](Status status, const hidl_vec<uint8_t>&,
3370ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                              const hidl_vec<uint8_t>&) {
3380ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                    EXPECT_EQ(Status::OK, status);
3390ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                });
3400ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        EXPECT_OK(res);
3410ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    }
3420ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
3430ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
3440ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
3450ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * The DRM HAL should return BAD_VALUE if an empty provisioning
3460ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * response is provided.
3470ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
3480ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, ProvideEmptyProvisionResponse) {
3490ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_vec<uint8_t> response;
3500ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto res = drmPlugin->provideProvisionResponse(
3510ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            response, [&](Status status, const hidl_vec<uint8_t>&,
3520ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                          const hidl_vec<uint8_t>&) {
3530ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_EQ(Status::BAD_VALUE, status);
3540ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            });
3550ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_OK(res);
3560ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
3570ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
3580ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
3590ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Helper method to open a session and verify that a non-empty
3600ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * session ID is returned
3610ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
3620ea406920af8313875866f13c9104129c08b2d76Jeff TinkerSessionId DrmHalVendorPluginTest::openSession() {
3630ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    SessionId sessionId;
3640ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
3650ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto res = drmPlugin->openSession([&](Status status, const SessionId& id) {
3660ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        EXPECT_EQ(Status::OK, status);
3670ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        EXPECT_NE(id.size(), 0u);
3680ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        sessionId = id;
3690ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    });
3700ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_OK(res);
3710ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    return sessionId;
3720ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
3730ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
3740ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
3750ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Helper method to close a session
3760ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
3770ea406920af8313875866f13c9104129c08b2d76Jeff Tinkervoid DrmHalVendorPluginTest::closeSession(const SessionId& sessionId) {
3780ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    Status status = drmPlugin->closeSession(sessionId);
3790ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_EQ(Status::OK, status);
3800ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
3810ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
3820ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
3830ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Test that a session can be opened and closed
3840ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
3850ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, OpenCloseSession) {
3860ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto sessionId = openSession();
3870ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    closeSession(sessionId);
3880ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
3890ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
3900ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
3910ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Test that attempting to close an invalid (empty) sessionId
3920ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * is prohibited with the documented error code.
3930ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
3940ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, CloseInvalidSession) {
3950ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    SessionId invalidSessionId;
3960ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    Status status = drmPlugin->closeSession(invalidSessionId);
3970ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_EQ(Status::BAD_VALUE, status);
3980ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
3990ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
4000ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
4010ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Test that attempting to close a valid session twice
4020ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * is prohibited with the documented error code.
4030ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
4040ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, CloseClosedSession) {
4050ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto sessionId = openSession();
4060ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    closeSession(sessionId);
4070ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    Status status = drmPlugin->closeSession(sessionId);
4080ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
4090ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
4100ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
4110ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
4120ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * A get key request should fail if no sessionId is provided
4130ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
4140ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, GetKeyRequestNoSession) {
4150ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    SessionId invalidSessionId;
4160ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_vec<uint8_t> initData;
4170ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_string mimeType = "video/mp4";
4180ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    KeyedVector optionalParameters;
4190ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto res = drmPlugin->getKeyRequest(
4200ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            invalidSessionId, initData, mimeType, KeyType::STREAMING,
4210ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            optionalParameters,
4220ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            [&](Status status, const hidl_vec<uint8_t>&, KeyRequestType,
4230ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                const hidl_string&) { EXPECT_EQ(Status::BAD_VALUE, status); });
4240ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_OK(res);
4250ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
4260ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
4270ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
4280ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Test that an empty sessionID returns BAD_VALUE
4290ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
4300ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, ProvideKeyResponseEmptySessionId) {
4310ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    SessionId session;
4320ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
4330ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_vec<uint8_t> keyResponse = {0x7b, 0x22, 0x6b, 0x65,
4340ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                                     0x79, 0x73, 0x22, 0x3a};
4350ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto res = drmPlugin->provideKeyResponse(
4360ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            session, keyResponse,
4370ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            [&](Status status, const hidl_vec<uint8_t>& keySetId) {
4380ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_EQ(Status::BAD_VALUE, status);
4390ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_EQ(keySetId.size(), 0u);
4400ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            });
4410ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_OK(res);
4420ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
4430ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
4440ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
4450ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Test that an empty key response returns BAD_VALUE
4460ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
4470ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, ProvideKeyResponseEmptyResponse) {
4480ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    SessionId session = openSession();
4490ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_vec<uint8_t> emptyResponse;
4500ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto res = drmPlugin->provideKeyResponse(
4510ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            session, emptyResponse,
4520ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            [&](Status status, const hidl_vec<uint8_t>& keySetId) {
4530ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_EQ(Status::BAD_VALUE, status);
4540ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_EQ(keySetId.size(), 0u);
4550ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            });
4560ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_OK(res);
4570ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    closeSession(session);
4580ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
4590ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
4600ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
461f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * Test that a removeKeys on an empty sessionID returns BAD_VALUE
462f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker */
463f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff TinkerTEST_P(DrmHalVendorPluginTest, RemoveKeysEmptySessionId) {
464f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    SessionId sessionId;
465f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    Status status = drmPlugin->removeKeys(sessionId);
466f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    EXPECT_TRUE(status == Status::BAD_VALUE);
467f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker}
468f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
469f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker/**
470f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * Test that remove keys returns okay on an initialized session
471f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * that has no keys.
472f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker */
473f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff TinkerTEST_P(DrmHalVendorPluginTest, RemoveKeysNewSession) {
474f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    SessionId sessionId = openSession();
475f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    Status status = drmPlugin->removeKeys(sessionId);
476f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    EXPECT_TRUE(status == Status::OK);
477f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    closeSession(sessionId);
478f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker}
479f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
480f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker/**
4810ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Test that the plugin either doesn't support getting
4820ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * secure stops, or has no secure stops available after
4830ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * clearing them.
4840ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
4850ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, GetSecureStops) {
4860ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    // There may be secure stops, depending on if there were keys
4870ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    // loaded and unloaded previously. Clear them to get to a known
4880ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    // state, then make sure there are none.
4890ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto res = drmPlugin->getSecureStops(
4900ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            [&](Status status, const hidl_vec<SecureStop>&) {
4910ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                if (status != Status::OK) {
4920ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                    EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
4930ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                }
4940ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            });
4950ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_OK(res);
4960ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
4970ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    res = drmPlugin->getSecureStops(
4980ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            [&](Status status, const hidl_vec<SecureStop>& secureStops) {
4990ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                if (status == Status::OK) {
5000ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                    EXPECT_EQ(secureStops.size(), 0u);
5010ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                } else {
5020ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                    EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
5030ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                }
5040ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            });
5050ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_OK(res);
5060ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
5070ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
5080ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
5090ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Test that the clearkey plugin returns BAD_VALUE if
5100ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * an empty ssid is provided.
5110ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
5120ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, GetSecureStopEmptySSID) {
5130ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    SecureStopId ssid;
5140ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto res = drmPlugin->getSecureStop(
5150ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            ssid, [&](Status status, const SecureStop&) {
5160ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_EQ(Status::BAD_VALUE, status);
5170ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            });
5180ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_OK(res);
5190ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
5200ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
5210ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
5220ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Test that releasing all secure stops either isn't supported
5230ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * or is completed successfully
5240ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
5250ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, ReleaseAllSecureStops) {
5260ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    Status status = drmPlugin->releaseAllSecureStops();
5270ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_TRUE(status == Status::OK ||
5280ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                status == Status::ERROR_DRM_CANNOT_HANDLE);
5290ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
5300ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
5310ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
5320ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Releasing a secure stop without first getting one and sending it to the
5330ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * server to get a valid SSID should return ERROR_DRM_INVALID_STATE.
5340ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * This is an optional API so it can also return CANNOT_HANDLE.
5350ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
5360ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, ReleaseSecureStopSequenceError) {
5370ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    SecureStopId ssid = {1, 2, 3, 4};
5380ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    Status status = drmPlugin->releaseSecureStop(ssid);
5390ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_TRUE(status == Status::ERROR_DRM_INVALID_STATE ||
5400ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                status == Status::ERROR_DRM_CANNOT_HANDLE);
5410ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
5420ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
5430ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
5440ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Test that releasing a specific secure stop with an empty ssid
5450ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * return BAD_VALUE. This is an optional API so it can also return
5460ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * CANNOT_HANDLE.
5470ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
5480ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, ReleaseSecureStopEmptySSID) {
5490ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    SecureStopId ssid;
5500ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    Status status = drmPlugin->releaseSecureStop(ssid);
5510ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_TRUE(status == Status::BAD_VALUE ||
5520ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                status == Status::ERROR_DRM_CANNOT_HANDLE);
5530ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
5540ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
5550ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
5560ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * The following five tests verify that the properties
5570ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * defined in the MediaDrm API are supported by
5580ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * the plugin.
5590ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
5600ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, GetVendorProperty) {
5610ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto res = drmPlugin->getPropertyString(
5620ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            "vendor", [&](Status status, const hidl_string& value) {
5630ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_EQ(Status::OK, status);
5640ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_NE(value.size(), 0u);
5650ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            });
5660ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_OK(res);
5670ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
5680ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
5690ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, GetVersionProperty) {
5700ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto res = drmPlugin->getPropertyString(
5710ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            "version", [&](Status status, const hidl_string& value) {
5720ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_EQ(Status::OK, status);
5730ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_NE(value.size(), 0u);
5740ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            });
5750ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_OK(res);
5760ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
5770ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
5780ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, GetDescriptionProperty) {
5790ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto res = drmPlugin->getPropertyString(
5800ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            "description", [&](Status status, const hidl_string& value) {
5810ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_EQ(Status::OK, status);
5820ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_NE(value.size(), 0u);
5830ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            });
5840ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_OK(res);
5850ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
5860ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
5870ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, GetAlgorithmsProperty) {
5880ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto res = drmPlugin->getPropertyString(
5890ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            "algorithms", [&](Status status, const hidl_string& value) {
5900ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                if (status == Status::OK) {
5910ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                    EXPECT_NE(value.size(), 0u);
5920ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                } else {
5930ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                    EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
5940ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                }
5950ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            });
5960ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_OK(res);
5970ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
5980ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
5990ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, GetPropertyUniqueDeviceID) {
6000ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto res = drmPlugin->getPropertyByteArray(
6010ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            "deviceUniqueId",
6020ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            [&](Status status, const hidl_vec<uint8_t>& value) {
6030ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                if (status == Status::OK) {
6040ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                    EXPECT_NE(value.size(), 0u);
6050ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                } else {
6060ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                    EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
6070ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                }
6080ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            });
6090ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_OK(res);
6100ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
6110ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
6120ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
6130ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Test that attempting to read invalid string and byte array
6140ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * properties returns the documented error code.
6150ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
6160ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, GetInvalidStringProperty) {
6170ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto res = drmPlugin->getPropertyString(
6180ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            "invalid", [&](Status status, const hidl_string&) {
6190ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
6200ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            });
6210ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_OK(res);
6220ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
6230ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
6240ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, GetInvalidByteArrayProperty) {
6250ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto res = drmPlugin->getPropertyByteArray(
6260ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            "invalid", [&](Status status, const hidl_vec<uint8_t>&) {
6270ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
6280ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            });
6290ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_OK(res);
6300ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
6310ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
6320ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
6330ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Test that setting invalid string and byte array properties returns
6340ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * the expected status value.
6350ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
6360ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, SetStringPropertyNotSupported) {
6370ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_EQ(drmPlugin->setPropertyString("awefijaeflijwef", "value"),
6380ea406920af8313875866f13c9104129c08b2d76Jeff Tinker              Status::ERROR_DRM_CANNOT_HANDLE);
6390ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
6400ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
6410ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, SetByteArrayPropertyNotSupported) {
6420ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_vec<uint8_t> value;
6430ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_EQ(drmPlugin->setPropertyByteArray("awefijaeflijwef", value),
6440ea406920af8313875866f13c9104129c08b2d76Jeff Tinker              Status::ERROR_DRM_CANNOT_HANDLE);
6450ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
6460ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
6470ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
6480ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Test that setting an invalid cipher algorithm returns
6490ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * the expected status value.
6500ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
6510ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, SetCipherInvalidAlgorithm) {
6520ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    SessionId session = openSession();
6530ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_string algorithm;
6540ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    Status status = drmPlugin->setCipherAlgorithm(session, algorithm);
6550ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_EQ(Status::BAD_VALUE, status);
6560ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    closeSession(session);
6570ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
6580ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
6590ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
6600ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Test that setting a cipher algorithm with no session returns
6610ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * the expected status value.
6620ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
6630ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, SetCipherAlgorithmNoSession) {
6640ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    SessionId session;
6650ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_string algorithm = "AES/CBC/NoPadding";
6660ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    Status status = drmPlugin->setCipherAlgorithm(session, algorithm);
6670ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_EQ(Status::BAD_VALUE, status);
6680ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
6690ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
6700ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
6710ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Test that setting a valid cipher algorithm returns
6720ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * the expected status value. It is not required that all
6730ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * vendor modules support this algorithm, but they must
6740ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * either accept it or return ERROR_DRM_CANNOT_HANDLE
6750ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
6760ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, SetCipherAlgorithm) {
6770ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    SessionId session = openSession();
6780ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    ;
6790ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_string algorithm = "AES/CBC/NoPadding";
6800ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    Status status = drmPlugin->setCipherAlgorithm(session, algorithm);
6810ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_TRUE(status == Status::OK ||
6820ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                status == Status::ERROR_DRM_CANNOT_HANDLE);
6830ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    closeSession(session);
6840ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
6850ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
6860ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
6870ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Test that setting an invalid mac algorithm returns
6880ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * the expected status value.
6890ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
6900ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, SetMacInvalidAlgorithm) {
6910ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    SessionId session = openSession();
6920ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_string algorithm;
6930ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    Status status = drmPlugin->setMacAlgorithm(session, algorithm);
6940ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_EQ(Status::BAD_VALUE, status);
6950ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    closeSession(session);
6960ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
6970ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
6980ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
6990ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Test that setting a mac algorithm with no session returns
7000ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * the expected status value.
7010ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
7020ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, SetMacNullAlgorithmNoSession) {
7030ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    SessionId session;
7040ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_string algorithm = "HmacSHA256";
7050ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    Status status = drmPlugin->setMacAlgorithm(session, algorithm);
7060ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_EQ(Status::BAD_VALUE, status);
7070ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
7080ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
7090ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
7100ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Test that setting a valid mac algorithm returns
7110ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * the expected status value. It is not required that all
7120ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * vendor modules support this algorithm, but they must
7130ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * either accept it or return ERROR_DRM_CANNOT_HANDLE
7140ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
7150ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, SetMacAlgorithm) {
7160ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    SessionId session = openSession();
7170ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_string algorithm = "HmacSHA256";
7180ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    Status status = drmPlugin->setMacAlgorithm(session, algorithm);
7190ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_TRUE(status == Status::OK ||
7200ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                status == Status::ERROR_DRM_CANNOT_HANDLE);
7210ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    closeSession(session);
7220ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
7230ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
7240ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
7250ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * The Generic* methods provide general purpose crypto operations
7260ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * that may be used for applications other than DRM. They leverage
7270ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * the hardware root of trust and secure key distribution mechanisms
7280ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * of a DRM system to enable app-specific crypto functionality where
7290ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * the crypto keys are not exposed outside of the trusted execution
7300ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * environment.
7310ea406920af8313875866f13c9104129c08b2d76Jeff Tinker *
7320ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Generic encrypt/decrypt/sign/verify should fail on invalid
7330ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * inputs, e.g. empty sessionId
7340ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
7350ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, GenericEncryptNoSession) {
7360ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    SessionId session;
7370ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_vec<uint8_t> keyId, input, iv;
7380ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto res = drmPlugin->encrypt(
7390ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            session, keyId, input, iv,
7400ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            [&](Status status, const hidl_vec<uint8_t>&) {
7410ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
7420ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            });
7430ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_OK(res);
7440ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
7450ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
7460ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, GenericDecryptNoSession) {
7470ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    SessionId session;
7480ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_vec<uint8_t> keyId, input, iv;
7490ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto res = drmPlugin->decrypt(
7500ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            session, keyId, input, iv,
7510ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            [&](Status status, const hidl_vec<uint8_t>&) {
7520ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
7530ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            });
7540ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_OK(res);
7550ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
7560ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
7570ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, GenericSignNoSession) {
7580ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    SessionId session;
7590ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_vec<uint8_t> keyId, message;
7600ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto res = drmPlugin->sign(
7610ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            session, keyId, message,
7620ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            [&](Status status, const hidl_vec<uint8_t>&) {
7630ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
7640ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            });
7650ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_OK(res);
7660ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
7670ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
7680ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, GenericVerifyNoSession) {
7690ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    SessionId session;
7700ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_vec<uint8_t> keyId, message, signature;
7710ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto res = drmPlugin->verify(
7720ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            session, keyId, message, signature, [&](Status status, bool) {
7730ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
7740ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            });
7750ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_OK(res);
7760ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
7770ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
7780ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, GenericSignRSANoSession) {
7790ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    SessionId session;
7800ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_string algorithm;
7810ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_vec<uint8_t> message, wrappedKey;
7820ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto res = drmPlugin->signRSA(session, algorithm, message, wrappedKey,
7830ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                                  [&](Status status, const hidl_vec<uint8_t>&) {
7840ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                                      EXPECT_EQ(Status::BAD_VALUE, status);
7850ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                                  });
7860ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_OK(res);
7870ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
7880ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
7890ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
7900ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Exercise the requiresSecureDecoderComponent method. Additional tests
7910ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * will verify positive cases with specific vendor content configurations.
7920ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Below we just test the negative cases.
7930ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
7940ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
7950ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
7960ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Verify that requiresSecureDecoderComponent handles empty mimetype.
7970ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
7980ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, RequiresSecureDecoderEmptyMimeType) {
7990ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_FALSE(cryptoPlugin->requiresSecureDecoderComponent(""));
8000ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
8010ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
8020ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
8030ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Verify that requiresSecureDecoderComponent handles invalid mimetype.
8040ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
8050ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, RequiresSecureDecoderInvalidMimeType) {
8060ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_FALSE(cryptoPlugin->requiresSecureDecoderComponent("bad"));
8070ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
8080ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
8090ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
810f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * Verify that requiresSecureDecoderComponent returns true for secure
811f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * configurations
812f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker */
813f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff TinkerTEST_P(DrmHalVendorPluginTest, RequiresSecureDecoderConfig) {
814f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    const char* kVendorStr = "Vendor module ";
815f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    for (auto config : contentConfigurations) {
816f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        for (auto key : config.keys) {
817f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            if (key.isSecure) {
818f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                EXPECT_TRUE(cryptoPlugin->requiresSecureDecoderComponent(config.mimeType));
819f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                break;
820f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            }
821f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        }
822f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    }
823f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker}
824f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
825f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker/**
826f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker *  Event Handling tests
827f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker */
828f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
829f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinkerclass TestDrmPluginListener : public IDrmPluginListener {
830f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinkerpublic:
831f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    TestDrmPluginListener() {reset();}
832f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    virtual ~TestDrmPluginListener() {}
833f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
834f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    virtual Return<void> sendEvent(EventType eventType, const hidl_vec<uint8_t>& sessionId,
835f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            const hidl_vec<uint8_t>& data) override {
836f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        eventType_ = eventType;
837f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        sessionId_ = sessionId;
838f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        data_ = data;
839f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        gotEvent_ = true;
840f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        return Void();
841f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    }
842f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
843f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    virtual Return<void> sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
844f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            int64_t expiryTimeInMS) override {
845f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        sessionId_ = sessionId;
846f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        expiryTimeInMS_ = expiryTimeInMS;
847f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        gotExpirationUpdate_ = true;
848f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        return Void();
849f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    }
850f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
851f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    virtual Return<void> sendKeysChange(const hidl_vec<uint8_t>& sessionId,
852f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) override {
853f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        sessionId_ = sessionId;
854f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        keyStatusList_ = keyStatusList;
855f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        hasNewUsableKey_ = hasNewUsableKey;
856f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        gotKeysChange_ = true;
857f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        return Void();
858f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    }
859f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
860f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    EventType getEventType() const {return eventType_;}
861f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    SessionId getSessionId() const {return sessionId_;}
862f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    vector<uint8_t> getData() const {return data_;}
863f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    int64_t getExpiryTimeInMS() const {return expiryTimeInMS_;}
864f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    hidl_vec<KeyStatus> getKeyStatusList() const {return keyStatusList_;}
865f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    bool hasNewUsableKey() {return hasNewUsableKey_;}
866f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    bool gotEvent() {return gotEvent_;}
867f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    bool gotExpirationUpdate() {return gotExpirationUpdate_;}
868f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    bool gotKeysChange() {return gotKeysChange_;}
869f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
870f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    void reset() {
871f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        gotEvent_ = gotExpirationUpdate_ = gotKeysChange_ = false;
872f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        eventType_ = EventType::PROVISION_REQUIRED;
873f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        sessionId_ = SessionId();
874f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        data_ = hidl_vec<uint8_t>();
875f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        expiryTimeInMS_ = 0;
876f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        keyStatusList_ = hidl_vec<KeyStatus>();
877f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        hasNewUsableKey_ = false;
878f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    }
879f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
880f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinkerprivate:
881f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    bool gotEvent_;
882f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    bool gotExpirationUpdate_;
883f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    bool gotKeysChange_;
884f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
885f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    EventType eventType_;
886f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    SessionId sessionId_;
887f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    hidl_vec<uint8_t> data_;
888f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    int64_t expiryTimeInMS_;
889f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    hidl_vec<KeyStatus> keyStatusList_;
890f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    bool hasNewUsableKey_;
891f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker};
892f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
893f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker/**
894f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * Simulate the plugin sending events. Make sure the listener
895f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * gets them.
896f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker */
897f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff TinkerTEST_P(DrmHalVendorPluginTest, ListenerEvents) {
898f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    sp<TestDrmPluginListener> listener = new TestDrmPluginListener();
899f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    drmPlugin->setListener(listener);
900f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    auto sessionId = openSession();
901f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    vector<uint8_t> data = {0, 1, 2};
902f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    EventType eventTypes[] = {EventType::PROVISION_REQUIRED,
903f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                              EventType::KEY_NEEDED,
904f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                              EventType::KEY_EXPIRED,
905f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                              EventType::VENDOR_DEFINED,
906f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                              EventType::SESSION_RECLAIMED};
907f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    for (auto eventType : eventTypes) {
908f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        listener->reset();
909f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        drmPlugin->sendEvent(eventType, sessionId, data);
910f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        while (!listener->gotEvent()) {usleep(100);}
911f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        EXPECT_EQ(eventType, listener->getEventType());
912f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        EXPECT_EQ(sessionId, listener->getSessionId());
913f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        EXPECT_EQ(data, listener->getData());
914f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    }
915f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    closeSession(sessionId);
916f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker}
917f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
918f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker/**
919f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * Simulate the plugin sending expiration updates and make sure
920f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * the listener gets them.
921f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker */
922f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff TinkerTEST_P(DrmHalVendorPluginTest, ListenerExpirationUpdate) {
923f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    sp<TestDrmPluginListener> listener = new TestDrmPluginListener();
924f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    drmPlugin->setListener(listener);
925f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    auto sessionId = openSession();
926f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    drmPlugin->sendExpirationUpdate(sessionId, 100);
927f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    while (!listener->gotExpirationUpdate()) {usleep(100);}
928f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    EXPECT_EQ(sessionId, listener->getSessionId());
929f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    EXPECT_EQ(100, listener->getExpiryTimeInMS());
930f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    closeSession(sessionId);
931f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker}
932f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
933f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker/**
934f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * Simulate the plugin sending keys change and make sure
935f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * the listener gets them.
936f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker */
937f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff TinkerTEST_P(DrmHalVendorPluginTest, ListenerKeysChange) {
938f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    sp<TestDrmPluginListener> listener = new TestDrmPluginListener();
939f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    drmPlugin->setListener(listener);
940f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    auto sessionId = openSession();
941f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    const hidl_vec<KeyStatus> keyStatusList = {
942f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        {{1}, KeyStatusType::USABLE},
943f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        {{2}, KeyStatusType::EXPIRED},
944f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        {{3}, KeyStatusType::OUTPUTNOTALLOWED},
945f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        {{4}, KeyStatusType::STATUSPENDING},
946f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        {{5}, KeyStatusType::INTERNALERROR},
947f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    };
948f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
949f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    drmPlugin->sendKeysChange(sessionId, keyStatusList, true);
950f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    while (!listener->gotKeysChange()) {usleep(100);}
951f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    EXPECT_EQ(sessionId, listener->getSessionId());
952f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    EXPECT_EQ(keyStatusList, listener->getKeyStatusList());
953f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    EXPECT_EQ(true, listener->hasNewUsableKey());
954f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker}
955f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
956f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker/**
957f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * Negative listener tests. Call send methods with no
958f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * listener set.
959f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker */
960f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff TinkerTEST_P(DrmHalVendorPluginTest, NotListening) {
961f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    sp<TestDrmPluginListener> listener = new TestDrmPluginListener();
962f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    drmPlugin->setListener(listener);
963f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    drmPlugin->setListener(nullptr);
964f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
965f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    SessionId sessionId;
966f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    vector<uint8_t> data;
967f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    hidl_vec<KeyStatus> keyStatusList;
968f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    drmPlugin->sendEvent(EventType::PROVISION_REQUIRED, sessionId, data);
969f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    drmPlugin->sendExpirationUpdate(sessionId, 100);
970f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    drmPlugin->sendKeysChange(sessionId, keyStatusList, true);
971f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    usleep(1000); // can't wait for the event to be recieved, just wait a long time
972f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    EXPECT_EQ(false, listener->gotEvent());
973f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    EXPECT_EQ(false, listener->gotExpirationUpdate());
974f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    EXPECT_EQ(false, listener->gotKeysChange());
975f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker}
976f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
977f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
978f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker/**
9790ea406920af8313875866f13c9104129c08b2d76Jeff Tinker *  CryptoPlugin tests
9800ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
9810ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
9820ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
9830ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Exercise the NotifyResolution API. There is no observable result,
9840ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * just call the method for coverage.
9850ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
9860ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, NotifyResolution) {
9870ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    cryptoPlugin->notifyResolution(1920, 1080);
9880ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
9890ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
9900ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
9910ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * getDecryptMemory allocates memory for decryption, then sets it
9920ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * as a shared buffer base in the crypto hal.  The allocated and
9930ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * mapped IMemory is returned.
9940ea406920af8313875866f13c9104129c08b2d76Jeff Tinker *
9950ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * @param size the size of the memory segment to allocate
9960ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * @param the index of the memory segment which will be used
9970ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * to refer to it for decryption.
9980ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
9990ea406920af8313875866f13c9104129c08b2d76Jeff Tinkersp<IMemory> DrmHalVendorPluginTest::getDecryptMemory(size_t size,
10000ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                                                     size_t index) {
10010ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    sp<IAllocator> ashmemAllocator = IAllocator::getService("ashmem");
10020ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_NE(ashmemAllocator, nullptr);
10030ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
10040ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_memory hidlMemory;
10050ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto res = ashmemAllocator->allocate(
10060ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            size, [&](bool success, const hidl_memory& memory) {
10070ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_EQ(success, true);
10080ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_EQ(memory.size(), size);
10090ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                hidlMemory = memory;
10100ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            });
10110ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
10120ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_OK(res);
10130ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
10140ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    sp<IMemory> mappedMemory = mapMemory(hidlMemory);
10150ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_NE(mappedMemory, nullptr);
10160ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    res = cryptoPlugin->setSharedBufferBase(hidlMemory, index);
10170ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_OK(res);
10180ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    return mappedMemory;
10190ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
10200ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
10210ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
10220ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Exercise the setMediaDrmSession method. setMediaDrmSession
10230ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * is used to associate a drm session with a crypto session.
10240ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
10250ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, SetMediaDrmSession) {
10260ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto sessionId = openSession();
10270ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    Status status = cryptoPlugin->setMediaDrmSession(sessionId);
10280ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_EQ(Status::OK, status);
10290ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    closeSession(sessionId);
10300ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
10310ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
10320ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
10330ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * setMediaDrmSession with a closed session id
10340ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
10350ea406920af8313875866f13c9104129c08b2d76Jeff TinkerTEST_P(DrmHalVendorPluginTest, SetMediaDrmSessionClosedSession) {
10360ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto sessionId = openSession();
10370ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    closeSession(sessionId);
10380ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    Status status = cryptoPlugin->setMediaDrmSession(sessionId);
10390ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, status);
10400ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
10410ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
10420ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
1043f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * setMediaDrmSession with a empty session id: BAD_VALUE
1044f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker */
1045f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff TinkerTEST_P(DrmHalVendorPluginTest, SetMediaDrmSessionEmptySession) {
1046f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    SessionId sessionId;
1047f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1048f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    EXPECT_EQ(Status::BAD_VALUE, status);
1049f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker}
1050f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1051f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker/**
10520ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Decrypt tests
10530ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
10540ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
10550ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerclass DrmHalVendorDecryptTest : public DrmHalVendorPluginTest {
10560ea406920af8313875866f13c9104129c08b2d76Jeff Tinker   public:
10570ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    DrmHalVendorDecryptTest() = default;
10580ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    virtual ~DrmHalVendorDecryptTest() {}
10590ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
10600ea406920af8313875866f13c9104129c08b2d76Jeff Tinker   protected:
10610ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    void loadKeys(const SessionId& sessionId,
1062f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                  const ContentConfiguration& configuration);
10630ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    void fillRandom(const sp<IMemory>& memory);
10640ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    KeyedVector toHidlKeyedVector(const map<string, string>& params);
10650ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_array<uint8_t, 16> toHidlArray(const vector<uint8_t>& vec) {
10660ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        EXPECT_EQ(vec.size(), 16u);
10670ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        return hidl_array<uint8_t, 16>(&vec[0]);
10680ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    }
1069f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    hidl_vec<KeyValue> queryKeyStatus(SessionId sessionId);
1070f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    void removeKeys(SessionId sessionId);
1071f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    uint32_t decrypt(Mode mode, bool isSecure,
1072f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            const hidl_array<uint8_t, 16>& keyId, uint8_t* iv,
1073f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            const hidl_vec<SubSample>& subSamples, const Pattern& pattern,
1074f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            const vector<uint8_t>& key, Status expectedStatus);
1075f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    void aes_ctr_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv,
1076f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key);
1077f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    void aes_cbc_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv,
1078f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key);
10790ea406920af8313875866f13c9104129c08b2d76Jeff Tinker};
10800ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
10810ea406920af8313875866f13c9104129c08b2d76Jeff TinkerKeyedVector DrmHalVendorDecryptTest::toHidlKeyedVector(
10820ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        const map<string, string>& params) {
10830ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    std::vector<KeyValue> stdKeyedVector;
10840ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    for (auto it = params.begin(); it != params.end(); ++it) {
10850ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        KeyValue keyValue;
10860ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        keyValue.key = it->first;
10870ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        keyValue.value = it->second;
10880ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        stdKeyedVector.push_back(keyValue);
10890ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    }
10900ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    return KeyedVector(stdKeyedVector);
10910ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
10920ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
10930ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
10940ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Helper method to load keys for subsequent decrypt tests.
10950ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * These tests use predetermined key request/response to
10960ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * avoid requiring a round trip to a license server.
10970ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
1098f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinkervoid DrmHalVendorDecryptTest::loadKeys(const SessionId& sessionId,
1099f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        const ContentConfiguration& configuration) {
11000ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_vec<uint8_t> keyRequest;
11010ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    auto res = drmPlugin->getKeyRequest(
11020ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            sessionId, configuration.initData, configuration.mimeType,
11030ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            KeyType::STREAMING,
11040ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            toHidlKeyedVector(configuration.optionalParameters),
11050ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            [&](Status status, const hidl_vec<uint8_t>& request,
11060ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                KeyRequestType type, const hidl_string&) {
11070ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_EQ(Status::OK, status)
11080ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                        << "Failed to get "
11090ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                           "key request for configuration "
11100ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                        << configuration.name;
11110ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_EQ(type, KeyRequestType::INITIAL);
11120ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_NE(request.size(), 0u) << "Expected key request size"
11130ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                                                 " to have length > 0 bytes";
11140ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                keyRequest = request;
11150ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            });
11160ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_OK(res);
11170ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
11180ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    /**
11190ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     * Get key response from vendor module
11200ea406920af8313875866f13c9104129c08b2d76Jeff Tinker     */
11210ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    hidl_vec<uint8_t> keyResponse =
11220ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            vendorModule->handleKeyRequest(keyRequest, configuration.serverUrl);
11230ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
11240ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_NE(keyResponse.size(), 0u) << "Expected key response size "
11250ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                                         "to have length > 0 bytes";
11260ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
11270ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    res = drmPlugin->provideKeyResponse(
11280ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            sessionId, keyResponse,
11290ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            [&](Status status, const hidl_vec<uint8_t>&) {
11300ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                EXPECT_EQ(Status::OK, status)
11310ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                        << "Failure providing "
11320ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                           "key response for configuration "
11330ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                        << configuration.name;
11340ea406920af8313875866f13c9104129c08b2d76Jeff Tinker            });
11350ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    EXPECT_OK(res);
11360ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
11370ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
11380ea406920af8313875866f13c9104129c08b2d76Jeff Tinkervoid DrmHalVendorDecryptTest::fillRandom(const sp<IMemory>& memory) {
11390ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    random_device rd;
11400ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    mt19937 rand(rd());
11410ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    for (size_t i = 0; i < memory->getSize() / sizeof(uint32_t); i++) {
11420ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        auto p = static_cast<uint32_t*>(
11430ea406920af8313875866f13c9104129c08b2d76Jeff Tinker                static_cast<void*>(memory->getPointer()));
11440ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        p[i] = rand();
11450ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    }
11460ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
11470ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
1148f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinkerhidl_vec<KeyValue> DrmHalVendorDecryptTest::queryKeyStatus(SessionId sessionId) {
1149f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    hidl_vec<KeyValue> keyStatus;
1150f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    auto res = drmPlugin->queryKeyStatus(sessionId,
1151f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            [&](Status status, KeyedVector info) {
1152f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                EXPECT_EQ(Status::OK, status);
1153f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                keyStatus = info;
1154f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            });
1155f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    EXPECT_OK(res);
1156f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    return keyStatus;
1157f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker}
1158f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1159f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinkervoid DrmHalVendorDecryptTest::removeKeys(SessionId sessionId) {
1160f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    auto res = drmPlugin->removeKeys(sessionId);
1161f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    EXPECT_OK(res);
1162f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker}
1163f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1164f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinkeruint32_t DrmHalVendorDecryptTest::decrypt(Mode mode, bool isSecure,
1165f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        const hidl_array<uint8_t, 16>& keyId, uint8_t* iv,
1166f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        const hidl_vec<SubSample>& subSamples, const Pattern& pattern,
1167f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        const vector<uint8_t>& key, Status expectedStatus) {
1168f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    const size_t kSegmentIndex = 0;
1169f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1170f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    uint8_t localIv[AES_BLOCK_SIZE];
1171f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    memcpy(localIv, iv, AES_BLOCK_SIZE);
1172f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1173f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    size_t totalSize = 0;
1174f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    for (size_t i = 0; i < subSamples.size(); i++) {
1175f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        totalSize += subSamples[i].numBytesOfClearData;
1176f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        totalSize += subSamples[i].numBytesOfEncryptedData;
1177f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    }
1178f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1179f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    // The first totalSize bytes of shared memory is the encrypted
1180f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    // input, the second totalSize bytes is the decrypted output.
1181f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    sp<IMemory> sharedMemory =
1182f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            getDecryptMemory(totalSize * 2, kSegmentIndex);
1183f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1184f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    SharedBuffer sourceBuffer = {
1185f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            .bufferId = kSegmentIndex, .offset = 0, .size = totalSize};
1186f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    fillRandom(sharedMemory);
1187f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1188f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    DestinationBuffer destBuffer = {.type = BufferType::SHARED_MEMORY,
1189f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                                    {.bufferId = kSegmentIndex,
1190f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                                     .offset = totalSize,
1191f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                                     .size = totalSize},
1192f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                                    .secureMemory = nullptr};
1193f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    uint64_t offset = 0;
1194f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    uint32_t bytesWritten = 0;
1195f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    auto res = cryptoPlugin->decrypt(isSecure, keyId, localIv, mode, pattern,
1196f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            subSamples, sourceBuffer, offset, destBuffer,
1197f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            [&](Status status, uint32_t count, string detailedError) {
1198f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                EXPECT_EQ(expectedStatus, status) << "Unexpected decrypt status " <<
1199f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                detailedError;
1200f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                bytesWritten = count;
1201f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            });
1202f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    EXPECT_OK(res);
1203f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1204f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    if (bytesWritten != totalSize) {
1205f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        return bytesWritten;
1206f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    }
1207f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    uint8_t* base = static_cast<uint8_t*>(
1208f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            static_cast<void*>(sharedMemory->getPointer()));
1209f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1210f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    // generate reference vector
1211f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    vector<uint8_t> reference(totalSize);
1212f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1213f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    memcpy(localIv, iv, AES_BLOCK_SIZE);
1214f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    switch (mode) {
1215f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    case Mode::UNENCRYPTED:
1216f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        memcpy(&reference[0], base, totalSize);
1217f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        break;
1218f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    case Mode::AES_CTR:
1219f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        aes_ctr_decrypt(&reference[0], base, localIv, subSamples, key);
1220f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        break;
1221f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    case Mode::AES_CBC:
1222f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        aes_cbc_decrypt(&reference[0], base, localIv, subSamples, key);
1223f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        break;
1224f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    case Mode::AES_CBC_CTS:
1225f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        EXPECT_TRUE(false) << "AES_CBC_CTS mode not supported";
1226f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        break;
1227f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    }
1228f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1229f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    // compare reference to decrypted data which is at base + total size
1230f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    EXPECT_EQ(0, memcmp(static_cast<void*>(&reference[0]),
1231f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                        static_cast<void*>(base + totalSize), totalSize))
1232f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            << "decrypt data mismatch";
1233f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    return totalSize;
1234f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker}
1235f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1236f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker/**
1237f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * Decrypt a list of clear+encrypted subsamples using the specified key
1238f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * in AES-CTR mode
1239f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker */
1240f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinkervoid DrmHalVendorDecryptTest::aes_ctr_decrypt(uint8_t* dest, uint8_t* src,
1241f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        uint8_t* iv, const hidl_vec<SubSample>& subSamples,
1242f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        const vector<uint8_t>& key) {
1243f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1244f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    AES_KEY decryptionKey;
1245f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    AES_set_encrypt_key(&key[0], 128, &decryptionKey);
1246f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1247f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    size_t offset = 0;
1248f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    unsigned blockOffset = 0;
1249f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    uint8_t previousEncryptedCounter[AES_BLOCK_SIZE];
1250f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    memset(previousEncryptedCounter, 0, AES_BLOCK_SIZE);
1251f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1252f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    for (size_t i = 0; i < subSamples.size(); i++) {
1253f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        const SubSample& subSample = subSamples[i];
1254f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1255f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        if (subSample.numBytesOfClearData > 0) {
1256f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            memcpy(dest + offset, src + offset, subSample.numBytesOfClearData);
1257f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            offset += subSample.numBytesOfClearData;
1258f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        }
1259f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1260f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        if (subSample.numBytesOfEncryptedData > 0) {
1261f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            AES_ctr128_encrypt(src + offset, dest + offset,
1262f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                    subSample.numBytesOfEncryptedData, &decryptionKey,
1263f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                    iv, previousEncryptedCounter, &blockOffset);
1264f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            offset += subSample.numBytesOfEncryptedData;
12650ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        }
12660ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    }
12670ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
12680ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
12690ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
1270f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * Decrypt a list of clear+encrypted subsamples using the specified key
1271f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * in AES-CBC mode
12720ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
1273f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinkervoid DrmHalVendorDecryptTest::aes_cbc_decrypt(uint8_t* dest, uint8_t* src,
1274f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        uint8_t* iv, const hidl_vec<SubSample>& subSamples,
1275f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        const vector<uint8_t>& key) {
1276f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    AES_KEY decryptionKey;
1277f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    AES_set_encrypt_key(&key[0], 128, &decryptionKey);
1278f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1279f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    size_t offset = 0;
1280f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    size_t num = 0;
1281f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    size_t ecount_buf = 0;
1282f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    for (size_t i = 0; i < subSamples.size(); i++) {
1283f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        const SubSample& subSample = subSamples[i];
1284f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1285f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        memcpy(dest + offset, src + offset, subSample.numBytesOfClearData);
1286f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        offset += subSample.numBytesOfClearData;
1287f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1288f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        AES_cbc_encrypt(src + offset, dest + offset, subSample.numBytesOfEncryptedData,
1289f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                &decryptionKey, iv, 0 /* decrypt */);
1290f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        offset += subSample.numBytesOfEncryptedData;
1291f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    }
1292f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker}
12930ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
1294f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1295f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker/**
1296f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * Test key status with empty session id, should return BAD_VALUE
1297f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker */
1298f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff TinkerTEST_P(DrmHalVendorDecryptTest, QueryKeyStatusInvalidSession) {
1299f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    SessionId sessionId;
1300f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    auto res = drmPlugin->queryKeyStatus(sessionId,
1301f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            [&](Status status, KeyedVector /* info */) {
1302f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                EXPECT_EQ(Status::BAD_VALUE, status);
1303f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            });
1304f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    EXPECT_OK(res);
1305f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker}
1306f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1307f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1308f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker/**
1309f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * Test key status.  There should be no key status prior to loading keys
1310f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker */
1311f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff TinkerTEST_P(DrmHalVendorDecryptTest, QueryKeyStatusWithNoKeys) {
1312f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    auto sessionId = openSession();
1313f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    auto keyStatus = queryKeyStatus(sessionId);
1314f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    EXPECT_EQ(0u, keyStatus.size());
1315f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    closeSession(sessionId);
1316f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker}
1317f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1318f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1319f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker/**
1320f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * Test key status.  There should be key status after loading keys.
1321f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker */
1322f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff TinkerTEST_P(DrmHalVendorDecryptTest, QueryKeyStatus) {
1323f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    for (auto config : contentConfigurations) {
13240ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        auto sessionId = openSession();
13250ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        loadKeys(sessionId, config);
1326f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        auto keyStatus = queryKeyStatus(sessionId);
1327f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        EXPECT_NE(0u, keyStatus.size());
1328f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        closeSession(sessionId);
1329f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    }
1330f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker}
13310ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
1332f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker/**
1333f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * Positive decrypt test. "Decrypt" a single clear segment and verify.
1334f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker */
1335f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff TinkerTEST_P(DrmHalVendorDecryptTest, ClearSegmentTest) {
1336f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    for (auto config : contentConfigurations) {
1337f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        for (auto key : config.keys) {
1338f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            const size_t kSegmentSize = 1024;
1339f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
1340f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            const Pattern noPattern = {0, 0};
1341f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            const vector<SubSample> subSamples = {{.numBytesOfClearData = kSegmentSize,
1342f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                                                   .numBytesOfEncryptedData = 0}};
1343f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            auto sessionId = openSession();
1344f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            loadKeys(sessionId, config);
1345f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1346f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1347f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            EXPECT_EQ(Status::OK, status);
1348f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1349f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            uint32_t byteCount = decrypt(Mode::UNENCRYPTED, key.isSecure, toHidlArray(key.keyId),
1350f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                    &iv[0], subSamples, noPattern, key.clearContentKey, Status::OK);
1351f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            EXPECT_EQ(kSegmentSize, byteCount);
1352f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1353f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            closeSession(sessionId);
1354f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        }
1355f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    }
1356f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker}
13570ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
1358f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker/**
1359f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * Positive decrypt test.  Decrypt a single segment using aes_ctr.
1360f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * Verify data matches.
1361f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker */
1362f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff TinkerTEST_P(DrmHalVendorDecryptTest, EncryptedAesCtrSegmentTest) {
1363f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    for (auto config : contentConfigurations) {
1364f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        for (auto key : config.keys) {
1365f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            const size_t kSegmentSize = 1024;
1366f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
1367f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            const Pattern noPattern = {0, 0};
1368f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            const vector<SubSample> subSamples = {{.numBytesOfClearData = kSegmentSize,
1369f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                                                   .numBytesOfEncryptedData = 0}};
1370f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            auto sessionId = openSession();
1371f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            loadKeys(sessionId, config);
1372f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1373f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1374f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            EXPECT_EQ(Status::OK, status);
1375f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1376f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            uint32_t byteCount = decrypt(Mode::AES_CTR, key.isSecure, toHidlArray(key.keyId),
1377f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                    &iv[0], subSamples, noPattern, key.clearContentKey, Status::OK);
1378f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            EXPECT_EQ(kSegmentSize, byteCount);
1379f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1380f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            closeSession(sessionId);
1381f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        }
1382f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    }
1383f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker}
13840ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
1385f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker/**
1386f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * Negative decrypt test. Decrypt without loading keys.
1387f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker */
1388f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff TinkerTEST_P(DrmHalVendorDecryptTest, EncryptedAesCtrSegmentTestNoKeys) {
1389f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    for (auto config : contentConfigurations) {
1390f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        for (auto key : config.keys) {
1391f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
1392f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            const Pattern noPattern = {0, 0};
1393f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            const vector<SubSample> subSamples = {{.numBytesOfClearData = 256,
1394f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                                                   .numBytesOfEncryptedData = 256}};
1395f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            auto sessionId = openSession();
1396f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1397f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1398f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            EXPECT_EQ(Status::OK, status);
1399f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1400f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            uint32_t byteCount = decrypt(Mode::AES_CTR, key.isSecure,
1401f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                    toHidlArray(key.keyId), &iv[0], subSamples, noPattern,
1402f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                    key.clearContentKey, Status::ERROR_DRM_NO_LICENSE);
1403f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            EXPECT_EQ(0u, byteCount);
1404f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1405f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            closeSession(sessionId);
1406f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        }
14070ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    }
14080ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
14090ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
14100ea406920af8313875866f13c9104129c08b2d76Jeff Tinker/**
1411f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * Test key removal.  Load keys then remove them and verify that
1412f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker * decryption can't be performed.
1413f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker */
1414f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff TinkerTEST_P(DrmHalVendorDecryptTest, AttemptDecryptWithKeysRemoved) {
1415f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    for (auto config : contentConfigurations) {
1416f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        for (auto key : config.keys) {
1417f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
1418f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            const Pattern noPattern = {0, 0};
1419f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            const vector<SubSample> subSamples = {{.numBytesOfClearData = 256,
1420f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                                                   .numBytesOfEncryptedData = 256}};
1421f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            auto sessionId = openSession();
1422f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1423f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            Status status = cryptoPlugin->setMediaDrmSession(sessionId);
1424f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            EXPECT_EQ(Status::OK, status);
1425f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1426f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            loadKeys(sessionId, config);
1427f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            removeKeys(sessionId);
1428f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1429f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            uint32_t byteCount = decrypt(Mode::AES_CTR, key.isSecure,
1430f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                    toHidlArray(key.keyId), &iv[0], subSamples, noPattern,
1431f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                    key.clearContentKey, Status::ERROR_DRM_DECRYPT);
1432f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            EXPECT_EQ(0u, byteCount);
1433f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1434f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker            closeSession(sessionId);
1435f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        }
1436f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    }
1437f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker}
1438f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1439f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker
1440f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker/**
14410ea406920af8313875866f13c9104129c08b2d76Jeff Tinker * Instantiate the set of test cases for each vendor module
14420ea406920af8313875866f13c9104129c08b2d76Jeff Tinker */
14430ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
14440ea406920af8313875866f13c9104129c08b2d76Jeff TinkerINSTANTIATE_TEST_CASE_P(
14450ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        DrmHalVendorFactoryTestCases, DrmHalVendorFactoryTest,
1446f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        testing::ValuesIn(gVendorModules->getPathList()));
14470ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
14480ea406920af8313875866f13c9104129c08b2d76Jeff TinkerINSTANTIATE_TEST_CASE_P(
14490ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        DrmHalVendorPluginTestCases, DrmHalVendorPluginTest,
1450f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        testing::ValuesIn(gVendorModules->getPathList()));
14510ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
14520ea406920af8313875866f13c9104129c08b2d76Jeff TinkerINSTANTIATE_TEST_CASE_P(
14530ea406920af8313875866f13c9104129c08b2d76Jeff Tinker        DrmHalVendorDecryptTestCases, DrmHalVendorDecryptTest,
1454f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        testing::ValuesIn(gVendorModules->getPathList()));
14550ea406920af8313875866f13c9104129c08b2d76Jeff Tinker
14560ea406920af8313875866f13c9104129c08b2d76Jeff Tinkerint main(int argc, char** argv) {
1457f50e7a7495d81f29ed75e4df110e104a7d6de19aJeff Tinker#if defined(__LP64__)
1458f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    const char* kModulePath = "/data/local/tmp/64/lib";
1459f50e7a7495d81f29ed75e4df110e104a7d6de19aJeff Tinker#else
1460f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    const char* kModulePath = "/data/local/tmp/32/lib";
1461f50e7a7495d81f29ed75e4df110e104a7d6de19aJeff Tinker#endif
1462f50e7a7495d81f29ed75e4df110e104a7d6de19aJeff Tinker    gVendorModules = new drm_vts::VendorModules(kModulePath);
1463f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    if (gVendorModules->getPathList().size() == 0) {
1464f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        std::cerr << "No vendor modules found in " << kModulePath <<
1465f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker                ", exiting" << std::endl;
1466f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker        exit(-1);
1467f20aa0c48524a890f2fcf08f249bafe62bb6db45Jeff Tinker    }
14680ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    ::testing::InitGoogleTest(&argc, argv);
14690ea406920af8313875866f13c9104129c08b2d76Jeff Tinker    return RUN_ALL_TESTS();
14700ea406920af8313875866f13c9104129c08b2d76Jeff Tinker}
1471