blob: 4ee7dd6c914c1cd9599e52bfa222ed66e85aa298 [file] [log] [blame]
/*
* 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.
*/
#include <chrono>
#include <functional>
#include <future>
#include <iostream>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <thread>
#include <vector>
#include <android/hidl/manager/1.0/IServiceManager.h>
#include <gtest/gtest.h>
#include <hidl-hash/Hash.h>
#include <hidl-util/FQName.h>
#include <hidl/ServiceManagement.h>
#include <vintf/HalManifest.h>
#include <vintf/VintfObject.h>
#include <vintf/parse_string.h>
#include "VtsTrebleVintfTestBase.h"
namespace android {
namespace vintf {
namespace testing {
namespace legacy {
using android::FQName;
using android::Hash;
using android::sp;
using android::hardware::hidl_array;
using android::hardware::hidl_string;
using android::hardware::hidl_vec;
using android::hidl::manager::V1_0::IServiceManager;
using android::vintf::HalManifest;
using android::vintf::to_string;
using android::vintf::Transport;
using android::vintf::Version;
using android::vintf::VintfObject;
using std::cout;
using std::endl;
using std::map;
using std::set;
using std::string;
using std::vector;
using HalVerifyFn =
std::function<void(const FQName &fq_name, const string &instance_name)>;
// Returns true iff HAL interface is exempt from following rules:
// 1. If an interface is declared in VINTF, it has to be served on the device.
static bool IsExempt(const FQName &fq_iface_name) {
static const set<string> exempt_hals_ = {};
string hal_name = fq_iface_name.package();
// Radio-releated and non-Google HAL interfaces are given exemptions.
return exempt_hals_.find(hal_name) != exempt_hals_.end() ||
!IsGoogleDefinedIface(fq_iface_name);
}
class VtsTrebleVintfTest : public ::testing::Test {
public:
virtual void SetUp() override {
default_manager_ = ::android::hardware::defaultServiceManager();
ASSERT_NE(default_manager_, nullptr)
<< "Failed to get default service manager." << endl;
passthrough_manager_ = ::android::hardware::getPassthroughServiceManager();
ASSERT_NE(passthrough_manager_, nullptr)
<< "Failed to get passthrough service manager." << endl;
vendor_manifest_ = VintfObject::GetDeviceHalManifest();
ASSERT_NE(vendor_manifest_, nullptr)
<< "Failed to get vendor HAL manifest." << endl;
}
// Applies given function to each HAL instance in VINTF.
void ForEachHalInstance(HalVerifyFn);
// Retrieves an existing HAL service.
sp<android::hidl::base::V1_0::IBase> GetHalService(
const FQName &fq_name, const string &instance_name);
// Default service manager.
sp<IServiceManager> default_manager_;
// Passthrough service manager.
sp<IServiceManager> passthrough_manager_;
// Vendor hal manifest.
std::shared_ptr<const HalManifest> vendor_manifest_;
};
void VtsTrebleVintfTest::ForEachHalInstance(HalVerifyFn fn) {
vendor_manifest_->forEachInstance([fn](const auto &manifest_instance) {
const FQName fq_name{manifest_instance.package(),
to_string(manifest_instance.version()),
manifest_instance.interface()};
const std::string instance_name = manifest_instance.instance();
auto future_result = std::async([&]() { fn(fq_name, instance_name); });
auto timeout = std::chrono::milliseconds(500);
std::future_status status = future_result.wait_for(timeout);
if (status != std::future_status::ready) {
cout << "Timed out on: " << fq_name.string() << " " << instance_name
<< endl;
}
return true; // continue to next instance
});
}
sp<android::hidl::base::V1_0::IBase> VtsTrebleVintfTest::GetHalService(
const FQName &fq_name, const string &instance_name) {
string hal_name = fq_name.package();
Version version{fq_name.getPackageMajorVersion(),
fq_name.getPackageMinorVersion()};
string iface_name = fq_name.name();
string fq_iface_name = fq_name.string();
cout << "Getting service of: " << fq_iface_name << endl;
Transport transport = vendor_manifest_->getTransport(
hal_name, version, iface_name, instance_name);
return VtsTrebleVintfTestBase::GetHalService(fq_name, instance_name,
transport);
}
// Tests that no HAL outside of the allowed set is specified as passthrough in
// VINTF.
TEST_F(VtsTrebleVintfTest, HalsAreBinderized) {
// Verifies that HAL is binderized unless it's allowed to be passthrough.
HalVerifyFn is_binderized = [this](const FQName &fq_name,
const string &instance_name) {
cout << "Verifying transport method of: " << fq_name.string() << endl;
string hal_name = fq_name.package();
Version version{fq_name.getPackageMajorVersion(),
fq_name.getPackageMinorVersion()};
string iface_name = fq_name.name();
Transport transport = vendor_manifest_->getTransport(
hal_name, version, iface_name, instance_name);
EXPECT_NE(transport, Transport::EMPTY)
<< hal_name << " has no transport specified in VINTF.";
if (transport == Transport::PASSTHROUGH) {
EXPECT_NE(kPassthroughHals.find(hal_name), kPassthroughHals.end())
<< hal_name << " can't be passthrough under Treble rules.";
}
};
ForEachHalInstance(is_binderized);
}
// Tests that all HALs specified in the VINTF are available through service
// manager.
TEST_F(VtsTrebleVintfTest, VintfHalsAreServed) {
// Verifies that HAL is available through service manager.
HalVerifyFn is_available = [this](const FQName &fq_name,
const string &instance_name) {
if (IsExempt(fq_name)) {
cout << fq_name.string() << " is exempt for O-MR1 vendor." << endl;
return;
}
sp<android::hidl::base::V1_0::IBase> hal_service =
GetHalService(fq_name, instance_name);
EXPECT_NE(hal_service, nullptr)
<< fq_name.string() << " not available." << endl;
};
ForEachHalInstance(is_available);
}
// Tests that HAL interfaces are officially released.
TEST_F(VtsTrebleVintfTest, InterfacesAreReleased) {
// Verifies that HAL are released by fetching the hash of the interface and
// comparing it to the set of known hashes of released interfaces.
HalVerifyFn is_released = [this](const FQName &fq_name,
const string &instance_name) {
sp<android::hidl::base::V1_0::IBase> hal_service =
GetHalService(fq_name, instance_name);
if (hal_service == nullptr) {
if (IsExempt(fq_name)) {
cout << fq_name.string() << " is exempt for O-MR1 vendor." << endl;
} else {
ADD_FAILURE() << fq_name.package() << " not available." << endl;
}
return;
}
vector<string> iface_chain{};
hal_service->interfaceChain(
[&iface_chain](const hidl_vec<hidl_string> &chain) {
for (const auto &iface_name : chain) {
iface_chain.push_back(iface_name);
}
});
vector<string> hash_chain{};
hal_service->getHashChain(
[&hash_chain](const hidl_vec<HashCharArray> &chain) {
for (const HashCharArray &hash_array : chain) {
vector<uint8_t> hash{hash_array.data(),
hash_array.data() + hash_array.size()};
hash_chain.push_back(Hash::hexString(hash));
}
});
ASSERT_EQ(iface_chain.size(), hash_chain.size());
for (size_t i = 0; i < iface_chain.size(); ++i) {
FQName fq_iface_name;
if (!FQName::parse(iface_chain[i], &fq_iface_name)) {
ADD_FAILURE() << "Could not parse iface name " << iface_chain[i]
<< " from interface chain of " << fq_name.string();
return;
}
string hash = hash_chain[i];
if (IsGoogleDefinedIface(fq_iface_name)) {
set<string> released_hashes = ReleasedHashes(fq_iface_name);
EXPECT_NE(released_hashes.find(hash), released_hashes.end())
<< "Hash not found. This interface was not released." << endl
<< "Interface name: " << fq_iface_name.string() << endl
<< "Hash: " << hash << endl;
}
}
};
ForEachHalInstance(is_released);
}
} // namespace legacy
} // namespace testing
} // namespace vintf
} // namespace android