/* * 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 "VtsTrebleVintfTestBase.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "SingleManifestTest.h" #include "utils.h" namespace android { namespace vintf { namespace testing { using android::FqInstance; 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::hardware::Return; using android::hidl::base::V1_0::IBase; using android::hidl::manager::V1_0::IServiceManager; using android::procpartition::Partition; using android::vintf::HalManifest; using android::vintf::Level; using android::vintf::ManifestHal; using android::vintf::Transport; using android::vintf::Version; using android::vintf::VintfObject; using android::vintf::operator<<; using android::vintf::to_string; using android::vintf::toFQNameString; using std::cout; using std::endl; using std::map; using std::set; using std::string; using std::vector; void VtsTrebleVintfTestBase::SetUp() { default_manager_ = ::android::hardware::defaultServiceManager(); ASSERT_NE(default_manager_, nullptr) << "Failed to get default service manager." << endl; } void VtsTrebleVintfTestBase::ForEachHidlHalInstance( const HalManifestPtr &manifest, HidlVerifyFn fn) { manifest->forEachInstance([manifest, fn](const auto &manifest_instance) { if (manifest_instance.format() != HalFormat::HIDL) { return true; // continue to next instance } const FQName fq_name{manifest_instance.package(), to_string(manifest_instance.version()), manifest_instance.interface()}; const Transport transport = manifest_instance.transport(); const std::string instance_name = manifest_instance.instance(); auto future_result = std::async([&]() { fn(fq_name, instance_name, transport); }); auto timeout = std::chrono::seconds(1); 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 }); } void VtsTrebleVintfTestBase::ForEachAidlHalInstance( const HalManifestPtr &manifest, AidlVerifyFn fn) { manifest->forEachInstance([manifest, fn](const auto &manifest_instance) { if (manifest_instance.format() != HalFormat::AIDL) { return true; // continue to next instance } const std::string &package = manifest_instance.package(); uint64_t version = manifest_instance.version().minorVer; const std::string &interface = manifest_instance.interface(); const std::string &instance = manifest_instance.instance(); const std::optional &updatable_via_apex = manifest_instance.updatableViaApex(); auto future_result = std::async([&]() { fn(package, version, interface, instance, updatable_via_apex); }); auto timeout = std::chrono::seconds(1); std::future_status status = future_result.wait_for(timeout); if (status != std::future_status::ready) { cout << "Timed out on: " << package << "." << interface << "/" << instance << endl; } return true; // continue to next instance }); } sp VtsTrebleVintfTestBase::GetHidlService(const FQName &fq_name, const string &instance_name, Transport transport, bool log) { return GetHidlService(fq_name.string(), instance_name, transport, log); } sp VtsTrebleVintfTestBase::GetHidlService(const string &fq_name, const string &instance_name, Transport transport, bool log) { using android::hardware::details::getRawServiceInternal; if (log) { cout << "Getting: " << fq_name << "/" << instance_name << endl; } // getService blocks until a service is available. In 100% of other cases // where getService is used, it should be called directly. However, this test // enforces that various services are actually available when they are // declared, it must make a couple of precautions in case the service isn't // actually available so that the proper failure can be reported. auto task = std::packaged_task()>([fq_name, instance_name]() { return getRawServiceInternal(fq_name, instance_name, true /* retry */, false /* getStub */); }); auto max_time = std::chrono::seconds(1); std::future> future = task.get_future(); std::thread(std::move(task)).detach(); auto status = future.wait_for(max_time); if (status != std::future_status::ready) return nullptr; sp base = future.get(); if (base == nullptr) return nullptr; bool wantRemote = transport == Transport::HWBINDER; if (base->isRemote() != wantRemote) return nullptr; return base; } sp VtsTrebleVintfTestBase::GetAidlService(const string &name) { auto task = std::packaged_task()>([name]() { return defaultServiceManager()->waitForService(String16(name.c_str())); }); auto max_time = std::chrono::seconds(2); // TODO(b/205347235) auto future = task.get_future(); std::thread(std::move(task)).detach(); auto status = future.wait_for(max_time); return status == std::future_status::ready ? future.get() : nullptr; } vector VtsTrebleVintfTestBase::GetInstanceNames( const sp &manager, const FQName &fq_name) { vector ret; auto status = manager->listByInterface(fq_name.string(), [&](const auto &out) { for (const auto &e : out) ret.push_back(e); }); EXPECT_TRUE(status.isOk()) << status.description(); return ret; } vector VtsTrebleVintfTestBase::GetInterfaceChain( const sp &service) { vector iface_chain{}; service->interfaceChain([&iface_chain](const hidl_vec &chain) { for (const auto &iface_name : chain) { iface_chain.push_back(iface_name); } }); return iface_chain; } Partition VtsTrebleVintfTestBase::GetPartition(sp hal_service) { Partition partition = Partition::UNKNOWN; auto ret = hal_service->getDebugInfo( [&](const auto &info) { partition = PartitionOfProcess(info.pid); }); EXPECT_TRUE(ret.isOk()); return partition; } set VtsTrebleVintfTestBase::GetPassthroughHals( HalManifestPtr manifest) { std::set manifest_passthrough_hals_; auto add_manifest_hals = [&manifest_passthrough_hals_]( const FQName &fq_name, const string &instance_name, Transport transport) { if (transport == Transport::HWBINDER) { // ignore } else if (transport == Transport::PASSTHROUGH) { // 1.n in manifest => 1.0, 1.1, ... 1.n are all served (if they exist) FQName fq = fq_name; while (true) { manifest_passthrough_hals_.insert(fq.string() + "/" + instance_name); if (fq.getPackageMinorVersion() <= 0) break; fq = fq.downRev(); } } else { ADD_FAILURE() << "Unrecognized transport: " << transport; } }; ForEachHidlHalInstance(manifest, add_manifest_hals); return manifest_passthrough_hals_; } set VtsTrebleVintfTestBase::GetHwbinderHals(HalManifestPtr manifest) { std::set manifest_hwbinder_hals_; auto add_manifest_hals = [&manifest_hwbinder_hals_]( const FQName &fq_name, const string &instance_name, Transport transport) { if (transport == Transport::HWBINDER) { // 1.n in manifest => 1.0, 1.1, ... 1.n are all served (if they exist) FQName fq = fq_name; while (true) { manifest_hwbinder_hals_.insert(fq.string() + "/" + instance_name); if (fq.getPackageMinorVersion() <= 0) break; fq = fq.downRev(); } } else if (transport == Transport::PASSTHROUGH) { // ignore } else { ADD_FAILURE() << "Unrecognized transport: " << transport; } }; ForEachHidlHalInstance(manifest, add_manifest_hals); return manifest_hwbinder_hals_; } } // namespace testing } // namespace vintf } // namespace android