blob: 463d67f945dfccd72377eb2d0414c99c81c89e65 [file] [log] [blame]
Steven Moreland80e1e6d2019-06-21 12:35:59 -07001/*
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 "ServiceManager.h"
18
19#include <android-base/logging.h>
Jon Spivack0d844302019-07-22 18:40:34 -070020#include <android-base/properties.h>
Steven Moreland80e1e6d2019-06-21 12:35:59 -070021#include <cutils/android_filesystem_config.h>
22#include <cutils/multiuser.h>
Jon Spivack0d844302019-07-22 18:40:34 -070023#include <thread>
Steven Moreland80e1e6d2019-06-21 12:35:59 -070024
25using ::android::binder::Status;
26
27namespace android {
28
29ServiceManager::ServiceManager(std::unique_ptr<Access>&& access) : mAccess(std::move(access)) {}
Steven Moreland130242d2019-08-26 17:41:32 -070030ServiceManager::~ServiceManager() {
31 // this should only happen in tests
32
Steven Moreland27cfab02019-08-12 14:34:16 -070033 for (const auto& [name, callbacks] : mNameToCallback) {
34 CHECK(!callbacks.empty()) << name;
35 for (const auto& callback : callbacks) {
36 CHECK(callback != nullptr) << name;
37 }
38 }
39
Steven Moreland130242d2019-08-26 17:41:32 -070040 for (const auto& [name, service] : mNameToService) {
41 CHECK(service.binder != nullptr) << name;
42 }
43}
Steven Moreland80e1e6d2019-06-21 12:35:59 -070044
45Status ServiceManager::getService(const std::string& name, sp<IBinder>* outBinder) {
Jon Spivack0d844302019-07-22 18:40:34 -070046 *outBinder = tryGetService(name, true);
47 // returns ok regardless of result for legacy reasons
48 return Status::ok();
Steven Moreland80e1e6d2019-06-21 12:35:59 -070049}
50
51Status ServiceManager::checkService(const std::string& name, sp<IBinder>* outBinder) {
Jon Spivack0d844302019-07-22 18:40:34 -070052 *outBinder = tryGetService(name, false);
53 // returns ok regardless of result for legacy reasons
54 return Status::ok();
55}
56
57sp<IBinder> ServiceManager::tryGetService(const std::string& name, bool startIfNotFound) {
Steven Morelanda9fe4742019-07-18 14:45:20 -070058 auto ctx = mAccess->getCallingContext();
Steven Moreland80e1e6d2019-06-21 12:35:59 -070059
Jon Spivack0d844302019-07-22 18:40:34 -070060 sp<IBinder> out;
61 if (auto it = mNameToService.find(name); it != mNameToService.end()) {
62 const Service& service = it->second;
Steven Moreland80e1e6d2019-06-21 12:35:59 -070063
Jon Spivack0d844302019-07-22 18:40:34 -070064 if (!service.allowIsolated) {
65 uid_t appid = multiuser_get_app_id(ctx.uid);
66 bool isIsolated = appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END;
Steven Moreland80e1e6d2019-06-21 12:35:59 -070067
Jon Spivack0d844302019-07-22 18:40:34 -070068 if (isIsolated) {
69 return nullptr;
70 }
Steven Moreland80e1e6d2019-06-21 12:35:59 -070071 }
Jon Spivack0d844302019-07-22 18:40:34 -070072 out = service.binder;
Steven Moreland80e1e6d2019-06-21 12:35:59 -070073 }
74
Steven Morelanda9fe4742019-07-18 14:45:20 -070075 if (!mAccess->canFind(ctx, name)) {
Jon Spivack0d844302019-07-22 18:40:34 -070076 return nullptr;
Steven Moreland80e1e6d2019-06-21 12:35:59 -070077 }
78
Jon Spivack0d844302019-07-22 18:40:34 -070079 if (!out && startIfNotFound) {
80 tryStartService(name);
81 }
82
83 return out;
Steven Moreland80e1e6d2019-06-21 12:35:59 -070084}
85
Steven Moreland905e2e82019-07-17 11:05:45 -070086bool isValidServiceName(const std::string& name) {
87 if (name.size() == 0) return false;
88 if (name.size() > 127) return false;
89
90 for (char c : name) {
Steven Morelandbb7951d2019-08-20 16:58:25 -070091 if (c == '_' || c == '-' || c == '.' || c == '/') continue;
Steven Moreland905e2e82019-07-17 11:05:45 -070092 if (c >= 'a' && c <= 'z') continue;
93 if (c >= 'A' && c <= 'Z') continue;
94 if (c >= '0' && c <= '9') continue;
95 return false;
96 }
97
98 return true;
99}
100
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700101Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) {
Steven Morelanda9fe4742019-07-18 14:45:20 -0700102 auto ctx = mAccess->getCallingContext();
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700103
104 // apps cannot add services
105 if (multiuser_get_app_id(ctx.uid) >= AID_APP) {
106 return Status::fromExceptionCode(Status::EX_SECURITY);
107 }
108
Steven Morelanda9fe4742019-07-18 14:45:20 -0700109 if (!mAccess->canAdd(ctx, name)) {
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700110 return Status::fromExceptionCode(Status::EX_SECURITY);
111 }
112
113 if (binder == nullptr) {
114 return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
115 }
116
Steven Moreland905e2e82019-07-17 11:05:45 -0700117 if (!isValidServiceName(name)) {
118 LOG(ERROR) << "Invalid service name: " << name;
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700119 return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
120 }
121
Steven Moreland88860b02019-08-12 14:24:14 -0700122 // implicitly unlinked when the binder is removed
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700123 if (OK != binder->linkToDeath(this)) {
124 LOG(ERROR) << "Could not linkToDeath when adding " << name;
125 return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
126 }
127
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700128 mNameToService[name] = Service {
129 .binder = binder,
130 .allowIsolated = allowIsolated,
131 .dumpPriority = dumpPriority,
132 };
133
Steven Moreland27cfab02019-08-12 14:34:16 -0700134 auto it = mNameToCallback.find(name);
135 if (it != mNameToCallback.end()) {
136 for (const sp<IServiceCallback>& cb : it->second) {
137 // permission checked in registerForNotifications
138 cb->onRegistration(name, binder);
139 }
140 }
141
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700142 return Status::ok();
143}
144
145Status ServiceManager::listServices(int32_t dumpPriority, std::vector<std::string>* outList) {
Steven Morelanda9fe4742019-07-18 14:45:20 -0700146 if (!mAccess->canList(mAccess->getCallingContext())) {
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700147 return Status::fromExceptionCode(Status::EX_SECURITY);
148 }
149
150 size_t toReserve = 0;
151 for (auto const& [name, service] : mNameToService) {
152 (void) name;
153
154 if (service.dumpPriority & dumpPriority) ++toReserve;
155 }
156
157 CHECK(outList->empty());
158
159 outList->reserve(toReserve);
160 for (auto const& [name, service] : mNameToService) {
161 (void) service;
162
163 if (service.dumpPriority & dumpPriority) {
164 outList->push_back(name);
165 }
166 }
167
168 return Status::ok();
169}
170
Steven Moreland27cfab02019-08-12 14:34:16 -0700171Status ServiceManager::registerForNotifications(
172 const std::string& name, const sp<IServiceCallback>& callback) {
173 auto ctx = mAccess->getCallingContext();
174
175 if (!mAccess->canFind(ctx, name)) {
176 return Status::fromExceptionCode(Status::EX_SECURITY);
177 }
178
179 if (!isValidServiceName(name)) {
180 LOG(ERROR) << "Invalid service name: " << name;
181 return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
182 }
183
184 if (callback == nullptr) {
185 return Status::fromExceptionCode(Status::EX_NULL_POINTER);
186 }
187
188 if (OK != IInterface::asBinder(callback)->linkToDeath(this)) {
189 LOG(ERROR) << "Could not linkToDeath when adding " << name;
190 return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
191 }
192
193 mNameToCallback[name].push_back(callback);
194
195 if (auto it = mNameToService.find(name); it != mNameToService.end()) {
196 const sp<IBinder>& binder = it->second.binder;
197
198 // never null if an entry exists
199 CHECK(binder != nullptr) << name;
200 callback->onRegistration(name, binder);
201 }
202
203 return Status::ok();
204}
205Status ServiceManager::unregisterForNotifications(
206 const std::string& name, const sp<IServiceCallback>& callback) {
207 auto ctx = mAccess->getCallingContext();
208
209 if (!mAccess->canFind(ctx, name)) {
210 return Status::fromExceptionCode(Status::EX_SECURITY);
211 }
212
213 bool found = false;
214
215 auto it = mNameToCallback.find(name);
216 if (it != mNameToCallback.end()) {
217 removeCallback(IInterface::asBinder(callback), &it, &found);
218 }
219
220 if (!found) {
221 LOG(ERROR) << "Trying to unregister callback, but none exists " << name;
222 return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
223 }
224
225 return Status::ok();
226}
227
228void ServiceManager::removeCallback(const wp<IBinder>& who,
229 CallbackMap::iterator* it,
230 bool* found) {
231 std::vector<sp<IServiceCallback>>& listeners = (*it)->second;
232
233 for (auto lit = listeners.begin(); lit != listeners.end();) {
234 if (IInterface::asBinder(*lit) == who) {
235 if(found) *found = true;
236 lit = listeners.erase(lit);
237 } else {
238 ++lit;
239 }
240 }
241
242 if (listeners.empty()) {
243 *it = mNameToCallback.erase(*it);
244 } else {
245 it++;
246 }
247}
248
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700249void ServiceManager::binderDied(const wp<IBinder>& who) {
250 for (auto it = mNameToService.begin(); it != mNameToService.end();) {
251 if (who == it->second.binder) {
252 it = mNameToService.erase(it);
253 } else {
254 ++it;
255 }
256 }
Steven Moreland27cfab02019-08-12 14:34:16 -0700257
258 for (auto it = mNameToCallback.begin(); it != mNameToCallback.end();) {
259 removeCallback(who, &it, nullptr /*found*/);
260 }
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700261}
262
Jon Spivack0d844302019-07-22 18:40:34 -0700263void ServiceManager::tryStartService(const std::string& name) {
264 ALOGI("Since '%s' could not be found, trying to start it as a lazy AIDL service",
265 name.c_str());
266
267 std::thread([=] {
268 (void)base::SetProperty("ctl.interface_start", "aidl/" + name);
269 }).detach();
270}
271
Steven Moreland80e1e6d2019-06-21 12:35:59 -0700272} // namespace android