/* * Copyright (C) 2019 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 #include #include #include #include #include #include #include #include "Access.h" #include "ServiceManager.h" using ::android::Access; using ::android::IPCThreadState; using ::android::Looper; using ::android::LooperCallback; using ::android::ProcessState; using ::android::ServiceManager; using ::android::sp; using ::android::base::SetProperty; using ::android::os::IServiceManager; class BinderCallback : public LooperCallback { public: static sp setupTo(const sp& looper) { sp cb = sp::make(); int binder_fd = -1; IPCThreadState::self()->setupPolling(&binder_fd); LOG_ALWAYS_FATAL_IF(binder_fd < 0, "Failed to setupPolling: %d", binder_fd); int ret = looper->addFd(binder_fd, Looper::POLL_CALLBACK, Looper::EVENT_INPUT, cb, nullptr /*data*/); LOG_ALWAYS_FATAL_IF(ret != 1, "Failed to add binder FD to Looper"); return cb; } int handleEvent(int /* fd */, int /* events */, void* /* data */) override { IPCThreadState::self()->handlePolledCommands(); return 1; // Continue receiving callbacks. } }; // LooperCallback for IClientCallback class ClientCallbackCallback : public LooperCallback { public: static sp setupTo(const sp& looper, const sp& manager) { sp cb = sp::make(manager); int fdTimer = timerfd_create(CLOCK_MONOTONIC, 0 /*flags*/); LOG_ALWAYS_FATAL_IF(fdTimer < 0, "Failed to timerfd_create: fd: %d err: %d", fdTimer, errno); itimerspec timespec { .it_interval = { .tv_sec = 5, .tv_nsec = 0, }, .it_value = { .tv_sec = 5, .tv_nsec = 0, }, }; int timeRes = timerfd_settime(fdTimer, 0 /*flags*/, ×pec, nullptr); LOG_ALWAYS_FATAL_IF(timeRes < 0, "Failed to timerfd_settime: res: %d err: %d", timeRes, errno); int addRes = looper->addFd(fdTimer, Looper::POLL_CALLBACK, Looper::EVENT_INPUT, cb, nullptr); LOG_ALWAYS_FATAL_IF(addRes != 1, "Failed to add client callback FD to Looper"); return cb; } int handleEvent(int fd, int /*events*/, void* /*data*/) override { uint64_t expirations; int ret = read(fd, &expirations, sizeof(expirations)); if (ret != sizeof(expirations)) { ALOGE("Read failed to callback FD: ret: %d err: %d", ret, errno); } mManager->handleClientCallbacks(); return 1; // Continue receiving callbacks. } private: friend sp; ClientCallbackCallback(const sp& manager) : mManager(manager) {} sp mManager; }; int main(int argc, char** argv) { android::base::InitLogging(argv, android::base::KernelLogger); if (argc > 2) { LOG(FATAL) << "usage: " << argv[0] << " [binder driver]"; } const char* driver = argc == 2 ? argv[1] : "/dev/binder"; LOG(INFO) << "Starting sm instance on " << driver; sp ps = ProcessState::initWithDriver(driver); ps->setThreadPoolMaxThreadCount(0); ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY); sp manager = sp::make(std::make_unique()); if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) { LOG(ERROR) << "Could not self register servicemanager"; } IPCThreadState::self()->setTheContextObject(manager); ps->becomeContextManager(); sp looper = Looper::prepare(false /*allowNonCallbacks*/); BinderCallback::setupTo(looper); ClientCallbackCallback::setupTo(looper, manager); #ifndef VENDORSERVICEMANAGER if (!SetProperty("servicemanager.ready", "true")) { LOG(ERROR) << "Failed to set servicemanager ready property"; } #endif while(true) { looper->pollAll(-1); } // should not be reached return EXIT_FAILURE; }