diff options
Diffstat (limited to 'adapter/HidlBinderAdapter.cpp')
-rw-r--r-- | adapter/HidlBinderAdapter.cpp | 237 |
1 files changed, 0 insertions, 237 deletions
diff --git a/adapter/HidlBinderAdapter.cpp b/adapter/HidlBinderAdapter.cpp deleted file mode 100644 index ed6dad1..0000000 --- a/adapter/HidlBinderAdapter.cpp +++ /dev/null @@ -1,237 +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. - */ - -#include <hidladapter/HidlBinderAdapter.h> - -#include <android-base/logging.h> -#include <android-base/properties.h> -#include <android/hidl/base/1.0/IBase.h> -#include <android/hidl/manager/1.0/IServiceManager.h> -#include <hidl/HidlTransportSupport.h> - -#include <unistd.h> -#include <iostream> -#include <map> -#include <string> - -namespace android { -namespace hardware { -namespace details { - -using android::base::SetProperty; -using android::base::WaitForProperty; - -const static std::string kDeactivateProp = "test.hidl.adapters.deactivated"; - -int usage(const std::string& me) { - std::cerr << "usage: " << me - << " [-p|P] [-n instance-name] interface-name instance-name number-of-threads." - << std::endl; - std::cerr << " -p: stop based on property " << kDeactivateProp << "and reset it." - << std::endl; - std::cerr << " -P: stop based on interface specific property " << kDeactivateProp - << ".<fq-name>.<instance-name>" << std::endl; - std::cerr - << " -n instance-name: register as a different instance name (does not de-register)" - << std::endl; - return EINVAL; -} - -enum class StopMethod { - NONE, - ALL, - SPECIFIC, -}; - -struct Args { - StopMethod stopMethod = StopMethod::NONE; - std::string interface; // e.x. IFoo - std::string instanceName; // e.x. default - int threadNumber; - std::string registerInstanceName; // e.x. default -}; - -bool processArguments(int argc, char** argv, Args* args) { - int c; - while ((c = getopt(argc, argv, "pPn:")) != -1) { - switch (c) { - case 'p': { - args->stopMethod = StopMethod::ALL; - break; - } - case 'P': { - args->stopMethod = StopMethod::SPECIFIC; - break; - } - case 'n': { - args->registerInstanceName = optarg; - break; - } - default: { return false; } - } - } - - argc -= optind; - argv += optind; - - if (argc != 3) { - std::cerr << "ERROR: requires exactly three positional arguments for " - "interface, instance name, and number of threads, but " - << argc << " provided." << std::endl; - return false; - } - - args->interface = argv[0]; - args->instanceName = argv[1]; - args->threadNumber = std::stoi(argv[2]); - - if (args->threadNumber <= 0) { - std::cerr << "ERROR: invalid thread number " << args->threadNumber - << " must be a positive integer." << std::endl; - return false; - } - - if (args->registerInstanceName.empty()) { - args->registerInstanceName = args->instanceName; - } - - return true; -} - -// only applies for -p argument -void waitForAdaptersDeactivated(const std::string& property) { - using std::literals::chrono_literals::operator""s; - - while (!WaitForProperty(property, "true", 30s)) { - // Log this so that when using this option on testing devices, there is - // a clear indication if adapters are not properly stopped - LOG(WARNING) << "Adapter use in progress. Waiting for stop based on 'true' " << property; - } - - SetProperty(property, "false"); -} - -int adapterMain(const std::string& package, int argc, char** argv, - const AdaptersFactory& adapters) { - using android::hardware::configureRpcThreadpool; - using android::hidl::base::V1_0::IBase; - using android::hidl::manager::V1_0::IServiceManager; - - const std::string& me = argc > 0 ? argv[0] : "(error)"; - - Args args; - if (!processArguments(argc, argv, &args)) { - return usage(me); - } - - std::string interfaceName = package + "::" + args.interface; - - auto it = adapters.find(interfaceName); - if (it == adapters.end()) { - std::cerr << "ERROR: could not resolve " << interfaceName << "." << std::endl; - return 1; - } - - std::cout << "Trying to adapt down " << interfaceName << "/" << args.instanceName << " to " - << args.registerInstanceName << std::endl; - - configureRpcThreadpool(args.threadNumber, false /* callerWillJoin */); - - sp<IServiceManager> manager = IServiceManager::getService(); - if (manager == nullptr) { - std::cerr << "ERROR: could not retrieve service manager." << std::endl; - return 1; - } - - sp<IBase> implementation = manager->get(interfaceName, args.instanceName).withDefault(nullptr); - if (implementation == nullptr) { - std::cerr << "ERROR: could not retrieve desired implementation" << std::endl; - return 1; - } - - sp<IBase> adapter = it->second(implementation); - if (adapter == nullptr) { - std::cerr << "ERROR: could not create adapter." << std::endl; - return 1; - } - - bool replaced = manager->add(args.registerInstanceName, adapter).withDefault(false); - if (!replaced) { - std::cerr << "ERROR: could not register the service with the service manager." << std::endl; - return 1; - } - - switch (args.stopMethod) { - case StopMethod::NONE: { - std::cout << "Press any key to disassociate adapter." << std::endl; - getchar(); - break; - }; - case StopMethod::SPECIFIC: { - const std::string property = - kDeactivateProp + "." + interfaceName + "." + args.registerInstanceName; - std::cout << "Set " << property << " to true to deactivate." << std::endl; - waitForAdaptersDeactivated(property); - break; - }; - case StopMethod::ALL: { - std::cout << "Set " << kDeactivateProp << " to true to deactivate." << std::endl; - waitForAdaptersDeactivated(kDeactivateProp); - break; - }; - } - - // automatically unregistered on process exit if it is a new instance name - if (args.registerInstanceName == args.instanceName) { - bool restored = manager->add(args.instanceName, implementation).withDefault(false); - if (!restored) { - std::cerr << "ERROR: could not re-register interface with the service manager." - << std::endl; - return 1; - } - } - - std::cout << "Success." << std::endl; - - return 0; -} - -// If an interface is adapted to 1.0, it can then not be adapted to 1.1 in the same process. -// This poses a problem in the following scenario: -// auto interface = new V1_1::implementation::IFoo; -// hidlObject1_0->foo(interface) // adaptation set at 1.0 -// hidlObject1_1->bar(interface) // adaptation still is 1.0 -// This could be solved by keeping a map of IBase,fqName -> IBase, but then you end up -// with multiple names for the same interface. -sp<IBase> adaptWithDefault(const sp<IBase>& something, - const std::function<sp<IBase>()>& makeDefault) { - static std::map<sp<IBase>, sp<IBase>> sAdapterMap; - - if (something == nullptr) { - return something; - } - - auto it = sAdapterMap.find(something); - if (it == sAdapterMap.end()) { - it = sAdapterMap.insert(it, {something, makeDefault()}); - } - - return it->second; -} - -} // namespace details -} // namespace hardware -} // namespace android |