/* * 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 "service_list.h" #include namespace android { namespace init { ServiceList::ServiceList() {} ServiceList& ServiceList::GetInstance() { static ServiceList instance; return instance; } size_t ServiceList::CheckAllCommands() { size_t failures = 0; for (const auto& service : services_) { failures += service->CheckAllCommands(); } return failures; } void ServiceList::AddService(std::unique_ptr service) { services_.emplace_back(std::move(service)); } // Shutdown services in the opposite order that they were started. const std::vector ServiceList::services_in_shutdown_order() const { std::vector shutdown_services; for (const auto& service : services_) { if (service->start_order() > 0) shutdown_services.emplace_back(service.get()); } std::sort(shutdown_services.begin(), shutdown_services.end(), [](const auto& a, const auto& b) { return a->start_order() > b->start_order(); }); return shutdown_services; } void ServiceList::RemoveService(const Service& svc) { auto svc_it = std::find_if( services_.begin(), services_.end(), [&svc](const std::unique_ptr& s) { return svc.name() == s->name(); }); if (svc_it == services_.end()) { return; } services_.erase(svc_it); } void ServiceList::DumpState() const { for (const auto& s : services_) { s->DumpState(); } } void ServiceList::MarkPostData() { post_data_ = true; } bool ServiceList::IsPostData() { return post_data_; } void ServiceList::MarkServicesUpdate() { services_update_finished_ = true; // start the delayed services for (const auto& name : delayed_service_names_) { Service* service = FindService(name); if (service == nullptr) { LOG(ERROR) << "delayed service '" << name << "' could not be found."; continue; } if (auto result = service->Start(); !result.ok()) { LOG(ERROR) << result.error().message(); } } delayed_service_names_.clear(); } void ServiceList::DelayService(const Service& service) { if (services_update_finished_) { LOG(ERROR) << "Cannot delay the start of service '" << service.name() << "' because all services are already updated. Ignoring."; return; } delayed_service_names_.emplace_back(service.name()); } } // namespace init } // namespace android