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

Commit 31f1a2ad authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Add servicedispatcher" am: 08d2f47d am: f63d6a3e

Original change: https://android-review.googlesource.com/c/platform/frameworks/native/+/1727279

Change-Id: I60b4d84622d01e2e8ad158bb85a121fbd9b3a321
parents e8df4488 f63d6a3e
Loading
Loading
Loading
Loading
+14 −0
Original line number Original line Diff line number Diff line
@@ -306,3 +306,17 @@ cc_library {
        export_aidl_headers: true,
        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 Original line 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);
}