/*
 * Copyright (C) 2005 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 <sys/socket.h>
#define LOG_TAG "ServiceManagerCppClient"

#include <binder/IServiceManager.h>
#include <binder/IServiceManagerUnitTestHelper.h>
#include "BackendUnifiedServiceManager.h"

#include <inttypes.h>
#include <unistd.h>
#include <chrono>
#include <condition_variable>

#include <FdTrigger.h>
#include <RpcSocketAddress.h>
#include <android-base/properties.h>
#include <android/os/BnAccessor.h>
#include <android/os/BnServiceCallback.h>
#include <android/os/BnServiceManager.h>
#include <android/os/IAccessor.h>
#include <android/os/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
#include <binder/RpcSession.h>
#include <utils/String8.h>
#include <variant>
#ifndef __ANDROID_VNDK__
#include <binder/IPermissionController.h>
#endif

#ifdef __ANDROID__
#include <cutils/properties.h>
#else
#include "ServiceManagerHost.h"
#endif

#if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__) && !defined(__ANDROID_NATIVE_BRIDGE__)
#include <android/apexsupport.h>
#include <vndksupport/linker.h>
#endif

#include "Static.h"
#include "Utils.h"

namespace android {

using namespace std::chrono_literals;

using AidlRegistrationCallback = IServiceManager::LocalRegistrationCallback;

using AidlServiceManager = android::os::IServiceManager;
using android::binder::Status;
using android::os::IAccessor;
using android::os::Service;

// libbinder's IServiceManager.h can't rely on the values generated by AIDL
// because many places use its headers via include_dirs (meaning, without
// declaring the dependency in the build system). So, for now, we can just check
// the values here.
static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_CRITICAL == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);
static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_HIGH == IServiceManager::DUMP_FLAG_PRIORITY_HIGH);
static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_NORMAL == IServiceManager::DUMP_FLAG_PRIORITY_NORMAL);
static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_DEFAULT == IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);
static_assert(AidlServiceManager::DUMP_FLAG_PRIORITY_ALL == IServiceManager::DUMP_FLAG_PRIORITY_ALL);
static_assert(AidlServiceManager::DUMP_FLAG_PROTO == IServiceManager::DUMP_FLAG_PROTO);

const String16& IServiceManager::getInterfaceDescriptor() const {
    return AidlServiceManager::descriptor;
}
IServiceManager::IServiceManager() {}
IServiceManager::~IServiceManager() {}

// From the old libbinder IServiceManager interface to IServiceManager.
class CppBackendShim : public IServiceManager {
public:
    explicit CppBackendShim(const sp<BackendUnifiedServiceManager>& impl);

    sp<IBinder> getService(const String16& name) const override;
    sp<IBinder> checkService(const String16& name) const override;
    status_t addService(const String16& name, const sp<IBinder>& service,
                        bool allowIsolated, int dumpsysPriority) override;
    Vector<String16> listServices(int dumpsysPriority) override;
    sp<IBinder> waitForService(const String16& name16) override;
    bool isDeclared(const String16& name) override;
    Vector<String16> getDeclaredInstances(const String16& interface) override;
    std::optional<String16> updatableViaApex(const String16& name) override;
    Vector<String16> getUpdatableNames(const String16& apexName) override;
    std::optional<IServiceManager::ConnectionInfo> getConnectionInfo(const String16& name) override;
    class RegistrationWaiter : public android::os::BnServiceCallback {
    public:
        explicit RegistrationWaiter(const sp<AidlRegistrationCallback>& callback)
              : mImpl(callback) {}
        Status onRegistration(const std::string& name, const sp<IBinder>& binder) override {
            mImpl->onServiceRegistration(String16(name.c_str()), binder);
            return Status::ok();
        }

    private:
        sp<AidlRegistrationCallback> mImpl;
    };

    status_t registerForNotifications(const String16& service,
                                      const sp<AidlRegistrationCallback>& cb) override;

    status_t unregisterForNotifications(const String16& service,
                                        const sp<AidlRegistrationCallback>& cb) override;

    std::vector<IServiceManager::ServiceDebugInfo> getServiceDebugInfo() override;
    // for legacy ABI
    const String16& getInterfaceDescriptor() const override {
        return mUnifiedServiceManager->getInterfaceDescriptor();
    }
    IBinder* onAsBinder() override { return IInterface::asBinder(mUnifiedServiceManager).get(); }

protected:
    sp<BackendUnifiedServiceManager> mUnifiedServiceManager;
    // AidlRegistrationCallback -> services that its been registered for
    // notifications.
    using LocalRegistrationAndWaiter =
            std::pair<sp<LocalRegistrationCallback>, sp<RegistrationWaiter>>;
    using ServiceCallbackMap = std::map<std::string, std::vector<LocalRegistrationAndWaiter>>;
    ServiceCallbackMap mNameToRegistrationCallback;
    std::mutex mNameToRegistrationLock;

    void removeRegistrationCallbackLocked(const sp<AidlRegistrationCallback>& cb,
                                          ServiceCallbackMap::iterator* it,
                                          sp<RegistrationWaiter>* waiter);

    // 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 CppBackendShim::getService
    // will still have the 5s delay that is expected by a large amount of Android code.
    //
    // When implementing CppBackendShim, use realGetService instead of
    // mUnifiedServiceManager->getService so that it can be overridden in CppServiceManagerHostShim.
    virtual Status realGetService(const std::string& name, sp<IBinder>* _aidl_return) {
        Service service;
        Status status = mUnifiedServiceManager->getService2(name, &service);
        *_aidl_return = service.get<Service::Tag::binder>();
        return status;
    }
};

class AccessorProvider {
public:
    AccessorProvider(std::set<std::string>&& instances, RpcAccessorProvider&& provider)
          : mInstances(std::move(instances)), mProvider(std::move(provider)) {}
    sp<IBinder> provide(const String16& name) {
        if (mInstances.count(String8(name).c_str()) > 0) {
            return mProvider(name);
        } else {
            return nullptr;
        }
    }
    const std::set<std::string>& instances() { return mInstances; }

private:
    AccessorProvider() = delete;

    std::set<std::string> mInstances;
    RpcAccessorProvider mProvider;
};

class AccessorProviderEntry {
public:
    AccessorProviderEntry(std::shared_ptr<AccessorProvider>&& provider)
          : mProvider(std::move(provider)) {}
    std::shared_ptr<AccessorProvider> mProvider;

private:
    AccessorProviderEntry() = delete;
};

[[clang::no_destroy]] static std::once_flag gSmOnce;
[[clang::no_destroy]] static sp<IServiceManager> gDefaultServiceManager;
[[clang::no_destroy]] static std::mutex gAccessorProvidersMutex;
[[clang::no_destroy]] static std::vector<AccessorProviderEntry> gAccessorProviders;

class LocalAccessor : public android::os::BnAccessor {
public:
    LocalAccessor(const String16& instance, RpcSocketAddressProvider&& connectionInfoProvider)
          : mInstance(instance), mConnectionInfoProvider(std::move(connectionInfoProvider)) {
        LOG_ALWAYS_FATAL_IF(!mConnectionInfoProvider,
                            "LocalAccessor object needs a valid connection info provider");
    }

    ~LocalAccessor() {
        if (mOnDelete) mOnDelete();
    }

    ::android::binder::Status addConnection(::android::os::ParcelFileDescriptor* outFd) {
        using android::os::IAccessor;
        sockaddr_storage addrStorage;
        std::unique_ptr<FdTrigger> trigger = FdTrigger::make();
        RpcTransportFd fd;
        status_t status =
                mConnectionInfoProvider(mInstance, reinterpret_cast<sockaddr*>(&addrStorage),
                                        sizeof(addrStorage));
        if (status != OK) {
            const std::string error = "The connection info provider was unable to provide "
                                      "connection info for instance " +
                    std::string(String8(mInstance).c_str()) +
                    " with status: " + statusToString(status);
            ALOGE("%s", error.c_str());
            return Status::fromServiceSpecificError(IAccessor::ERROR_CONNECTION_INFO_NOT_FOUND,
                                                    error.c_str());
        }
        if (addrStorage.ss_family == AF_VSOCK) {
            sockaddr_vm* addr = reinterpret_cast<sockaddr_vm*>(&addrStorage);
            status = singleSocketConnection(VsockSocketAddress(addr->svm_cid, addr->svm_port),
                                            trigger, &fd);
        } else if (addrStorage.ss_family == AF_UNIX) {
            sockaddr_un* addr = reinterpret_cast<sockaddr_un*>(&addrStorage);
            status = singleSocketConnection(UnixSocketAddress(addr->sun_path), trigger, &fd);
        } else if (addrStorage.ss_family == AF_INET) {
            sockaddr_in* addr = reinterpret_cast<sockaddr_in*>(&addrStorage);
            status = singleSocketConnection(InetSocketAddress(reinterpret_cast<sockaddr*>(addr),
                                                              sizeof(sockaddr_in),
                                                              inet_ntoa(addr->sin_addr),
                                                              ntohs(addr->sin_port)),
                                            trigger, &fd);
        } else {
            const std::string error =
                    "Unsupported socket family type or the ConnectionInfoProvider failed to find a "
                    "valid address. Family type: " +
                    std::to_string(addrStorage.ss_family);
            ALOGE("%s", error.c_str());
            return Status::fromServiceSpecificError(IAccessor::ERROR_UNSUPPORTED_SOCKET_FAMILY,
                                                    error.c_str());
        }
        if (status != OK) {
            const std::string error = "Failed to connect to socket for " +
                    std::string(String8(mInstance).c_str()) +
                    " with status: " + statusToString(status);
            ALOGE("%s", error.c_str());
            int err = 0;
            if (status == -EACCES) {
                err = IAccessor::ERROR_FAILED_TO_CONNECT_EACCES;
            } else {
                err = IAccessor::ERROR_FAILED_TO_CONNECT_TO_SOCKET;
            }
            return Status::fromServiceSpecificError(err, error.c_str());
        }
        *outFd = os::ParcelFileDescriptor(std::move(fd.fd));
        return Status::ok();
    }

    ::android::binder::Status getInstanceName(String16* instance) {
        *instance = mInstance;
        return Status::ok();
    }

private:
    LocalAccessor() = delete;
    String16 mInstance;
    RpcSocketAddressProvider mConnectionInfoProvider;
    std::function<void()> mOnDelete;
};

android::binder::Status getInjectedAccessor(const std::string& name,
                                            android::os::Service* service) {
    std::vector<AccessorProviderEntry> copiedProviders;
    {
        std::lock_guard<std::mutex> lock(gAccessorProvidersMutex);
        copiedProviders.insert(copiedProviders.begin(), gAccessorProviders.begin(),
                               gAccessorProviders.end());
    }

    // Unlocked to call the providers. This requires the providers to be
    // threadsafe and not contain any references to objects that could be
    // deleted.
    for (const auto& provider : copiedProviders) {
        sp<IBinder> binder = provider.mProvider->provide(String16(name.c_str()));
        if (binder == nullptr) continue;
        status_t status = validateAccessor(String16(name.c_str()), binder);
        if (status != OK) {
            ALOGE("A provider returned a binder that is not an IAccessor for instance %s. Status: "
                  "%s",
                  name.c_str(), statusToString(status).c_str());
            return android::binder::Status::fromStatusT(android::INVALID_OPERATION);
        }
        *service = os::Service::make<os::Service::Tag::accessor>(binder);
        return android::binder::Status::ok();
    }

    *service = os::Service::make<os::Service::Tag::accessor>(nullptr);
    return android::binder::Status::ok();
}

sp<IServiceManager> defaultServiceManager()
{
    std::call_once(gSmOnce, []() {
        gDefaultServiceManager = sp<CppBackendShim>::make(getBackendUnifiedServiceManager());
    });

    return gDefaultServiceManager;
}

void setDefaultServiceManager(const sp<IServiceManager>& sm) {
    bool called = false;
    std::call_once(gSmOnce, [&]() {
        gDefaultServiceManager = sm;
        called = true;
    });

    if (!called) {
        LOG_ALWAYS_FATAL("setDefaultServiceManager() called after defaultServiceManager().");
    }
}

sp<IServiceManager> getServiceManagerShimFromAidlServiceManagerForTests(
        const sp<AidlServiceManager>& sm) {
    return sp<CppBackendShim>::make(sp<BackendUnifiedServiceManager>::make(sm));
}

// gAccessorProvidersMutex must be locked already
static bool isInstanceProvidedLocked(const std::string& instance) {
    return gAccessorProviders.end() !=
            std::find_if(gAccessorProviders.begin(), gAccessorProviders.end(),
                         [&instance](const AccessorProviderEntry& entry) {
                             return entry.mProvider->instances().count(instance) > 0;
                         });
}

std::weak_ptr<AccessorProvider> addAccessorProvider(std::set<std::string>&& instances,
                                                    RpcAccessorProvider&& providerCallback) {
    if (instances.empty()) {
        ALOGE("Set of instances is empty! Need a non empty set of instances to provide for.");
        return std::weak_ptr<AccessorProvider>();
    }
    std::lock_guard<std::mutex> lock(gAccessorProvidersMutex);
    for (const auto& instance : instances) {
        if (isInstanceProvidedLocked(instance)) {
            ALOGE("The instance %s is already provided for by a previously added "
                  "RpcAccessorProvider.",
                  instance.c_str());
            return std::weak_ptr<AccessorProvider>();
        }
    }
    std::shared_ptr<AccessorProvider> provider =
            std::make_shared<AccessorProvider>(std::move(instances), std::move(providerCallback));
    std::weak_ptr<AccessorProvider> receipt = provider;
    gAccessorProviders.push_back(AccessorProviderEntry(std::move(provider)));

    return receipt;
}

status_t removeAccessorProvider(std::weak_ptr<AccessorProvider> wProvider) {
    std::shared_ptr<AccessorProvider> provider = wProvider.lock();
    if (provider == nullptr) {
        ALOGE("The provider supplied to removeAccessorProvider has already been removed or the "
              "argument to this function was nullptr.");
        return BAD_VALUE;
    }
    std::lock_guard<std::mutex> lock(gAccessorProvidersMutex);
    size_t sizeBefore = gAccessorProviders.size();
    gAccessorProviders.erase(std::remove_if(gAccessorProviders.begin(), gAccessorProviders.end(),
                                            [&](AccessorProviderEntry entry) {
                                                return entry.mProvider == provider;
                                            }),
                             gAccessorProviders.end());
    if (sizeBefore == gAccessorProviders.size()) {
        ALOGE("Failed to find an AccessorProvider for removeAccessorProvider");
        return NAME_NOT_FOUND;
    }

    return OK;
}

status_t validateAccessor(const String16& instance, const sp<IBinder>& binder) {
    if (binder == nullptr) {
        ALOGE("Binder is null");
        return BAD_VALUE;
    }
    sp<IAccessor> accessor = checked_interface_cast<IAccessor>(binder);
    if (accessor == nullptr) {
        ALOGE("This binder for %s is not an IAccessor binder", String8(instance).c_str());
        return BAD_TYPE;
    }
    String16 reportedInstance;
    Status status = accessor->getInstanceName(&reportedInstance);
    if (!status.isOk()) {
        ALOGE("Failed to validate the binder being used to create a new ARpc_Accessor for %s with "
              "status: %s",
              String8(instance).c_str(), status.toString8().c_str());
        return NAME_NOT_FOUND;
    }
    if (reportedInstance != instance) {
        ALOGE("Instance %s doesn't match the Accessor's instance of %s", String8(instance).c_str(),
              String8(reportedInstance).c_str());
        return NAME_NOT_FOUND;
    }
    return OK;
}

sp<IBinder> createAccessor(const String16& instance,
                           RpcSocketAddressProvider&& connectionInfoProvider) {
    // Try to create a new accessor
    if (!connectionInfoProvider) {
        ALOGE("Could not find an Accessor for %s and no ConnectionInfoProvider provided to "
              "create a new one",
              String8(instance).c_str());
        return nullptr;
    }
    sp<IBinder> binder = sp<LocalAccessor>::make(instance, std::move(connectionInfoProvider));
    return binder;
}

status_t delegateAccessor(const String16& name, const sp<IBinder>& accessor,
                          sp<IBinder>* delegator) {
    LOG_ALWAYS_FATAL_IF(delegator == nullptr, "delegateAccessor called with a null out param");
    if (accessor == nullptr) {
        ALOGW("Accessor argument to delegateAccessor is null.");
        *delegator = nullptr;
        return OK;
    }
    status_t status = validateAccessor(name, accessor);
    if (status != OK) {
        ALOGE("The provided accessor binder is not an IAccessor for instance %s. Status: "
              "%s",
              String8(name).c_str(), statusToString(status).c_str());
        return status;
    }
    // validateAccessor already called checked_interface_cast and made sure this
    // is a valid accessor object.
    *delegator = sp<android::os::IAccessorDelegator>::make(interface_cast<IAccessor>(accessor));

    return OK;
}

#if !defined(__ANDROID_VNDK__)
// IPermissionController is not accessible to vendors

bool checkCallingPermission(const String16& permission)
{
    return checkCallingPermission(permission, nullptr, nullptr);
}

static StaticString16 _permission(u"permission");

bool checkCallingPermission(const String16& permission, int32_t* outPid, int32_t* outUid)
{
    IPCThreadState* ipcState = IPCThreadState::self();
    pid_t pid = ipcState->getCallingPid();
    uid_t uid = ipcState->getCallingUid();
    if (outPid) *outPid = pid;
    if (outUid) *outUid = uid;
    return checkPermission(permission, pid, uid);
}

bool checkPermission(const String16& permission, pid_t pid, uid_t uid, bool logPermissionFailure) {
    static std::mutex gPermissionControllerLock;
    static sp<IPermissionController> gPermissionController;

    sp<IPermissionController> pc;
    gPermissionControllerLock.lock();
    pc = gPermissionController;
    gPermissionControllerLock.unlock();

    auto startTime = std::chrono::steady_clock::now().min();

    while (true) {
        if (pc != nullptr) {
            bool res = pc->checkPermission(permission, pid, uid);
            if (res) {
                if (startTime != startTime.min()) {
                    const auto waitTime = std::chrono::steady_clock::now() - startTime;
                    ALOGI("Check passed after %" PRIu64 "ms for %s from uid=%d pid=%d",
                          to_ms(waitTime), String8(permission).c_str(), uid, pid);
                }
                return res;
            }

            // Is this a permission failure, or did the controller go away?
            if (IInterface::asBinder(pc)->isBinderAlive()) {
                if (logPermissionFailure) {
                    ALOGW("Permission failure: %s from uid=%d pid=%d", String8(permission).c_str(),
                          uid, pid);
                }
                return false;
            }

            // Object is dead!
            gPermissionControllerLock.lock();
            if (gPermissionController == pc) {
                gPermissionController = nullptr;
            }
            gPermissionControllerLock.unlock();
        }

        // Need to retrieve the permission controller.
        sp<IBinder> binder = defaultServiceManager()->checkService(_permission);
        if (binder == nullptr) {
            // Wait for the permission controller to come back...
            if (startTime == startTime.min()) {
                startTime = std::chrono::steady_clock::now();
                ALOGI("Waiting to check permission %s from uid=%d pid=%d",
                      String8(permission).c_str(), uid, pid);
            }
            sleep(1);
        } else {
            pc = interface_cast<IPermissionController>(binder);
            // Install the new permission controller, and try again.
            gPermissionControllerLock.lock();
            gPermissionController = pc;
            gPermissionControllerLock.unlock();
        }
    }
}

#endif //__ANDROID_VNDK__

void* openDeclaredPassthroughHal(const String16& interface, const String16& instance, int flag) {
#if defined(__ANDROID__) && !defined(__ANDROID_VENDOR__) && !defined(__ANDROID_RECOVERY__) && \
        !defined(__ANDROID_NATIVE_BRIDGE__)
    sp<IServiceManager> sm = defaultServiceManager();
    String16 name = interface + String16("/") + instance;
    if (!sm->isDeclared(name)) {
        return nullptr;
    }
    String16 libraryName = interface + String16(".") + instance + String16(".so");
    if (auto updatableViaApex = sm->updatableViaApex(name); updatableViaApex.has_value()) {
        return AApexSupport_loadLibrary(String8(libraryName).c_str(),
                                        String8(*updatableViaApex).c_str(), flag);
    }
    return android_load_sphal_library(String8(libraryName).c_str(), flag);
#else
    (void)interface;
    (void)instance;
    (void)flag;
    return nullptr;
#endif
}

// ----------------------------------------------------------------------

CppBackendShim::CppBackendShim(const sp<BackendUnifiedServiceManager>& impl)
      : mUnifiedServiceManager(impl) {}

// This implementation could be simplified and made more efficient by delegating
// to waitForService. However, this changes the threading structure in some
// cases and could potentially break prebuilts. Once we have higher logistical
// complexity, this could be attempted.
sp<IBinder> CppBackendShim::getService(const String16& name) const {
    static bool gSystemBootCompleted = false;

    sp<IBinder> svc = checkService(name);
    if (svc != nullptr) return svc;

    sp<ProcessState> self = ProcessState::selfOrNull();
    const bool isVendorService =
            self && strcmp(self->getDriverName().c_str(), "/dev/vndbinder") == 0;
    constexpr auto timeout = 5s;
    const auto startTime = std::chrono::steady_clock::now();
    // Vendor code can't access system properties
    if (!gSystemBootCompleted && !isVendorService) {
#ifdef __ANDROID__
        char bootCompleted[PROPERTY_VALUE_MAX];
        property_get("sys.boot_completed", bootCompleted, "0");
        gSystemBootCompleted = strcmp(bootCompleted, "1") == 0 ? true : false;
#else
        gSystemBootCompleted = true;
#endif
    }
    // retry interval in millisecond; note that vendor services stay at 100ms
    const useconds_t sleepTime = gSystemBootCompleted ? 1000 : 100;

    ALOGI("Waiting for service '%s' on '%s'...", String8(name).c_str(),
          self ? self->getDriverName().c_str() : "RPC accessors only");

    int n = 0;
    while (std::chrono::steady_clock::now() - startTime < timeout) {
        n++;
        usleep(1000*sleepTime);

        sp<IBinder> svc = checkService(name);
        if (svc != nullptr) {
            const auto waitTime = std::chrono::steady_clock::now() - startTime;
            ALOGI("Waiting for service '%s' on '%s' successful after waiting %" PRIu64 "ms",
                  String8(name).c_str(), ProcessState::self()->getDriverName().c_str(),
                  to_ms(waitTime));
            return svc;
        }
    }
    ALOGW("Service %s didn't start. Returning NULL", String8(name).c_str());
    return nullptr;
}

sp<IBinder> CppBackendShim::checkService(const String16& name) const {
    Service ret;
    if (!mUnifiedServiceManager->checkService(String8(name).c_str(), &ret).isOk()) {
        return nullptr;
    }
    return ret.get<Service::Tag::binder>();
}

status_t CppBackendShim::addService(const String16& name, const sp<IBinder>& service,
                                    bool allowIsolated, int dumpsysPriority) {
    Status status = mUnifiedServiceManager->addService(String8(name).c_str(), service,
                                                       allowIsolated, dumpsysPriority);
    return status.exceptionCode();
}

Vector<String16> CppBackendShim::listServices(int dumpsysPriority) {
    std::vector<std::string> ret;
    if (!mUnifiedServiceManager->listServices(dumpsysPriority, &ret).isOk()) {
        return {};
    }

    Vector<String16> res;
    res.setCapacity(ret.size());
    for (const std::string& name : ret) {
        res.push(String16(name.c_str()));
    }
    return res;
}

sp<IBinder> CppBackendShim::waitForService(const String16& name16) {
    class Waiter : public android::os::BnServiceCallback {
        Status onRegistration(const std::string& /*name*/,
                              const sp<IBinder>& binder) override {
            std::unique_lock<std::mutex> lock(mMutex);
            mBinder = binder;
            lock.unlock();
            // Flushing here helps ensure the service's ref count remains accurate
            IPCThreadState::self()->flushCommands();
            mCv.notify_one();
            return Status::ok();
        }
    public:
        sp<IBinder> mBinder;
        std::mutex mMutex;
        std::condition_variable mCv;
    };

    // Simple RAII object to ensure a function call immediately before going out of scope
    class Defer {
    public:
        explicit Defer(std::function<void()>&& f) : mF(std::move(f)) {}
        ~Defer() { mF(); }
    private:
        std::function<void()> mF;
    };

    const std::string name = String8(name16).c_str();

    sp<IBinder> out;
    if (Status status = realGetService(name, &out); !status.isOk()) {
        ALOGW("Failed to getService in waitForService for %s: %s", name.c_str(),
              status.toString8().c_str());
        sp<ProcessState> self = ProcessState::selfOrNull();
        if (self && 0 == self->getThreadPoolMaxTotalThreadCount()) {
            ALOGW("Got service, but may be racey because we could not wait efficiently for it. "
                  "Threadpool has 0 guaranteed threads. "
                  "Is the threadpool configured properly? "
                  "See ProcessState::startThreadPool and "
                  "ProcessState::setThreadPoolMaxThreadCount.");
        }
        return nullptr;
    }
    if (out != nullptr) return out;

    sp<Waiter> waiter = sp<Waiter>::make();
    if (Status status = mUnifiedServiceManager->registerForNotifications(name, waiter);
        !status.isOk()) {
        ALOGW("Failed to registerForNotifications in waitForService for %s: %s", name.c_str(),
              status.toString8().c_str());
        return nullptr;
    }
    Defer unregister([&] { mUnifiedServiceManager->unregisterForNotifications(name, waiter); });

    while(true) {
        {
            // It would be really nice if we could read binder commands on this
            // thread instead of needing a threadpool to be started, but for
            // instance, if we call getAndExecuteCommand, it might be the case
            // that another thread serves the callback, and we never get a
            // command, so we hang indefinitely.
            std::unique_lock<std::mutex> lock(waiter->mMutex);
            waiter->mCv.wait_for(lock, 1s, [&] {
                return waiter->mBinder != nullptr;
            });
            if (waiter->mBinder != nullptr) return waiter->mBinder;
        }

        sp<ProcessState> self = ProcessState::selfOrNull();
        ALOGW("Waited one second for %s (is service started? Number of threads started in the "
              "threadpool: %zu. Are binder threads started and available?)",
              name.c_str(), self ? self->getThreadPoolMaxTotalThreadCount() : 0);

        // Handle race condition for lazy services. Here is what can happen:
        // - the service dies (not processed by init yet).
        // - sm processes death notification.
        // - sm gets getService and calls init to start service.
        // - init gets the start signal, but the service already appears
        //   started, so it does nothing.
        // - 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 = 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;
        }
        if (out != nullptr) return out;
    }
}

