Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 08d2f47d authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Add servicedispatcher"

parents 85ec1f65 dbf58d47
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -309,3 +309,17 @@ cc_library {
        export_aidl_headers: true,
    },
}

cc_binary {
    name: "servicedispatcher",
    host_supported: false,
    srcs: [
        "servicedispatcher.cpp",
    ],
    shared_libs: [
        "libbase",
        "libbinder",
        "liblog",
        "libutils",
    ],
}
+138 −0
Original line number Diff line number Diff line
/*
 * 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 <stdint.h>
#include <sysexits.h>
#include <unistd.h>

#include <iostream>

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <binder/IServiceManager.h>
#include <binder/RpcServer.h>

using android::defaultServiceManager;
using android::OK;
using android::RpcServer;
using android::statusToString;
using android::String16;
using android::base::Basename;
using android::base::GetBoolProperty;
using android::base::InitLogging;
using android::base::LogdLogger;
using android::base::LogId;
using android::base::LogSeverity;
using android::base::ParseUint;
using android::base::StdioLogger;
using android::base::StringPrintf;

namespace {
int Usage(const char* program) {
    auto format = R"(dispatch calls to RPC service.
Usage:
  %s [-n <num_threads>] <service_name>
    -n <num_threads>: number of RPC threads added to the service (default 1).
    <service_name>: the service to connect to.
)";
    LOG(ERROR) << StringPrintf(format, Basename(program).c_str());
    return EX_USAGE;
}

int Dispatch(const char* name, uint32_t numThreads) {
    auto sm = defaultServiceManager();
    if (nullptr == sm) {
        LOG(ERROR) << "No servicemanager";
        return EX_SOFTWARE;
    }
    auto binder = sm->checkService(String16(name));
    if (nullptr == binder) {
        LOG(ERROR) << "No service \"" << name << "\"";
        return EX_SOFTWARE;
    }
    auto rpcServer = RpcServer::make();
    if (nullptr == rpcServer) {
        LOG(ERROR) << "Cannot create RpcServer";
        return EX_SOFTWARE;
    }
    rpcServer->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
    unsigned int port;
    if (!rpcServer->setupInetServer(0, &port)) {
        LOG(ERROR) << "setupInetServer failed";
        return EX_SOFTWARE;
    }
    auto socket = rpcServer->releaseServer();
    auto status = binder->setRpcClientDebug(std::move(socket), numThreads);
    if (status != OK) {
        LOG(ERROR) << "setRpcClientDebug failed with " << statusToString(status);
        return EX_SOFTWARE;
    }
    LOG(INFO) << "Finish setting up RPC on service " << name << " with " << numThreads
              << " threads on port" << port;

    std::cout << port << std::endl;
    return EX_OK;
}

// Log to logd. For warning and more severe messages, also log to stderr.
class ServiceDispatcherLogger {
public:
    void operator()(LogId id, LogSeverity severity, const char* tag, const char* file,
                    unsigned int line, const char* message) {
        mLogdLogger(id, severity, tag, file, line, message);
        if (severity >= LogSeverity::WARNING) {
            std::cout << std::flush;
            std::cerr << Basename(getprogname()) << ": " << message << std::endl;
        }
    }

private:
    LogdLogger mLogdLogger{};
};

} // namespace

int main(int argc, char* argv[]) {
    InitLogging(argv, ServiceDispatcherLogger());

    if (!GetBoolProperty("ro.debuggable", false)) {
        LOG(ERROR) << "servicedispatcher is only allowed on debuggable builds.";
        return EX_NOPERM;
    }
    LOG(WARNING) << "WARNING: servicedispatcher is debug only. Use with caution.";

    uint32_t numThreads = 1;
    int opt;
    while (-1 != (opt = getopt(argc, argv, "n:"))) {
        switch (opt) {
            case 'n': {
                if (!ParseUint(optarg, &numThreads)) {
                    return Usage(argv[0]);
                }
            } break;
            default: {
                return Usage(argv[0]);
            }
        }
    }
    if (optind + 1 != argc) return Usage(argv[0]);
    auto name = argv[optind];

    return Dispatch(name, numThreads);
}