blob: 08ed67625526285636c1b23a5e2ecd43a8e14426 [file] [log] [blame]
Peter Kalauskas3373cd32018-10-24 15:37:00 -07001/*
2 * Copyright (C) 2018 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 <hidl/HidlLazyUtils.h>
18#include <hidl/HidlTransportSupport.h>
19
20#include <android-base/logging.h>
21
22#include <android/hidl/manager/1.2/IClientCallback.h>
23#include <android/hidl/manager/1.2/IServiceManager.h>
24
25namespace android {
26namespace hardware {
27namespace details {
28
Steven Moreland40b3ab42019-01-25 13:23:20 -080029using ::android::hidl::base::V1_0::IBase;
30
Peter Kalauskas3373cd32018-10-24 15:37:00 -070031class ClientCounterCallback : public ::android::hidl::manager::V1_2::IClientCallback {
32 public:
Steven Moreland40b3ab42019-01-25 13:23:20 -080033 ClientCounterCallback() : mNumConnectedServices(0) {}
Peter Kalauskas3373cd32018-10-24 15:37:00 -070034
Steven Moreland40b3ab42019-01-25 13:23:20 -080035 bool addRegisteredService(const sp<IBase>& service, const std::string& name);
Peter Kalauskas3373cd32018-10-24 15:37:00 -070036
37 protected:
Steven Moreland40b3ab42019-01-25 13:23:20 -080038 Return<void> onClients(const sp<IBase>& service, bool clients) override;
Peter Kalauskas3373cd32018-10-24 15:37:00 -070039
40 private:
41 /**
Steven Moreland40b3ab42019-01-25 13:23:20 -080042 * Registers or re-registers services. Returns whether successful.
43 */
44 bool registerService(const sp<IBase>& service, const std::string& name);
45
46 /**
47 * Unregisters all services that we can. If we can't unregister all, re-register other
48 * services.
49 */
50 void tryShutdown();
51
52 /**
Peter Kalauskas3373cd32018-10-24 15:37:00 -070053 * Counter of the number of services that currently have at least one client.
54 */
55 size_t mNumConnectedServices;
56
Steven Moreland40b3ab42019-01-25 13:23:20 -080057 struct Service {
58 sp<IBase> service;
59 std::string name;
60 };
Peter Kalauskas3373cd32018-10-24 15:37:00 -070061 /**
62 * Number of services that have been registered.
63 */
Steven Moreland40b3ab42019-01-25 13:23:20 -080064 std::vector<Service> mRegisteredServices;
Peter Kalauskas3373cd32018-10-24 15:37:00 -070065};
66
67class LazyServiceRegistrarImpl {
68 public:
69 LazyServiceRegistrarImpl() : mClientCallback(new ClientCounterCallback) {}
70
Peter Kalauskas7ce31552019-01-03 15:15:46 -080071 status_t registerService(const sp<::android::hidl::base::V1_0::IBase>& service,
72 const std::string& name);
Peter Kalauskas3373cd32018-10-24 15:37:00 -070073
74 private:
75 sp<ClientCounterCallback> mClientCallback;
76};
77
Steven Moreland40b3ab42019-01-25 13:23:20 -080078bool ClientCounterCallback::addRegisteredService(const sp<IBase>& service,
79 const std::string& name) {
80 bool success = registerService(service, name);
81
82 if (success) {
83 mRegisteredServices.push_back({service, name});
84 }
85
86 return success;
87}
88
89bool ClientCounterCallback::registerService(const sp<IBase>& service, const std::string& name) {
90 auto manager = hardware::defaultServiceManager1_2();
91
92 const std::string descriptor = getDescriptor(service.get());
93
94 LOG(INFO) << "Registering HAL: " << descriptor << " with name: " << name;
95
96 status_t res = android::hardware::details::registerAsServiceInternal(service, name);
97 if (res != android::OK) {
98 LOG(ERROR) << "Failed to register as service.";
99 return false;
100 }
101
102 bool ret = manager->registerClientCallback(getDescriptor(service.get()), name, service, this);
103 if (!ret) {
104 LOG(ERROR) << "Failed to add client callback.";
105 return false;
106 }
107
108 return true;
Peter Kalauskas3373cd32018-10-24 15:37:00 -0700109}
110
111/**
112 * onClients is oneway, so no need to worry about multi-threading. Note that this means multiple
113 * invocations could occur on different threads however.
114 */
115Return<void> ClientCounterCallback::onClients(const sp<::android::hidl::base::V1_0::IBase>& service,
116 bool clients) {
117 if (clients) {
Peter Kalauskas3373cd32018-10-24 15:37:00 -0700118 mNumConnectedServices++;
119 } else {
Peter Kalauskas3373cd32018-10-24 15:37:00 -0700120 mNumConnectedServices--;
121 }
Steven Moreland40b3ab42019-01-25 13:23:20 -0800122
123 LOG(INFO) << "Process has " << mNumConnectedServices << " (of " << mRegisteredServices.size()
Steven Moreland06d58be2019-02-04 14:20:13 -0800124 << " available) client(s) in use after notification " << getDescriptor(service.get())
Steven Moreland40b3ab42019-01-25 13:23:20 -0800125 << " has clients: " << clients;
Peter Kalauskas3373cd32018-10-24 15:37:00 -0700126
127 if (mNumConnectedServices == 0) {
Steven Moreland40b3ab42019-01-25 13:23:20 -0800128 tryShutdown();
129 }
130
131 return Status::ok();
132}
133
134void ClientCounterCallback::tryShutdown() {
135 LOG(INFO) << "Trying to exit HAL. No clients in use for any service in process.";
136
137 auto manager = hardware::defaultServiceManager1_2();
138
139 auto unRegisterIt = mRegisteredServices.begin();
140 for (; unRegisterIt != mRegisteredServices.end(); ++unRegisterIt) {
141 auto& entry = (*unRegisterIt);
142
143 const std::string descriptor = getDescriptor(entry.service.get());
144 bool success = manager->tryUnregister(descriptor, entry.name, entry.service);
145
146 if (!success) {
Steven Moreland06d58be2019-02-04 14:20:13 -0800147 LOG(INFO) << "Failed to unregister HAL " << descriptor << "/" << entry.name;
Steven Moreland40b3ab42019-01-25 13:23:20 -0800148 break;
149 }
150 }
151
152 if (unRegisterIt == mRegisteredServices.end()) {
153 LOG(INFO) << "Unregistered all clients and exiting";
Peter Kalauskas3373cd32018-10-24 15:37:00 -0700154 exit(EXIT_SUCCESS);
155 }
Steven Moreland40b3ab42019-01-25 13:23:20 -0800156
157 for (auto reRegisterIt = mRegisteredServices.begin(); reRegisterIt != unRegisterIt;
158 reRegisterIt++) {
159 auto& entry = (*reRegisterIt);
160
161 // re-register entry
162 if (!registerService(entry.service, entry.name)) {
163 // Must restart. Otherwise, clients will never be able to get ahold of this service.
164 LOG(FATAL) << "Bad state: could not re-register " << getDescriptor(entry.service.get());
165 }
166 }
Peter Kalauskas3373cd32018-10-24 15:37:00 -0700167}
168
Peter Kalauskas7ce31552019-01-03 15:15:46 -0800169status_t LazyServiceRegistrarImpl::registerService(
Peter Kalauskas3373cd32018-10-24 15:37:00 -0700170 const sp<::android::hidl::base::V1_0::IBase>& service, const std::string& name) {
Steven Moreland40b3ab42019-01-25 13:23:20 -0800171 if (!mClientCallback->addRegisteredService(service, name)) {
172 return ::android::UNKNOWN_ERROR;
Peter Kalauskas3373cd32018-10-24 15:37:00 -0700173 }
Steven Moreland40b3ab42019-01-25 13:23:20 -0800174
175 return ::android::OK;
Peter Kalauskas3373cd32018-10-24 15:37:00 -0700176}
177
178} // namespace details
179
180LazyServiceRegistrar::LazyServiceRegistrar() {
181 mImpl = std::make_shared<details::LazyServiceRegistrarImpl>();
182}
183
Peter Kalauskas1e969222019-08-14 12:13:11 -0700184LazyServiceRegistrar& LazyServiceRegistrar::getInstance() {
185 static auto registrarInstance = new LazyServiceRegistrar();
186 return *registrarInstance;
187}
188
Peter Kalauskas7ce31552019-01-03 15:15:46 -0800189status_t LazyServiceRegistrar::registerService(
Peter Kalauskas3373cd32018-10-24 15:37:00 -0700190 const sp<::android::hidl::base::V1_0::IBase>& service, const std::string& name) {
Peter Kalauskas7ce31552019-01-03 15:15:46 -0800191 return mImpl->registerService(service, name);
Peter Kalauskas3373cd32018-10-24 15:37:00 -0700192}
193
194} // namespace hardware
195} // namespace android