bool CppBackendShim::isDeclared(const String16& name) {
    bool declared;
    if (Status status = mUnifiedServiceManager->isDeclared(String8(name).c_str(), &declared);
        !status.isOk()) {
        ALOGW("Failed to get isDeclared for %s: %s", String8(name).c_str(),
              status.toString8().c_str());
        return false;
    }
    return declared;
}

Vector<String16> CppBackendShim::getDeclaredInstances(const String16& interface) {
    std::vector<std::string> out;
    if (Status status =
                mUnifiedServiceManager->getDeclaredInstances(String8(interface).c_str(), &out);
        !status.isOk()) {
        ALOGW("Failed to getDeclaredInstances for %s: %s", String8(interface).c_str(),
              status.toString8().c_str());
        return {};
    }

    Vector<String16> res;
    res.setCapacity(out.size());
    for (const std::string& instance : out) {
        res.push(String16(instance.c_str()));
    }
    return res;
}

std::optional<String16> CppBackendShim::updatableViaApex(const String16& name) {
    std::optional<std::string> declared;
    if (Status status = mUnifiedServiceManager->updatableViaApex(String8(name).c_str(), &declared);
        !status.isOk()) {
        ALOGW("Failed to get updatableViaApex for %s: %s", String8(name).c_str(),
              status.toString8().c_str());
        return std::nullopt;
    }
    return declared ? std::optional<String16>(String16(declared.value().c_str())) : std::nullopt;
}

