Merge "drm vts 1.0 refactor" am: ae3a851727 am: aba5f2f610 am: 2920ac4f90

Change-Id: I7bec3b671cf681e74c11b589cef690ad6861eb9a
This commit is contained in:
Automerger Merge Worker 2020-01-29 05:59:33 +00:00
commit 3f054b5b24
8 changed files with 801 additions and 659 deletions

View file

@ -29,21 +29,58 @@ cc_library_static {
export_include_dirs: ["include"],
}
cc_test {
name: "VtsHalDrmV1_0TargetTest",
cc_library_static {
name: "android.hardware.drm@1.0-vts",
defaults: ["VtsHalTargetTestDefaults"],
local_include_dirs: [
"include",
],
srcs: [
"drm_hal_clearkey_test.cpp",
"drm_hal_vendor_test.cpp",
],
static_libs: [
shared_libs: [
"android.hardware.drm@1.0",
"android.hardware.drm@1.0-helper",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
"libhidlmemory",
"libnativehelper",
"libssl",
],
static_libs: [
"android.hardware.drm@1.0-helper",
"libcrypto_static",
"libdrmvtshelper",
],
export_shared_lib_headers: [
"android.hardware.drm@1.0",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
"libhidlmemory",
"libnativehelper",
],
export_include_dirs: [
"include",
],
}
cc_test {
name: "VtsHalDrmV1_0TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
srcs: [
"drm_hal_test_main.cpp",
],
whole_static_libs: [
"android.hardware.drm@1.0-vts",
],
shared_libs: [
"android.hardware.drm@1.0",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
"libhidlmemory",
"libnativehelper",
],
static_libs: [
"android.hardware.drm@1.0-helper",
"libcrypto_static",
"libdrmvtshelper",
],

View file

@ -16,127 +16,26 @@
#define LOG_TAG "drm_hal_clearkey_test@1.0"
#include <android/hardware/drm/1.0/ICryptoFactory.h>
#include <android/hardware/drm/1.0/ICryptoPlugin.h>
#include <android/hardware/drm/1.0/IDrmFactory.h>
#include <android/hardware/drm/1.0/IDrmPlugin.h>
#include <android/hardware/drm/1.0/types.h>
#include <android/hidl/allocator/1.0/IAllocator.h>
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
#include <hidl/HidlSupport.h>
#include <hidl/ServiceManagement.h>
#include <hidlmemory/mapping.h>
#include <log/log.h>
#include <openssl/aes.h>
#include <memory>
#include <random>
using ::android::hardware::drm::V1_0::BufferType;
using ::android::hardware::drm::V1_0::DestinationBuffer;
using ::android::hardware::drm::V1_0::ICryptoFactory;
using ::android::hardware::drm::V1_0::ICryptoPlugin;
using ::android::hardware::drm::V1_0::IDrmFactory;
using ::android::hardware::drm::V1_0::IDrmPlugin;
using ::android::hardware::drm::V1_0::KeyedVector;
using ::android::hardware::drm::V1_0::KeyValue;
using ::android::hardware::drm::V1_0::KeyRequestType;
using ::android::hardware::drm::V1_0::KeyType;
using ::android::hardware::drm::V1_0::Mode;
using ::android::hardware::drm::V1_0::Pattern;
using ::android::hardware::drm::V1_0::SecureStop;
using ::android::hardware::drm::V1_0::SecureStopId;
using ::android::hardware::drm::V1_0::SessionId;
using ::android::hardware::drm::V1_0::SharedBuffer;
using ::android::hardware::drm::V1_0::Status;
using ::android::hardware::drm::V1_0::SubSample;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hidl::allocator::V1_0::IAllocator;
using ::android::hidl::memory::V1_0::IMemory;
using ::android::sp;
#include "android/hardware/drm/1.0/vts/drm_hal_clearkey_test.h"
using std::string;
using std::unique_ptr;
using std::random_device;
using std::map;
using std::mt19937;
using std::vector;
/**
* These clearkey tests use white box knowledge of the legacy clearkey
* plugin to verify that the HIDL HAL services and interfaces are working.
* It is not intended to verify any vendor's HAL implementation. If you
* are looking for vendor HAL tests, see drm_hal_vendor_test.cpp
*/
#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
#define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk())
static const uint8_t kCommonPsshBoxUUID[16] = {
0x10, 0x77, 0xEF, 0xEC, 0xC0, 0xB2, 0x4D, 0x02,
0xAC, 0xE3, 0x3C, 0x1E, 0x52, 0xE2, 0xFB, 0x4B};
// To be used in mpd to specify drm scheme for players
static const uint8_t kClearKeyUUID[16] = {
0xE2, 0x71, 0x9D, 0x58, 0xA9, 0x85, 0xB3, 0xC9,
0x78, 0x1A, 0xB0, 0x30, 0xAF, 0x78, 0xD3, 0x0E};
static const uint8_t kInvalidUUID[16] = {
0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80};
class DrmHalClearkeyFactoryTest : public ::testing::TestWithParam<std::string> {
public:
void SetUp() override {
const ::testing::TestInfo* const test_info =
::testing::UnitTest::GetInstance()->current_test_info();
ALOGD("Running test %s.%s", test_info->test_case_name(),
test_info->name());
const std::string instanceName = GetParam();
drmFactory = IDrmFactory::getService(instanceName);
ASSERT_NE(nullptr, drmFactory.get());
cryptoFactory = ICryptoFactory::getService(instanceName);
ASSERT_NE(nullptr, cryptoFactory.get());
const bool drmClearKey = drmFactory->isCryptoSchemeSupported(kClearKeyUUID);
const bool cryptoClearKey = cryptoFactory->isCryptoSchemeSupported(kClearKeyUUID);
EXPECT_EQ(drmClearKey, cryptoClearKey);
const bool supportsClearKey = drmClearKey && cryptoClearKey;
const bool drmCommonPsshBox = drmFactory->isCryptoSchemeSupported(kCommonPsshBoxUUID);
const bool cryptoCommonPsshBox = cryptoFactory->isCryptoSchemeSupported(kCommonPsshBoxUUID);
EXPECT_EQ(drmCommonPsshBox, cryptoCommonPsshBox);
const bool supportsCommonPsshBox = drmCommonPsshBox && cryptoCommonPsshBox;
EXPECT_EQ(supportsClearKey, supportsCommonPsshBox);
correspondsToThisTest = supportsClearKey && supportsCommonPsshBox;
if (instanceName == "clearkey") {
EXPECT_TRUE(correspondsToThisTest);
// TODO(b/147449315)
// Only the clearkey plugged into the "default" instance supports
// this test. Currently the "clearkey" instance fails some tests
// here.
GTEST_SKIP() << "Clearkey tests don't work with 'clearkey' instance yet.";
}
if (!correspondsToThisTest) {
GTEST_SKIP() << "Cannot test clearkey features on non-clearkey DRM modules";
}
}
protected:
sp<IDrmFactory> drmFactory;
sp<ICryptoFactory> cryptoFactory;
bool correspondsToThisTest;
};
namespace android {
namespace hardware {
namespace drm {
namespace V1_0 {
namespace vts {
/**
* Ensure the factory doesn't support an invalid scheme UUID
@ -264,48 +163,6 @@ TEST_P(DrmHalClearkeyFactoryTest, CreateInvalidCryptoPlugin) {
EXPECT_OK(res);
}
class DrmHalClearkeyPluginTest : public DrmHalClearkeyFactoryTest {
public:
virtual void SetUp() override {
// Create factories
DrmHalClearkeyFactoryTest::SetUp();
if (!correspondsToThisTest) {
GTEST_SKIP() << "Cannot test clearkey features on non-clearkey DRM modules";
}
ASSERT_NE(nullptr, drmFactory.get());
hidl_string packageName("android.hardware.drm.test");
auto res = drmFactory->createPlugin(
kClearKeyUUID, packageName,
[this](Status status, const sp<IDrmPlugin>& plugin) {
EXPECT_EQ(Status::OK, status);
ASSERT_NE(nullptr, plugin.get());
drmPlugin = plugin;
});
ASSERT_OK(res);
hidl_vec<uint8_t> initVec;
res = cryptoFactory->createPlugin(
kClearKeyUUID, initVec,
[this](Status status, const sp<ICryptoPlugin>& plugin) {
EXPECT_EQ(Status::OK, status);
ASSERT_NE(nullptr, plugin.get());
cryptoPlugin = plugin;
});
ASSERT_OK(res);
}
SessionId openSession();
void closeSession(const SessionId& sessionId);
hidl_vec<uint8_t> loadKeys(const SessionId& sessionId, const KeyType& type);
sp<IMemory> getDecryptMemory(size_t size, size_t index);
protected:
sp<IDrmPlugin> drmPlugin;
sp<ICryptoPlugin> cryptoPlugin;
};
/**
* DrmPlugin tests
*/
@ -966,30 +823,6 @@ TEST_P(DrmHalClearkeyPluginTest, SetMediaDrmSessionEmptySession) {
* Decrypt tests
*/
class DrmHalClearkeyDecryptTest : public DrmHalClearkeyPluginTest {
public:
void SetUp() override {
DrmHalClearkeyPluginTest::SetUp();
if (!correspondsToThisTest) {
GTEST_SKIP() << "Cannot test clearkey features on non-clearkey DRM modules";
}
}
void fillRandom(const sp<IMemory>& memory);
hidl_array<uint8_t, 16> toHidlArray(const vector<uint8_t>& vec) {
EXPECT_EQ(16u, vec.size());
return hidl_array<uint8_t, 16>(&vec[0]);
}
uint32_t decrypt(Mode mode, uint8_t* iv, const hidl_vec<SubSample>& subSamples,
const Pattern& pattern, Status status);
void aes_ctr_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv,
const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key);
void aes_cbc_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv,
const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key);
void decryptWithInvalidKeys(hidl_vec<uint8_t>& invalidResponse,
vector<uint8_t>& iv, const Pattern& noPattern, const vector<SubSample>& subSamples);
};
void DrmHalClearkeyDecryptTest::fillRandom(const sp<IMemory>& memory) {
random_device rd;
mt19937 rand(rd());
@ -1300,20 +1133,8 @@ TEST_P(DrmHalClearkeyDecryptTest, DecryptWithKeyTooLong) {
decryptWithInvalidKeys(invalidResponse, iv, noPattern, subSamples);
}
static const std::set<std::string> kAllInstances = [] {
std::vector<std::string> drmInstances =
android::hardware::getAllHalInstanceNames(IDrmFactory::descriptor);
std::vector<std::string> cryptoInstances =
android::hardware::getAllHalInstanceNames(ICryptoFactory::descriptor);
std::set<std::string> allInstances;
allInstances.insert(drmInstances.begin(), drmInstances.end());
allInstances.insert(cryptoInstances.begin(), cryptoInstances.end());
return allInstances;
}();
INSTANTIATE_TEST_SUITE_P(PerInstance, DrmHalClearkeyFactoryTest, testing::ValuesIn(kAllInstances),
android::hardware::PrintInstanceNameToString);
INSTANTIATE_TEST_SUITE_P(PerInstance, DrmHalClearkeyPluginTest, testing::ValuesIn(kAllInstances),
android::hardware::PrintInstanceNameToString);
INSTANTIATE_TEST_SUITE_P(PerInstance, DrmHalClearkeyDecryptTest, testing::ValuesIn(kAllInstances),
android::hardware::PrintInstanceNameToString);
} // namespace vts
} // namespace V1_0
} // namespace drm
} // namespace hardware
} // namespace android

View file

@ -0,0 +1,71 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "drm_hal_vendor_test@1.0"
#include "vendor_modules.h"
#include "android/hardware/drm/1.0/vts/drm_hal_vendor_test.h"
#include "android/hardware/drm/1.0/vts/drm_hal_clearkey_test.h"
using ::android::hardware::drm::V1_0::ICryptoFactory;
using ::android::hardware::drm::V1_0::IDrmFactory;
using ::android::hardware::drm::V1_0::vts::DrmHalClearkeyFactoryTest;
using ::android::hardware::drm::V1_0::vts::DrmHalClearkeyPluginTest;
using ::android::hardware::drm::V1_0::vts::DrmHalClearkeyDecryptTest;
using ::android::hardware::drm::V1_0::vts::DrmHalVendorFactoryTest;
using ::android::hardware::drm::V1_0::vts::DrmHalVendorPluginTest;
using ::android::hardware::drm::V1_0::vts::DrmHalVendorDecryptTest;
/**
* Instantiate the set of test cases for each vendor module
*/
static const std::vector<DrmHalTestParam> kAllInstances = [] {
std::vector<std::string> drmInstances =
android::hardware::getAllHalInstanceNames(IDrmFactory::descriptor);
std::vector<std::string> cryptoInstances =
android::hardware::getAllHalInstanceNames(ICryptoFactory::descriptor);
std::set<std::string> allInstances;
allInstances.insert(drmInstances.begin(), drmInstances.end());
allInstances.insert(cryptoInstances.begin(), cryptoInstances.end());
std::vector<DrmHalTestParam> allInstanceUuidCombos;
auto noUUID = [](std::string s) { return DrmHalTestParam(s); };
std::transform(allInstances.begin(), allInstances.end(),
std::back_inserter(allInstanceUuidCombos), noUUID);
return allInstanceUuidCombos;
}();
INSTANTIATE_TEST_CASE_P(DrmHalVendorFactoryTestCases, DrmHalVendorFactoryTest,
testing::ValuesIn(kAllInstances),
drm_vts::PrintParamInstanceToString);
INSTANTIATE_TEST_CASE_P(DrmHalVendorPluginTestCases, DrmHalVendorPluginTest,
testing::ValuesIn(kAllInstances),
drm_vts::PrintParamInstanceToString);
INSTANTIATE_TEST_CASE_P(DrmHalVendorDecryptTestCases, DrmHalVendorDecryptTest,
testing::ValuesIn(kAllInstances),
drm_vts::PrintParamInstanceToString);
INSTANTIATE_TEST_SUITE_P(PerInstance, DrmHalClearkeyFactoryTest, testing::ValuesIn(kAllInstances),
drm_vts::PrintParamInstanceToString);
INSTANTIATE_TEST_SUITE_P(PerInstance, DrmHalClearkeyPluginTest, testing::ValuesIn(kAllInstances),
drm_vts::PrintParamInstanceToString);
INSTANTIATE_TEST_SUITE_P(PerInstance, DrmHalClearkeyDecryptTest, testing::ValuesIn(kAllInstances),
drm_vts::PrintParamInstanceToString);

View file

@ -1,234 +0,0 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef DRM_HAL_VENDOR_MODULE_API_H
#define DRM_HAL_VENDOR_MODULE_API_H
#include <stdint.h>
#include <map>
#include <string>
#include <vector>
/**
* The DRM and Crypto HALs interact with vendor-provided HAL implementations
* that have DRM-specific capabilities. Since the VTS tests cannot contain
* DRM-specific functionality, supporting modules are required to enable VTS
* to validate HAL implementations in a generic way. If the vendor-specific
* VTS module is not provided for a given drm HAL implementation, only very
* small subset of functionality can be verified.
*
* As an example, a DRM HAL implementation interacts with a DRM-specific
* license server to obtain licenses for decrypting content. The DRM HAL
* implementation generates a key request message, delivers it to the server
* and receives a key response message which is then loaded into the HAL. Once
* the keys are loaded, the Crypto HAL decryption functionality and performance
* and other associated APIs can be tested by the common VTS test suite.
*
* Vendor-specific VTS modules are shared libraries used by the DRM VTS test.
* They provide a set of functions to support VTS testing of the DRM HAL module.
*
* The modules are placed in a common location on the file system. The VTS test
* scans through all vendor-provided support libraries and runs the VTS test
* suite on each library that is found.
*
* The vendor-specific module exposes an extern C vendorModuleFactory()
* function that returns a DrmHalVTSVendorModule instance. DrmHalVTSVendorModule
* instances are versioned, where each version is represented by subclass of
* DrmHalVTSVendorModule that corresponds to the API version. For example, a
* vendor-specific module that implements version 1 of the API would return a
* DrmHalVTSVendorModule_V1 from the vendorModuleFactory() function.
*/
class DrmHalVTSVendorModule;
extern "C" {
/**
* The factory method for creating DrmHalVTSVendorModule instances. The returned
* instance will be a subclass of DrmHalVTSVendorModule that corresponds to the
* supported API version.
*/
DrmHalVTSVendorModule* vendorModuleFactory();
};
class DrmHalVTSVendorModule {
public:
DrmHalVTSVendorModule() : installed(true) {}
virtual ~DrmHalVTSVendorModule() {}
/**
* Return the vendor-specific module API version. The version is an integer
* value with initial version 1. The API version indicates which subclass
* version DrmHalVTSVendorModule this instance is.
*/
virtual uint32_t getAPIVersion() const = 0;
/**
* Return the UUID for the DRM HAL implementation. Protection System
* Specific
* UUID (see http://dashif.org/identifiers/protection/)
*/
virtual std::vector<uint8_t> getUUID() const = 0;
/**
* Return the service name for the DRM HAL implementation. If the hal is a
* legacy
* drm plugin, i.e. not running as a HIDL service, return the empty string.
*/
virtual std::string getServiceName() const = 0;
/**
* Set a flag in the vendor module to indicate whether or not the drm
* scheme corresponding to this module is installed on the device.
*/
void setInstalled(bool flag) {installed = flag;}
bool isInstalled() const {return installed;}
private:
bool installed;
DrmHalVTSVendorModule(const DrmHalVTSVendorModule&) = delete;
void operator=(const DrmHalVTSVendorModule&) = delete;
};
/**
* API Version 1. This is the baseline version that supports a minimal set
* of VTS tests.
*/
class DrmHalVTSVendorModule_V1 : public DrmHalVTSVendorModule {
public:
DrmHalVTSVendorModule_V1() {}
virtual ~DrmHalVTSVendorModule_V1() {}
virtual uint32_t getAPIVersion() const { return 1; }
/**
* Handle a provisioning request. This function will be called if the HAL
* module's getProvisionRequest returns a provision request. The vendor
* module should process the provisioning request, either by sending it
* to a provisioning server, or generating a mock response. The resulting
* provisioning response is returned to the VTS test.
*
* @param provisioningRequest the provisioning request recieved from
* the DRM HAL
* @param url the default url the HAL implementation provided with the
* provisioning request
* @return the generated provisioning response
*/
virtual std::vector<uint8_t> handleProvisioningRequest(
const std::vector<uint8_t>& provisioningRequest,
const std::string& url) = 0;
/**
* Content configuration specifies content-specific parameters associated
* with a key request/response transaction. It allows the VTS test to
* request keys and use them to perform decryption.
*/
struct ContentConfiguration {
/**
* Assign a name for this configuration that will be referred to
* in log messages.
*/
const std::string name;
/**
* Server to use when requesting a key response. This url will be
* passed as a parameter to the vendor vts module along with the
* key request to perform the key request transaction.
*/
const std::string serverUrl;
/**
* Initialization data provided to getKeyRequest, e.g. PSSH for CENC
* content
*/
const std::vector<uint8_t> initData;
/**
* Mime type provided to getKeyRequest, e.g. "video/mp4", or "cenc"
*/
const std::string mimeType;
/**
* Optional parameters to be associated with the key request
*/
const std::map<std::string, std::string> optionalParameters;
/**
* Define license policy attributes for the content configuration.
* These attributes can affect which tests are able to be applied.
*/
struct Policy {
/**
* Indicate if the license policy allows offline playback.
* Content configurated with this policy supports KeyType::OFFLINE
* key requests/responses. A vendor module should provide at least
* one content configuration where allowOffline is true if the drm
* scheme supports offline content.
*/
bool allowOffline;
} policy;
/**
* The keys that will be available once the keys are loaded
*/
struct Key {
/**
* Indicate if the key content is configured to require secure
* buffers, where the output buffers are protected and cannot be
* accessed by the non-secure cpu. A vendor module should provide
* at least one content configurations where isSecure is false, to
* allow decrypt result verification tests to be run.
*/
bool isSecure;
/**
* A key ID identifies a key to use for decryption
*/
const std::vector<uint8_t> keyId;
/**
* The clear content key is provided to generate expected values for
* validating decryption.
*/
const std::vector<uint8_t> clearContentKey;
};
std::vector<Key> keys;
};
/**
* Return a list of content configurations that can be exercised by the
* VTS test.
*/
virtual std::vector<ContentConfiguration>
getContentConfigurations() const = 0;
/**
* Handle a key request. This function will be called if the HAL
* module's getKeyRequest returns a key request. The vendor
* module should process the key request, either by sending it
* to a license server, or by generating a mock response. The resulting
* key response is returned to the VTS test.
*
* @param keyRequest the key request recieved from the DRM HAL
* @param serverUrl the url of the key server that was supplied
* by the ContentConfiguration
* @return the generated key response
*/
virtual std::vector<uint8_t> handleKeyRequest(
const std::vector<uint8_t>& keyRequest,
const std::string& serverUrl) = 0;
};
#endif // DRM_HAL_VENDOR_MODULE_API_H

View file

@ -0,0 +1 @@
include/drm_hal_vendor_module_api.h

View file

@ -16,138 +16,46 @@
#define LOG_TAG "drm_hal_vendor_test@1.0"
#include <android/hardware/drm/1.0/ICryptoFactory.h>
#include <android/hardware/drm/1.0/ICryptoPlugin.h>
#include <android/hardware/drm/1.0/IDrmFactory.h>
#include <android/hardware/drm/1.0/IDrmPlugin.h>
#include <android/hardware/drm/1.0/IDrmPluginListener.h>
#include <android/hardware/drm/1.0/types.h>
#include <android/hidl/allocator/1.0/IAllocator.h>
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
#include <hidlmemory/mapping.h>
#include <log/log.h>
#include <openssl/aes.h>
#include <memory>
#include <random>
#include "drm_hal_vendor_module_api.h"
#include "vendor_modules.h"
#include <VtsHalHidlTargetCallbackBase.h>
using ::android::hardware::drm::V1_0::BufferType;
using ::android::hardware::drm::V1_0::DestinationBuffer;
using ::android::hardware::drm::V1_0::EventType;
using ::android::hardware::drm::V1_0::ICryptoFactory;
using ::android::hardware::drm::V1_0::ICryptoPlugin;
using ::android::hardware::drm::V1_0::IDrmFactory;
using ::android::hardware::drm::V1_0::IDrmPlugin;
using ::android::hardware::drm::V1_0::IDrmPluginListener;
using ::android::hardware::drm::V1_0::KeyedVector;
using ::android::hardware::drm::V1_0::KeyRequestType;
using ::android::hardware::drm::V1_0::KeyStatus;
using ::android::hardware::drm::V1_0::KeyStatusType;
using ::android::hardware::drm::V1_0::KeyType;
using ::android::hardware::drm::V1_0::KeyValue;
using ::android::hardware::drm::V1_0::Mode;
using ::android::hardware::drm::V1_0::Pattern;
using ::android::hardware::drm::V1_0::SecureStop;
using ::android::hardware::drm::V1_0::SecureStopId;
using ::android::hardware::drm::V1_0::SessionId;
using ::android::hardware::drm::V1_0::SharedBuffer;
using ::android::hardware::drm::V1_0::Status;
using ::android::hardware::drm::V1_0::SubSample;
#include "android/hardware/drm/1.0/vts/drm_hal_vendor_test.h"
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hidl::allocator::V1_0::IAllocator;
using ::android::hidl::memory::V1_0::IMemory;
using ::android::sp;
using std::string;
using std::unique_ptr;
using std::random_device;
using std::map;
using std::mt19937;
using std::vector;
using ContentConfiguration = ::DrmHalVTSVendorModule_V1::ContentConfiguration;
using Key = ::DrmHalVTSVendorModule_V1::ContentConfiguration::Key;
#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
#define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk())
#define RETURN_IF_SKIPPED \
if (vendorModule == nullptr || !vendorModule->isInstalled()) { \
GTEST_SKIP() << "This drm scheme not supported." \
<< " library:" << GetParam() << " service-name:" \
<< (vendorModule == nullptr ? "N/A" : vendorModule->getServiceName()) \
<< std::endl; \
return; \
}
static const uint8_t kInvalidUUID[16] = {
0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
};
static drm_vts::VendorModules* gVendorModules = nullptr;
class DrmHalVendorFactoryTest : public testing::TestWithParam<std::string> {
public:
DrmHalVendorFactoryTest()
: vendorModule(
static_cast<DrmHalVTSVendorModule_V1*>(gVendorModules->getModule(GetParam()))) {}
virtual ~DrmHalVendorFactoryTest() {}
virtual void SetUp() {
const ::testing::TestInfo* const test_info =
::testing::UnitTest::GetInstance()->current_test_info();
ALOGD("Running test %s.%s from vendor module %s", test_info->test_case_name(),
test_info->name(), GetParam().c_str());
const std::string instance = GetParam();
if (instance == "widevine") {
ASSERT_NE(nullptr, vendorModule.get());
}
if (vendorModule == nullptr) {
GTEST_SKIP() << "No vendor module available";
} else {
ASSERT_EQ(instance, vendorModule->getServiceName());
contentConfigurations = vendorModule->getContentConfigurations();
}
drmFactory = IDrmFactory::getService(instance);
ASSERT_NE(nullptr, drmFactory.get());
cryptoFactory = ICryptoFactory::getService(instance);
ASSERT_NE(nullptr, cryptoFactory.get());
// If drm scheme not installed skip subsequent tests
if (!drmFactory->isCryptoSchemeSupported(getVendorUUID())) {
// no GTEST_SKIP since only some tests require the module
vendorModule->setInstalled(false);
}
}
protected:
hidl_array<uint8_t, 16> getVendorUUID() {
if (vendorModule == nullptr) return {};
vector<uint8_t> uuid = vendorModule->getUUID();
return hidl_array<uint8_t, 16>(&uuid[0]);
static drm_vts::VendorModules* gVendorModules = [] {
#if defined(__LP64__)
const char* kModulePath = "/data/local/tmp/64/lib";
#else
const char* kModulePath = "/data/local/tmp/32/lib";
#endif
auto modules = new drm_vts::VendorModules(kModulePath);
if (modules->getPathList().size() == 0) {
std::cerr << "WARNING: No vendor modules found in " << kModulePath <<
", all vendor tests will be skipped" << std::endl;
}
return modules;
}();
sp<IDrmFactory> drmFactory;
sp<ICryptoFactory> cryptoFactory;
unique_ptr<DrmHalVTSVendorModule_V1> vendorModule;
vector<ContentConfiguration> contentConfigurations;
};
namespace android {
namespace hardware {
namespace drm {
namespace V1_0 {
namespace vts {
DrmHalVendorFactoryTest::DrmHalVendorFactoryTest()
: vendorModule(static_cast<DrmHalVTSVendorModule_V1*>(
gVendorModules->getModuleByName(GetParam().instance_))) {} // getModuleByName
TEST_P(DrmHalVendorFactoryTest, ValidateConfigurations) {
const char* kVendorStr = "Vendor module ";
@ -195,8 +103,8 @@ TEST_P(DrmHalVendorFactoryTest, EmptyPluginUUIDNotSupported) {
*/
TEST_P(DrmHalVendorFactoryTest, PluginConfigUUIDSupported) {
RETURN_IF_SKIPPED;
EXPECT_TRUE(drmFactory->isCryptoSchemeSupported(getVendorUUID()));
EXPECT_TRUE(cryptoFactory->isCryptoSchemeSupported(getVendorUUID()));
EXPECT_TRUE(drmFactory->isCryptoSchemeSupported(getUUID()));
EXPECT_TRUE(cryptoFactory->isCryptoSchemeSupported(getUUID()));
}
/**
@ -232,7 +140,7 @@ TEST_P(DrmHalVendorFactoryTest, CreateVendorDrmPlugin) {
RETURN_IF_SKIPPED;
hidl_string packageName("android.hardware.drm.test");
auto res = drmFactory->createPlugin(
getVendorUUID(), packageName,
getUUID(), packageName,
[&](Status status, const sp<IDrmPlugin>& plugin) {
EXPECT_EQ(Status::OK, status);
EXPECT_NE(nullptr, plugin.get());
@ -247,7 +155,7 @@ TEST_P(DrmHalVendorFactoryTest, CreateVendorCryptoPlugin) {
RETURN_IF_SKIPPED;
hidl_vec<uint8_t> initVec;
auto res = cryptoFactory->createPlugin(
getVendorUUID(), initVec,
getUUID(), initVec,
[&](Status status, const sp<ICryptoPlugin>& plugin) {
EXPECT_EQ(Status::OK, status);
EXPECT_NE(nullptr, plugin.get());
@ -285,50 +193,6 @@ TEST_P(DrmHalVendorFactoryTest, CreateInvalidCryptoPlugin) {
EXPECT_OK(res);
}
class DrmHalVendorPluginTest : public DrmHalVendorFactoryTest {
public:
virtual ~DrmHalVendorPluginTest() {}
virtual void SetUp() override {
// Create factories
DrmHalVendorFactoryTest::SetUp();
RETURN_IF_SKIPPED;
hidl_string packageName("android.hardware.drm.test");
auto res = drmFactory->createPlugin(
getVendorUUID(), packageName,
[this](Status status, const sp<IDrmPlugin>& plugin) {
EXPECT_EQ(Status::OK, status);
ASSERT_NE(nullptr, plugin.get());
drmPlugin = plugin;
});
ASSERT_OK(res);
hidl_vec<uint8_t> initVec;
res = cryptoFactory->createPlugin(
getVendorUUID(), initVec,
[this](Status status, const sp<ICryptoPlugin>& plugin) {
EXPECT_EQ(Status::OK, status);
ASSERT_NE(nullptr, plugin.get());
cryptoPlugin = plugin;
});
ASSERT_OK(res);
}
virtual void TearDown() override {}
SessionId openSession();
void closeSession(const SessionId& sessionId);
sp<IMemory> getDecryptMemory(size_t size, size_t index);
KeyedVector toHidlKeyedVector(const map<string, string>& params);
hidl_vec<uint8_t> loadKeys(const SessionId& sessionId,
const ContentConfiguration& configuration,
const KeyType& type);
protected:
sp<IDrmPlugin> drmPlugin;
sp<ICryptoPlugin> cryptoPlugin;
};
/**
* DrmPlugin tests
*/
@ -1193,7 +1057,7 @@ sp<IMemory> DrmHalVendorPluginTest::getDecryptMemory(size_t size,
EXPECT_OK(res);
sp<IMemory> mappedMemory = mapMemory(hidlMemory);
sp<IMemory> mappedMemory = android::hardware::mapMemory(hidlMemory);
EXPECT_NE(nullptr, mappedMemory.get());
res = cryptoPlugin->setSharedBufferBase(hidlMemory, index);
EXPECT_OK(res);
@ -1237,29 +1101,6 @@ TEST_P(DrmHalVendorPluginTest, SetMediaDrmSessionEmptySession) {
* Decrypt tests
*/
class DrmHalVendorDecryptTest : public DrmHalVendorPluginTest {
public:
DrmHalVendorDecryptTest() = default;
virtual ~DrmHalVendorDecryptTest() {}
protected:
void fillRandom(const sp<IMemory>& memory);
hidl_array<uint8_t, 16> toHidlArray(const vector<uint8_t>& vec) {
EXPECT_EQ(vec.size(), 16u);
return hidl_array<uint8_t, 16>(&vec[0]);
}
hidl_vec<KeyValue> queryKeyStatus(SessionId sessionId);
void removeKeys(SessionId sessionId);
uint32_t decrypt(Mode mode, bool isSecure,
const hidl_array<uint8_t, 16>& keyId, uint8_t* iv,
const hidl_vec<SubSample>& subSamples, const Pattern& pattern,
const vector<uint8_t>& key, Status expectedStatus);
void aes_ctr_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv,
const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key);
void aes_cbc_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv,
const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key);
};
void DrmHalVendorDecryptTest::fillRandom(const sp<IMemory>& memory) {
random_device rd;
mt19937 rand(rd());
@ -1566,47 +1407,8 @@ TEST_P(DrmHalVendorDecryptTest, AttemptDecryptWithKeysRemoved) {
}
}
/**
* Instantiate the set of test cases for each vendor module
*/
static const std::set<std::string> kAllInstances = [] {
std::vector<std::string> drmInstances =
android::hardware::getAllHalInstanceNames(IDrmFactory::descriptor);
std::vector<std::string> cryptoInstances =
android::hardware::getAllHalInstanceNames(ICryptoFactory::descriptor);
std::set<std::string> allInstances;
allInstances.insert(drmInstances.begin(), drmInstances.end());
allInstances.insert(cryptoInstances.begin(), cryptoInstances.end());
return allInstances;
}();
INSTANTIATE_TEST_CASE_P(DrmHalVendorFactoryTestCases, DrmHalVendorFactoryTest,
testing::ValuesIn(kAllInstances),
android::hardware::PrintInstanceNameToString);
INSTANTIATE_TEST_CASE_P(DrmHalVendorPluginTestCases, DrmHalVendorPluginTest,
testing::ValuesIn(kAllInstances),
android::hardware::PrintInstanceNameToString);
INSTANTIATE_TEST_CASE_P(DrmHalVendorDecryptTestCases, DrmHalVendorDecryptTest,
testing::ValuesIn(kAllInstances),
android::hardware::PrintInstanceNameToString);
int main(int argc, char** argv) {
#if defined(__LP64__)
const char* kModulePath = "/data/local/tmp/64/lib";
#else
const char* kModulePath = "/data/local/tmp/32/lib";
#endif
gVendorModules = new drm_vts::VendorModules(kModulePath);
if (gVendorModules->getPathList().size() == 0) {
std::cerr << "WARNING: No vendor modules found in " << kModulePath <<
", all vendor tests will be skipped" << std::endl;
}
::testing::InitGoogleTest(&argc, argv);
int status = RUN_ALL_TESTS();
ALOGI("Test result = %d", status);
return status;
}
} // namespace vts
} // namespace V1_0
} // namespace drm
} // namespace hardware
} // namespace android

View file

@ -0,0 +1,201 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef DRM_HAL_CLEARKEY_TEST_H
#define DRM_HAL_CLEARKEY_TEST_H
#include <android/hardware/drm/1.0/ICryptoFactory.h>
#include <android/hardware/drm/1.0/ICryptoPlugin.h>
#include <android/hardware/drm/1.0/IDrmFactory.h>
#include <android/hardware/drm/1.0/IDrmPlugin.h>
#include <android/hardware/drm/1.0/types.h>
#include <android/hidl/allocator/1.0/IAllocator.h>
#include <gtest/gtest.h>
#include <hidl/HidlSupport.h>
#include <hidl/ServiceManagement.h>
#include <hidlmemory/mapping.h>
#include <log/log.h>
#include "drm_vts_helper.h"
using ::android::hidl::allocator::V1_0::IAllocator;
using ::android::hidl::memory::V1_0::IMemory;
using ::drm_vts::DrmHalTestParam;
using ::drm_vts::PrintParamInstanceToString;
using std::string;
using std::map;
using std::vector;
/**
* These clearkey tests use white box knowledge of the legacy clearkey
* plugin to verify that the HIDL HAL services and interfaces are working.
* It is not intended to verify any vendor's HAL implementation. If you
* are looking for vendor HAL tests, see drm_hal_vendor_test.cpp
*/
#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
#define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk())
namespace android {
namespace hardware {
namespace drm {
namespace V1_0 {
namespace vts {
class DrmHalClearkeyFactoryTest : public ::testing::TestWithParam<DrmHalTestParam> {
public:
void SetUp() override {
const ::testing::TestInfo* const test_info =
::testing::UnitTest::GetInstance()->current_test_info();
ALOGD("Running test %s.%s", test_info->test_case_name(),
test_info->name());
const std::string instanceName = GetParam().instance_;
drmFactory = IDrmFactory::getService(instanceName);
ASSERT_NE(nullptr, drmFactory.get());
cryptoFactory = ICryptoFactory::getService(instanceName);
ASSERT_NE(nullptr, cryptoFactory.get());
const bool drmClearKey = drmFactory->isCryptoSchemeSupported(kClearKeyUUID);
const bool cryptoClearKey = cryptoFactory->isCryptoSchemeSupported(kClearKeyUUID);
EXPECT_EQ(drmClearKey, cryptoClearKey);
const bool supportsClearKey = drmClearKey && cryptoClearKey;
const bool drmCommonPsshBox = drmFactory->isCryptoSchemeSupported(kCommonPsshBoxUUID);
const bool cryptoCommonPsshBox = cryptoFactory->isCryptoSchemeSupported(kCommonPsshBoxUUID);
EXPECT_EQ(drmCommonPsshBox, cryptoCommonPsshBox);
const bool supportsCommonPsshBox = drmCommonPsshBox && cryptoCommonPsshBox;
EXPECT_EQ(supportsClearKey, supportsCommonPsshBox);
correspondsToThisTest = supportsClearKey && supportsCommonPsshBox;
if (instanceName == "clearkey") {
EXPECT_TRUE(correspondsToThisTest);
// TODO(b/147449315)
// Only the clearkey plugged into the "default" instance supports
// this test. Currently the "clearkey" instance fails some tests
// here.
GTEST_SKIP() << "Clearkey tests don't work with 'clearkey' instance yet.";
}
if (!correspondsToThisTest) {
GTEST_SKIP() << "Cannot test clearkey features on non-clearkey DRM modules";
}
}
protected:
static constexpr uint8_t kCommonPsshBoxUUID[16] = {
0x10, 0x77, 0xEF, 0xEC, 0xC0, 0xB2, 0x4D, 0x02,
0xAC, 0xE3, 0x3C, 0x1E, 0x52, 0xE2, 0xFB, 0x4B};
// To be used in mpd to specify drm scheme for players
static constexpr uint8_t kClearKeyUUID[16] = {
0xE2, 0x71, 0x9D, 0x58, 0xA9, 0x85, 0xB3, 0xC9,
0x78, 0x1A, 0xB0, 0x30, 0xAF, 0x78, 0xD3, 0x0E};
sp<IDrmFactory> drmFactory;
sp<ICryptoFactory> cryptoFactory;
bool correspondsToThisTest;
};
class DrmHalClearkeyPluginTest : public DrmHalClearkeyFactoryTest {
public:
virtual void SetUp() override {
// Create factories
DrmHalClearkeyFactoryTest::SetUp();
if (!correspondsToThisTest) {
GTEST_SKIP() << "Cannot test clearkey features on non-clearkey DRM modules";
}
ASSERT_NE(nullptr, drmFactory.get());
hidl_string packageName("android.hardware.drm.test");
auto res = drmFactory->createPlugin(
getUUID(), packageName,
[this](Status status, const sp<IDrmPlugin>& plugin) {
EXPECT_EQ(Status::OK, status);
ASSERT_NE(nullptr, plugin.get());
drmPlugin = plugin;
});
ASSERT_OK(res);
hidl_vec<uint8_t> initVec;
res = cryptoFactory->createPlugin(
getUUID(), initVec,
[this](Status status, const sp<ICryptoPlugin>& plugin) {
EXPECT_EQ(Status::OK, status);
ASSERT_NE(nullptr, plugin.get());
cryptoPlugin = plugin;
});
ASSERT_OK(res);
}
SessionId openSession();
void closeSession(const SessionId& sessionId);
hidl_vec<uint8_t> loadKeys(const SessionId& sessionId, const KeyType& type);
sp<IMemory> getDecryptMemory(size_t size, size_t index);
protected:
hidl_array<uint8_t, 16> getUUID() {
if (GetParamUUID() == hidl_array<uint8_t, 16>()) {
return kClearKeyUUID;
}
return GetParamUUID();
}
hidl_array<uint8_t, 16> GetParamUUID() {
return GetParam().scheme_;
}
sp<IDrmPlugin> drmPlugin;
sp<ICryptoPlugin> cryptoPlugin;
};
class DrmHalClearkeyDecryptTest : public DrmHalClearkeyPluginTest {
public:
void SetUp() override {
DrmHalClearkeyPluginTest::SetUp();
if (!correspondsToThisTest) {
GTEST_SKIP() << "Cannot test clearkey features on non-clearkey DRM modules";
}
}
void fillRandom(const sp<IMemory>& memory);
hidl_array<uint8_t, 16> toHidlArray(const vector<uint8_t>& vec) {
EXPECT_EQ(16u, vec.size());
return hidl_array<uint8_t, 16>(&vec[0]);
}
uint32_t decrypt(Mode mode, uint8_t* iv, const hidl_vec<SubSample>& subSamples,
const Pattern& pattern, Status status);
void aes_ctr_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv,
const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key);
void aes_cbc_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv,
const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key);
void decryptWithInvalidKeys(hidl_vec<uint8_t>& invalidResponse,
vector<uint8_t>& iv, const Pattern& noPattern, const vector<SubSample>& subSamples);
};
} // namespace vts
} // namespace V1_0
} // namespace drm
} // namespace hardware
} // namespace android
#endif // DRM_HAL_CLEARKEY_TEST_H

View file

@ -0,0 +1,209 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef DRM_HAL_VENDOR_TEST_H
#define DRM_HAL_VENDOR_TEST_H
#include <android/hardware/drm/1.0/ICryptoFactory.h>
#include <android/hardware/drm/1.0/ICryptoPlugin.h>
#include <android/hardware/drm/1.0/IDrmFactory.h>
#include <android/hardware/drm/1.0/IDrmPlugin.h>
#include <android/hardware/drm/1.0/IDrmPluginListener.h>
#include <android/hardware/drm/1.0/types.h>
#include <android/hidl/allocator/1.0/IAllocator.h>
#include <gtest/gtest.h>
#include <hidl/HidlSupport.h>
#include <hidl/ServiceManagement.h>
#include <hidlmemory/mapping.h>
#include <log/log.h>
#include <memory>
#include <set>
#include <vector>
#include "drm_hal_vendor_module_api.h"
#include "drm_vts_helper.h"
#include "vendor_modules.h"
#include <VtsHalHidlTargetCallbackBase.h>
using ::android::hidl::allocator::V1_0::IAllocator;
using ::android::hidl::memory::V1_0::IMemory;
using ::drm_vts::DrmHalTestParam;
using ::drm_vts::PrintParamInstanceToString;
using std::string;
using std::unique_ptr;
using std::map;
using std::vector;
using ContentConfiguration = ::DrmHalVTSVendorModule_V1::ContentConfiguration;
using Key = ::DrmHalVTSVendorModule_V1::ContentConfiguration::Key;
#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
#define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk())
#define RETURN_IF_SKIPPED \
if (vendorModule == nullptr || !vendorModule->isInstalled()) { \
GTEST_SKIP() << "This drm scheme not supported." \
<< " library:" << GetParam() << " service-name:" \
<< (vendorModule == nullptr ? "N/A" : vendorModule->getServiceName()) \
<< std::endl; \
return; \
}
namespace android {
namespace hardware {
namespace drm {
namespace V1_0 {
namespace vts {
class DrmHalVendorFactoryTest : public testing::TestWithParam<DrmHalTestParam> {
public:
DrmHalVendorFactoryTest();
virtual ~DrmHalVendorFactoryTest() {}
virtual void SetUp() {
const ::testing::TestInfo* const test_info =
::testing::UnitTest::GetInstance()->current_test_info();
ALOGD("Running test %s.%s from vendor module %s", test_info->test_case_name(),
test_info->name(), GetParam().instance_.c_str());
const std::string instance = GetParam().instance_;
if (instance == "widevine") {
ASSERT_NE(nullptr, vendorModule.get());
}
if (vendorModule == nullptr) {
GTEST_SKIP() << "No vendor module available";
} else {
ASSERT_EQ(instance, vendorModule->getServiceName());
contentConfigurations = vendorModule->getContentConfigurations();
}
drmFactory = IDrmFactory::getService(instance);
ASSERT_NE(nullptr, drmFactory.get());
cryptoFactory = ICryptoFactory::getService(instance);
ASSERT_NE(nullptr, cryptoFactory.get());
// If drm scheme not installed skip subsequent tests
if (!drmFactory->isCryptoSchemeSupported(getUUID())) {
// no GTEST_SKIP since only some tests require the module
vendorModule->setInstalled(false);
hidl_array<uint8_t, 16> noUUID;
ASSERT_EQ(GetParamUUID(), noUUID) << "param uuid unsupported";
}
}
protected:
hidl_array<uint8_t, 16> getUUID() {
if (GetParamUUID() == hidl_array<uint8_t, 16>()) {
return getVendorUUID();
}
return GetParamUUID();
}
hidl_array<uint8_t, 16> getVendorUUID() {
if (vendorModule == nullptr) return {};
vector<uint8_t> uuid = vendorModule->getUUID();
return hidl_array<uint8_t, 16>(&uuid[0]);
}
hidl_array<uint8_t, 16> GetParamUUID() {
return GetParam().scheme_;
}
sp<IDrmFactory> drmFactory;
sp<ICryptoFactory> cryptoFactory;
unique_ptr<DrmHalVTSVendorModule_V1> vendorModule;
vector<ContentConfiguration> contentConfigurations;
};
class DrmHalVendorPluginTest : public DrmHalVendorFactoryTest {
public:
virtual ~DrmHalVendorPluginTest() {}
virtual void SetUp() override {
// Create factories
DrmHalVendorFactoryTest::SetUp();
RETURN_IF_SKIPPED;
hidl_string packageName("android.hardware.drm.test");
auto res = drmFactory->createPlugin(
getVendorUUID(), packageName,
[this](Status status, const sp<IDrmPlugin>& plugin) {
EXPECT_EQ(Status::OK, status);
ASSERT_NE(nullptr, plugin.get());
drmPlugin = plugin;
});
ASSERT_OK(res);
hidl_vec<uint8_t> initVec;
res = cryptoFactory->createPlugin(
getVendorUUID(), initVec,
[this](Status status, const sp<ICryptoPlugin>& plugin) {
EXPECT_EQ(Status::OK, status);
ASSERT_NE(nullptr, plugin.get());
cryptoPlugin = plugin;
});
ASSERT_OK(res);
}
virtual void TearDown() override {}
SessionId openSession();
void closeSession(const SessionId& sessionId);
sp<IMemory> getDecryptMemory(size_t size, size_t index);
KeyedVector toHidlKeyedVector(const map<string, string>& params);
hidl_vec<uint8_t> loadKeys(const SessionId& sessionId,
const ContentConfiguration& configuration,
const KeyType& type);
protected:
sp<IDrmPlugin> drmPlugin;
sp<ICryptoPlugin> cryptoPlugin;
};
class DrmHalVendorDecryptTest : public DrmHalVendorPluginTest {
public:
DrmHalVendorDecryptTest() = default;
virtual ~DrmHalVendorDecryptTest() {}
protected:
void fillRandom(const sp<IMemory>& memory);
hidl_array<uint8_t, 16> toHidlArray(const vector<uint8_t>& vec) {
EXPECT_EQ(vec.size(), 16u);
return hidl_array<uint8_t, 16>(&vec[0]);
}
hidl_vec<KeyValue> queryKeyStatus(SessionId sessionId);
void removeKeys(SessionId sessionId);
uint32_t decrypt(Mode mode, bool isSecure,
const hidl_array<uint8_t, 16>& keyId, uint8_t* iv,
const hidl_vec<SubSample>& subSamples, const Pattern& pattern,
const vector<uint8_t>& key, Status expectedStatus);
void aes_ctr_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv,
const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key);
void aes_cbc_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv,
const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key);
};
} // namespace vts
} // namespace V1_0
} // namespace drm
} // namespace hardware
} // namespace android
#endif // DRM_HAL_VENDOR_TEST_H

View file

@ -0,0 +1,234 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef DRM_HAL_VENDOR_MODULE_API_H
#define DRM_HAL_VENDOR_MODULE_API_H
#include <stdint.h>
#include <map>
#include <string>
#include <vector>
/**
* The DRM and Crypto HALs interact with vendor-provided HAL implementations
* that have DRM-specific capabilities. Since the VTS tests cannot contain
* DRM-specific functionality, supporting modules are required to enable VTS
* to validate HAL implementations in a generic way. If the vendor-specific
* VTS module is not provided for a given drm HAL implementation, only very
* small subset of functionality can be verified.
*
* As an example, a DRM HAL implementation interacts with a DRM-specific
* license server to obtain licenses for decrypting content. The DRM HAL
* implementation generates a key request message, delivers it to the server
* and receives a key response message which is then loaded into the HAL. Once
* the keys are loaded, the Crypto HAL decryption functionality and performance
* and other associated APIs can be tested by the common VTS test suite.
*
* Vendor-specific VTS modules are shared libraries used by the DRM VTS test.
* They provide a set of functions to support VTS testing of the DRM HAL module.
*
* The modules are placed in a common location on the file system. The VTS test
* scans through all vendor-provided support libraries and runs the VTS test
* suite on each library that is found.
*
* The vendor-specific module exposes an extern C vendorModuleFactory()
* function that returns a DrmHalVTSVendorModule instance. DrmHalVTSVendorModule
* instances are versioned, where each version is represented by subclass of
* DrmHalVTSVendorModule that corresponds to the API version. For example, a
* vendor-specific module that implements version 1 of the API would return a
* DrmHalVTSVendorModule_V1 from the vendorModuleFactory() function.
*/
class DrmHalVTSVendorModule;
extern "C" {
/**
* The factory method for creating DrmHalVTSVendorModule instances. The returned
* instance will be a subclass of DrmHalVTSVendorModule that corresponds to the
* supported API version.
*/
DrmHalVTSVendorModule* vendorModuleFactory();
};
class DrmHalVTSVendorModule {
public:
DrmHalVTSVendorModule() : installed(true) {}
virtual ~DrmHalVTSVendorModule() {}
/**
* Return the vendor-specific module API version. The version is an integer
* value with initial version 1. The API version indicates which subclass
* version DrmHalVTSVendorModule this instance is.
*/
virtual uint32_t getAPIVersion() const = 0;
/**
* Return the UUID for the DRM HAL implementation. Protection System
* Specific
* UUID (see http://dashif.org/identifiers/protection/)
*/
virtual std::vector<uint8_t> getUUID() const = 0;
/**
* Return the service name for the DRM HAL implementation. If the hal is a
* legacy
* drm plugin, i.e. not running as a HIDL service, return the empty string.
*/
virtual std::string getServiceName() const = 0;
/**
* Set a flag in the vendor module to indicate whether or not the drm
* scheme corresponding to this module is installed on the device.
*/
void setInstalled(bool flag) {installed = flag;}
bool isInstalled() const {return installed;}
private:
bool installed;
DrmHalVTSVendorModule(const DrmHalVTSVendorModule&) = delete;
void operator=(const DrmHalVTSVendorModule&) = delete;
};
/**
* API Version 1. This is the baseline version that supports a minimal set
* of VTS tests.
*/
class DrmHalVTSVendorModule_V1 : public DrmHalVTSVendorModule {
public:
DrmHalVTSVendorModule_V1() {}
virtual ~DrmHalVTSVendorModule_V1() {}
virtual uint32_t getAPIVersion() const { return 1; }
/**
* Handle a provisioning request. This function will be called if the HAL
* module's getProvisionRequest returns a provision request. The vendor
* module should process the provisioning request, either by sending it
* to a provisioning server, or generating a mock response. The resulting
* provisioning response is returned to the VTS test.
*
* @param provisioningRequest the provisioning request recieved from
* the DRM HAL
* @param url the default url the HAL implementation provided with the
* provisioning request
* @return the generated provisioning response
*/
virtual std::vector<uint8_t> handleProvisioningRequest(
const std::vector<uint8_t>& provisioningRequest,
const std::string& url) = 0;
/**
* Content configuration specifies content-specific parameters associated
* with a key request/response transaction. It allows the VTS test to
* request keys and use them to perform decryption.
*/
struct ContentConfiguration {
/**
* Assign a name for this configuration that will be referred to
* in log messages.
*/
const std::string name;
/**
* Server to use when requesting a key response. This url will be
* passed as a parameter to the vendor vts module along with the
* key request to perform the key request transaction.
*/
const std::string serverUrl;
/**
* Initialization data provided to getKeyRequest, e.g. PSSH for CENC
* content
*/
const std::vector<uint8_t> initData;
/**
* Mime type provided to getKeyRequest, e.g. "video/mp4", or "cenc"
*/
const std::string mimeType;
/**
* Optional parameters to be associated with the key request
*/
const std::map<std::string, std::string> optionalParameters;
/**
* Define license policy attributes for the content configuration.
* These attributes can affect which tests are able to be applied.
*/
struct Policy {
/**
* Indicate if the license policy allows offline playback.
* Content configurated with this policy supports KeyType::OFFLINE
* key requests/responses. A vendor module should provide at least
* one content configuration where allowOffline is true if the drm
* scheme supports offline content.
*/
bool allowOffline;
} policy;
/**
* The keys that will be available once the keys are loaded
*/
struct Key {
/**
* Indicate if the key content is configured to require secure
* buffers, where the output buffers are protected and cannot be
* accessed by the non-secure cpu. A vendor module should provide
* at least one content configurations where isSecure is false, to
* allow decrypt result verification tests to be run.
*/
bool isSecure;
/**
* A key ID identifies a key to use for decryption
*/
const std::vector<uint8_t> keyId;
/**
* The clear content key is provided to generate expected values for
* validating decryption.
*/
const std::vector<uint8_t> clearContentKey;
};
std::vector<Key> keys;
};
/**
* Return a list of content configurations that can be exercised by the
* VTS test.
*/
virtual std::vector<ContentConfiguration>
getContentConfigurations() const = 0;
/**
* Handle a key request. This function will be called if the HAL
* module's getKeyRequest returns a key request. The vendor
* module should process the key request, either by sending it
* to a license server, or by generating a mock response. The resulting
* key response is returned to the VTS test.
*
* @param keyRequest the key request recieved from the DRM HAL
* @param serverUrl the url of the key server that was supplied
* by the ContentConfiguration
* @return the generated key response
*/
virtual std::vector<uint8_t> handleKeyRequest(
const std::vector<uint8_t>& keyRequest,
const std::string& serverUrl) = 0;
};
#endif // DRM_HAL_VENDOR_MODULE_API_H