Merge "Implement host service manager"
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index d8f8e55..da570f3 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -151,6 +151,7 @@
                 "libbase",
             ],
             srcs: [
+                "ServiceManagerHost.cpp",
                 "UtilsHost.cpp",
             ],
         },
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index d421060..2175fd4 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -35,6 +35,8 @@
 
 #ifdef __ANDROID__
 #include <cutils/properties.h>
+#else
+#include "ServiceManagerHost.h"
 #endif
 
 #include "Static.h"
@@ -84,8 +86,19 @@
     IBinder* onAsBinder() override {
         return IInterface::asBinder(mTheRealServiceManager).get();
     }
-private:
+
+protected:
     sp<AidlServiceManager> mTheRealServiceManager;
+
+    // Directly get the service in a way that, for lazy services, requests the service to be started
+    // if it is not currently started. This way, calls directly to ServiceManagerShim::getService
+    // will still have the 5s delay that is expected by a large amount of Android code.
+    //
+    // When implementing ServiceManagerShim, use realGetService instead of
+    // mTheRealServiceManager->getService so that it can be overridden in ServiceManagerHostShim.
+    virtual Status realGetService(const std::string& name, sp<IBinder>* _aidl_return) {
+        return mTheRealServiceManager->getService(name, _aidl_return);
+    }
 };
 
 [[clang::no_destroy]] static std::once_flag gSmOnce;
@@ -319,7 +332,7 @@
     const std::string name = String8(name16).c_str();
 
     sp<IBinder> out;