Vector<String16> CppBackendShim::getUpdatableNames(const String16& apexName) {
    std::vector<std::string> out;
    if (Status status = mUnifiedServiceManager->getUpdatableNames(String8(apexName).c_str(), &out);
        !status.isOk()) {
        ALOGW("Failed to getUpdatableNames for %s: %s", String8(apexName).c_str(),
              status.toString8().c_str());
        return {};
    }

    Vector<String16> res;
    res.setCapacity(out.size());
    for (const std::string& instance : out) {
        res.push(String16(instance.c_str()));
    }
    return res;
}

std::optional<IServiceManager::ConnectionInfo> CppBackendShim::getConnectionInfo(
        const String16& name) {
    std::optional<os::ConnectionInfo> connectionInfo;
    if (Status status =
                mUnifiedServiceManager->getConnectionInfo(String8(name).c_str(), &connectionInfo);
        !status.isOk()) {
        ALOGW("Failed to get ConnectionInfo for %s: %s", String8(name).c_str(),
              status.toString8().c_str());
    }
    return connectionInfo.has_value()
            ? std::make_optional<IServiceManager::ConnectionInfo>(
                      {connectionInfo->ipAddress, static_cast<unsigned int>(connectionInfo->port)})
            : std::nullopt;
}

status_t CppBackendShim::registerForNotifications(const String16& name,
                                                  const sp<AidlRegistrationCallback>& cb) {
    if (cb == nullptr) {
        ALOGE("%s: null cb passed", __FUNCTION__);
        return BAD_VALUE;
    }
    std::string nameStr = String8(name).c_str();
    sp<RegistrationWaiter> registrationWaiter = sp<RegistrationWaiter>::make(cb);
    std::lock_guard<std::mutex> lock(mNameToRegistrationLock);
    if (Status status =
                mUnifiedServiceManager->registerForNotifications(nameStr, registrationWaiter);
        !status.isOk()) {
        ALOGW("Failed to registerForNotifications for %s: %s", nameStr.c_str(),
              status.toString8().c_str());
        return UNKNOWN_ERROR;
    }
    mNameToRegistrationCallback[nameStr].push_back(std::make_pair(cb, registrationWaiter));
    return OK;
}

