1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "service_list.h"
18 
19 #include <android-base/logging.h>
20 
21 namespace android {
22 namespace init {
23 
ServiceList()24 ServiceList::ServiceList() {}
25 
GetInstance()26 ServiceList& ServiceList::GetInstance() {
27     static ServiceList instance;
28     return instance;
29 }
30 
CheckAllCommands()31 size_t ServiceList::CheckAllCommands() {
32     size_t failures = 0;
33     for (const auto& service : services_) {
34         failures += service->CheckAllCommands();
35     }
36     return failures;
37 }
38 
AddService(std::unique_ptr<Service> service)39 void ServiceList::AddService(std::unique_ptr<Service> service) {
40     services_.emplace_back(std::move(service));
41 }
42 
43 // Shutdown services in the opposite order that they were started.
services_in_shutdown_order() const44 const std::vector<Service*> ServiceList::services_in_shutdown_order() const {
45     std::vector<Service*> shutdown_services;
46     for (const auto& service : services_) {
47         if (service->start_order() > 0) shutdown_services.emplace_back(service.get());
48     }
49     std::sort(shutdown_services.begin(), shutdown_services.end(),
50               [](const auto& a, const auto& b) { return a->start_order() > b->start_order(); });
51     return shutdown_services;
52 }
53 
RemoveService(const Service & svc)54 void ServiceList::RemoveService(const Service& svc) {
55     auto svc_it = std::find_if(
56             services_.begin(), services_.end(),
57             [&svc](const std::unique_ptr<Service>& s) { return svc.name() == s->name(); });
58     if (svc_it == services_.end()) {
59         return;
60     }
61 
62     services_.erase(svc_it);
63 }
64 
DumpState() const65 void ServiceList::DumpState() const {
66     for (const auto& s : services_) {
67         s->DumpState();
68     }
69 }
70 
MarkPostData()71 void ServiceList::MarkPostData() {
72     post_data_ = true;
73 }
74 
IsPostData()75 bool ServiceList::IsPostData() {
76     return post_data_;
77 }
78 
MarkServicesUpdate()79 void ServiceList::MarkServicesUpdate() {
80     services_update_finished_ = true;
81 
82     // start the delayed services
83     for (const auto& name : delayed_service_names_) {
84         Service* service = FindService(name);
85         if (service == nullptr) {
86             LOG(ERROR) << "delayed service '" << name << "' could not be found.";
87             continue;
88         }
89         if (auto result = service->Start(); !result.ok()) {
90             LOG(ERROR) << result.error().message();
91         }
92     }
93     delayed_service_names_.clear();
94 }
95 
DelayService(const Service & service)96 void ServiceList::DelayService(const Service& service) {
97     if (services_update_finished_) {
98         LOG(ERROR) << "Cannot delay the start of service '" << service.name()
99                    << "' because all services are already updated. Ignoring.";
100         return;
101     }
102     delayed_service_names_.emplace_back(service.name());
103 }
104 
105 }  // namespace init
106 }  // namespace android
107