-    if (Status status = mTheRealServiceManager->getService(name, &out); !status.isOk()) {
+    if (Status status = realGetService(name, &out); !status.isOk()) {
         ALOGW("Failed to getService in waitForService for %s: %s", name.c_str(),
               status.toString8().c_str());
         return nullptr;
@@ -363,7 +376,7 @@
         // - init gets death signal, but doesn't know it needs to restart
         //   the service
         // - we need to request service again to get it to start
-        if (Status status = mTheRealServiceManager->getService(name, &out); !status.isOk()) {
+        if (Status status = realGetService(name, &out); !status.isOk()) {
             ALOGW("Failed to getService in waitForService on later try for %s: %s", name.c_str(),
                   status.toString8().c_str());
             return nullptr;
@@ -412,4 +425,38 @@
     return declared ? std::optional<String16>(String16(declared.value().c_str())) : std::nullopt;
 }
 
+#ifndef __ANDROID__
+// ServiceManagerShim for host. Implements the old libbinder android::IServiceManager API.
+// The internal implementation of the AIDL interface android::os::IServiceManager calls into
+// on-device service manager.
+class ServiceManagerHostShim : public ServiceManagerShim {
+public:
+    using ServiceManagerShim::ServiceManagerShim;
+    // ServiceManagerShim::getService is based on checkService, so no need to override it.
+    sp<IBinder> checkService(const String16& name) const override {
+        return getDeviceService({String8(name).c_str()});
+    }
+
+protected:
+    // Override realGetService for ServiceManagerShim::waitForService.
+    Status realGetService(const std::string& name, sp<IBinder>* _aidl_return) {
+        *_aidl_return = getDeviceService({"-g", name});
+        return Status::ok();
+    }
+};
+sp<IServiceManager> createRpcDelegateServiceManager() {
+    auto binder = getDeviceService({"manager"});
+    if (binder == nullptr) {
+        ALOGE("getDeviceService(\"manager\") returns null");
+        return nullptr;
+    }
+    auto interface = AidlServiceManager::asInterface(binder);
+    if (interface == nullptr) {
+        ALOGE("getDeviceService(\"manager\") returns non service manager");
+        return nullptr;
+    }
+    return sp<ServiceManagerHostShim>::make(interface);
+}
+#endif
+
 } // namespace android
diff --git a/libs/binder/ServiceManagerHost.cpp b/libs/binder/ServiceManagerHost.cpp
new file mode 100644
index 0000000..07f5778
--- /dev/null
+++ b/libs/binder/ServiceManagerHost.cpp
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2021 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 "ServiceManagerHost.h"
+
+#include <android-base/parseint.h>
+#include <android-base/strings.h>
+#include <binder/IServiceManager.h>
+#include <binder/RpcSession.h>
+
+#include "UtilsHost.h"
+
+namespace android {
+
+namespace {
+
+const void* kDeviceServiceExtraId = "DeviceServiceExtra";
+
+// Parse stdout of program execution to string. If any error, return 0.
+unsigned int parsePortNumber(const std::string& out, const std::string& what) {
+    auto trimmed = android::base::Trim(out);
+    unsigned int port = 0;
+    if (!android::base::ParseUint(trimmed, &port)) {
+        int savedErrno = errno;
+        ALOGE("%s is not a valid %s: %s", trimmed.c_str(), what.c_str(), strerror(savedErrno));
+        return 0;
+    }
+    if (port == 0) {
+        ALOGE("0 is not a valid %s", what.c_str());
+        return 0; // explicitly
+    }
+    return port;
+}
+
+// RAII object for adb forwarding
+class AdbForwarder {
+public:
+    AdbForwarder() = default;
+    static std::optional<AdbForwarder> forward(unsigned int devicePort);
+    AdbForwarder(AdbForwarder&& other) noexcept { (*this) = std::move(other); }
+    AdbForwarder& operator=(AdbForwarder&&) noexcept;
+    ~AdbForwarder();
+    [[nodiscard]] const std::optional<unsigned int>& hostPort() const { return mPort; }
+
+private:
+    DISALLOW_COPY_AND_ASSIGN(AdbForwarder);
+    explicit AdbForwarder(unsigned int port) : mPort(port) {}
+    std::optional<unsigned int> mPort;
+};
+std::optional<AdbForwarder> AdbForwarder::forward(unsigned int devicePort) {
+    auto result =
+            execute({"adb", "forward", "tcp:0", "tcp:" + std::to_string(devicePort)}, nullptr);
+    if (!result.ok()) {
+        ALOGE("Unable to run `adb forward tcp:0 tcp:%d`: %s", devicePort,
+              result.error().message().c_str());
+        return std::nullopt;
+    }
+    // Must end with exit code 0 (`has_value() && value() == 0`)
+    if (result->exitCode.value_or(1) != 0) {
+        ALOGE("Unable to run `adb forward tcp:0 tcp:%d`, command exits with %s", devicePort,
+              result->toString().c_str());
+        return std::nullopt;
+    }
+    if (!result->stderr.empty()) {
+        LOG_HOST("`adb forward tcp:0 tcp:%d` writes to stderr: %s", devicePort,
+                 result->stderr.c_str());
+    }
+
+    unsigned int hostPort = parsePortNumber(result->stdout, "host port");
+    if (hostPort == 0) return std::nullopt;
+
+    return AdbForwarder(hostPort);
+}
+
+AdbForwarder& AdbForwarder::operator=(AdbForwarder&& other) noexcept {
+    std::swap(mPort, other.mPort);
+    return *this;
+}
+
+AdbForwarder::~AdbForwarder() {
+    if (!mPort.has_value()) return;
+
+    auto result = execute({"adb", "forward", "--remove", "tcp:" + std::to_string(*mPort)}, nullptr);
+    if (!result.ok()) {
+        ALOGE("Unable to run `adb forward --remove tcp:%d`: %s", *mPort,
+              result.error().message().c_str());
+        return;
+    }
+    // Must end with exit code 0 (`has_value() && value() == 0`)
+    if (result->exitCode.value_or(1) != 0) {
+        ALOGE("Unable to run `adb forward --remove tcp:%d`, command exits with %s", *mPort,
+              result->toString().c_str());
+        return;
+    }
+    if (!result->stderr.empty()) {
+        LOG_HOST("`adb forward --remove tcp:%d` writes to stderr: %s", *mPort,
+                 result->stderr.c_str());
+    }
+
+    LOG_HOST("Successfully run `adb forward --remove tcp:%d`", *mPort);
+}
+
+void cleanupCommandResult(const void* id, void* obj, void* /* cookie */) {
+    LOG_ALWAYS_FATAL_IF(id != kDeviceServiceExtraId,
+                        "cleanupCommandResult invoked with mismatched ID %p, "
+                        "expected %p",
+                        id, kDeviceServiceExtraId);
+    auto ptr = static_cast<CommandResult*>(obj);
+    delete ptr;
+}
+
+} // namespace
+
+sp<IBinder> getDeviceService(std::vector<std::string>&& serviceDispatcherArgs) {
+    std::vector<std::string> prefix{"adb", "shell", "servicedispatcher"};
+    serviceDispatcherArgs.insert(serviceDispatcherArgs.begin(), prefix.begin(), prefix.end());
+
+    auto result = execute(std::move(serviceDispatcherArgs), &CommandResult::stdoutEndsWithNewLine);
+    if (!result.ok()) {
+        ALOGE("%s", result.error().message().c_str());
+        return nullptr;
+    }
+
+    // `servicedispatcher` process must be alive to keep the port open.
+    if (result->exitCode.has_value()) {
+        ALOGE("Command exits with: %s", result->toString().c_str());
+        return nullptr;
+    }
+    if (!result->stderr.empty()) {
+        LOG_HOST("servicedispatcher writes to stderr: %s", result->stderr.c_str());
+    }
+
+    if (!result->stdoutEndsWithNewLine()) {
+        ALOGE("Unexpected command result: %s", result->toString().c_str());
+        return nullptr;
+    }
+
+    unsigned int devicePort = parsePortNumber(result->stdout, "device port");
+    if (devicePort == 0) return nullptr;
+
+    auto forwardResult = AdbForwarder::forward(devicePort);
+    if (!forwardResult.has_value()) {
+        return nullptr;
+    }
+    LOG_ALWAYS_FATAL_IF(!forwardResult->hostPort().has_value());
+
+    auto rpcSession = RpcSession::make();
+    if (!rpcSession->setupInetClient("127.0.0.1", *forwardResult->hostPort())) {
+        ALOGE("Unable to set up inet client on host port %u", *forwardResult->hostPort());
+        return nullptr;
+    }
+    auto binder = rpcSession->getRootObject();
+    if (binder == nullptr) {
+        ALOGE("RpcSession::getRootObject returns nullptr");
+        return nullptr;
+    }
+    binder->attachObject(kDeviceServiceExtraId,
+                         static_cast<void*>(new CommandResult(std::move(*result))), nullptr,
+                         &cleanupCommandResult);
+    return binder;
+}
+
+} // namespace android
diff --git a/libs/binder/ServiceManagerHost.h b/libs/binder/ServiceManagerHost.h
new file mode 100644
index 0000000..e59724c
--- /dev/null
+++ b/libs/binder/ServiceManagerHost.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#pragma once
+
+#include <android-base/macros.h>
+#include <android/os/IServiceManager.h>
+
+namespace android {
+
+// Get a service on device by running servicedispatcher with the given args, e.g.
+//     getDeviceService({"foo"});
+// Return nullptr on any error.
+// When the returned binder object is destroyed, remove adb forwarding and kills
+// the long-running servicedispatcher process.
+sp<IBinder> getDeviceService(std::vector<std::string>&& serviceDispatcherArgs);
+
+} // namespace android
diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
index 3dbe2c4..8e46147 100644
--- a/libs/binder/include/binder/IServiceManager.h
+++ b/libs/binder/include/binder/IServiceManager.h
@@ -169,4 +169,17 @@
                             int32_t* outPid, int32_t* outUid);
 bool checkPermission(const String16& permission, pid_t pid, uid_t uid);
 
+#ifndef __ANDROID__
+// Create an IServiceManager that delegates the service manager on the device via adb.
+// This is can be set as the default service manager at program start, so that
+// defaultServiceManager() returns it:
+//    int main() {
+//        setDefaultServiceManager(createRpcDelegateServiceManager());
+//        auto sm = defaultServiceManager();
+//        // ...
+//    }
+// Resources are cleaned up when the object is destroyed.
+sp<IServiceManager> createRpcDelegateServiceManager();
+#endif
+
 } // namespace android