void CppBackendShim::removeRegistrationCallbackLocked(const sp<AidlRegistrationCallback>& cb,
                                                      ServiceCallbackMap::iterator* it,
                                                      sp<RegistrationWaiter>* waiter) {
    std::vector<LocalRegistrationAndWaiter>& localRegistrationAndWaiters = (*it)->second;
    for (auto lit = localRegistrationAndWaiters.begin();
         lit != localRegistrationAndWaiters.end();) {
        if (lit->first == cb) {
            if (waiter) {
                *waiter = lit->second;
            }
            lit = localRegistrationAndWaiters.erase(lit);
        } else {
            ++lit;
        }
    }

    if (localRegistrationAndWaiters.empty()) {
        mNameToRegistrationCallback.erase(*it);
    }
}

status_t CppBackendShim::unregisterForNotifications(const String16& name,
                                                    const sp<AidlRegistrationCallback>& cb) {
    if (cb == nullptr) {
        ALOGE("%s: null cb passed", __FUNCTION__);
        return BAD_VALUE;
    }
    std::string nameStr = String8(name).c_str();
    std::lock_guard<std::mutex> lock(mNameToRegistrationLock);
    auto it = mNameToRegistrationCallback.find(nameStr);
    sp<RegistrationWaiter> registrationWaiter;
    if (it != mNameToRegistrationCallback.end()) {
        removeRegistrationCallbackLocked(cb, &it, &registrationWaiter);
    } else {
        ALOGE("%s no callback registered for notifications on %s", __FUNCTION__, nameStr.c_str());
        return BAD_VALUE;
    }
    if (registrationWaiter == nullptr) {
        ALOGE("%s Callback passed wasn't used to register for notifications", __FUNCTION__);
        return BAD_VALUE;
    }
    if (Status status = mUnifiedServiceManager->unregisterForNotifications(String8(name).c_str(),
                                                                           registrationWaiter);
        !status.isOk()) {
        ALOGW("Failed to get service manager to unregisterForNotifications for %s: %s",
              String8(name).c_str(), status.toString8().c_str());
        return UNKNOWN_ERROR;
    }
    return OK;
}

