libhidladapter: Support for HIDL adapters

A HIDL adapter takes an x.(y+1) interface and registers
it as an x.y interface for testing.

This library allows someone or something to run an adapter.

Note: this requires b/62303973 to properly mock a lower interface version.
Note: this requires adapters to run as root to get around sepolicy.

Bug: 37518178
Test: can switch out implementations
~/android/master$ lshal | grep hidl.allocator
Y android.hidl.allocator@1.0::IAllocator/ashmem                               0/1        652    471
~/android/master$ lshal | grep hidl.allocator
Y android.hidl.allocator@1.0::IAllocator/ashmem                               0/1        7635   471
~/android/master$ lshal | grep hidl.allocator
Y android.hidl.allocator@1.0::IAllocator/ashmem                               0/1        652    471

Change-Id: Ic72feb3a2fd4649e67b396c33b9a292e9c0a944a
diff --git a/adapter/HidlBinderAdapter.cpp b/adapter/HidlBinderAdapter.cpp
new file mode 100644
index 0000000..e769cb5
--- /dev/null
+++ b/adapter/HidlBinderAdapter.cpp
@@ -0,0 +1,122 @@
+/*
+ * 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/hidl/base/1.0/IBase.h>
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include <iostream>
+#include <map>
+#include <string>
+
+namespace android {
+namespace hardware {
+namespace details {
+
+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;
+
+    if (argc != 4) {
+        std::cerr << "usage: " << argv[0] << " interface-name instance-name number-of-threads."
+                  << std::endl;
+        return 1;
+    }
+
+    std::string interfaceName = package + "::" + argv[1];
+    std::string instanceName = argv[2];
+    int threadNumber = std::stoi(argv[3]);
+
+    if (threadNumber <= 0) {
+        std::cerr << "ERROR: invalid thread number " << threadNumber
+                  << " must be a positive integer.";
+    }
+
+    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 << "/" << instanceName << std::endl;
+
+    configureRpcThreadpool(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, 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(instanceName, adapter).withDefault(false);
+    if (!replaced) {
+        std::cerr << "ERROR: could not register the service with the service manager." << std::endl;
+        return 1;
+    }
+
+    std::cout << "Press any key to disassociate adapter." << std::endl;
+    getchar();
+
+    bool restored = manager->add(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;
+
+    auto it = sAdapterMap.find(something);
+    if (it == sAdapterMap.end()) {
+        it = sAdapterMap.insert(it, {something, makeDefault()});
+    }
+
+    return it->second;
+}
+
+}  // namespace details
+}  // namespace hardware
+}  // namespace android