std::vector<IServiceManager::ServiceDebugInfo> CppBackendShim::getServiceDebugInfo() {
    std::vector<os::ServiceDebugInfo> serviceDebugInfos;
    std::vector<IServiceManager::ServiceDebugInfo> ret;
    if (Status status = mUnifiedServiceManager->getServiceDebugInfo(&serviceDebugInfos);
        !status.isOk()) {
        ALOGW("%s Failed to get ServiceDebugInfo", __FUNCTION__);
        return ret;
    }
    for (const auto& serviceDebugInfo : serviceDebugInfos) {
        IServiceManager::ServiceDebugInfo retInfo;
        retInfo.pid = serviceDebugInfo.debugPid;
        retInfo.name = serviceDebugInfo.name;
        ret.emplace_back(retInfo);
    }
    return ret;
}

#ifndef __ANDROID__
// CppBackendShim 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 CppServiceManagerHostShim : public CppBackendShim {
public:
    CppServiceManagerHostShim(const sp<AidlServiceManager>& impl,
                              const RpcDelegateServiceManagerOptions& options)
          : CppBackendShim(sp<BackendUnifiedServiceManager>::make(impl)), mOptions(options) {}
    // CppBackendShim::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()}, mOptions);
    }

protected:
    // Override realGetService for CppBackendShim::waitForService.
    Status realGetService(const std::string& name, sp<IBinder>* _aidl_return) override {
        *_aidl_return = getDeviceService({"-g", name}, mOptions);
        return Status::ok();
    }

private:
    RpcDelegateServiceManagerOptions mOptions;
};
sp<IServiceManager> createRpcDelegateServiceManager(
        const RpcDelegateServiceManagerOptions& options) {
    auto binder = getDeviceService({"manager"}, options);
    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<CppServiceManagerHostShim>::make(interface, options);
}
#endif

} // namespace android
