diff options
-rw-r--r-- | libs/fakeservicemanager/Android.bp | 25 | ||||
-rw-r--r-- | libs/fakeservicemanager/ServiceManager.cpp | 64 | ||||
-rw-r--r-- | libs/fakeservicemanager/ServiceManager.h | 74 | ||||
-rw-r--r-- | libs/fakeservicemanager/test_sm.cpp | 126 |
4 files changed, 289 insertions, 0 deletions
diff --git a/libs/fakeservicemanager/Android.bp b/libs/fakeservicemanager/Android.bp new file mode 100644 index 0000000000..de32ff4e64 --- /dev/null +++ b/libs/fakeservicemanager/Android.bp @@ -0,0 +1,25 @@ +cc_defaults { + name: "fakeservicemanager_defaults", + srcs: [ + "ServiceManager.cpp", + ], + + shared_libs: [ + "libbinder", + "libutils", + ], +} + +cc_library { + name: "libfakeservicemanager", + defaults: ["fakeservicemanager_defaults"], +} + +cc_test_host { + name: "fakeservicemanager_test", + defaults: ["fakeservicemanager_defaults"], + srcs: [ + "test_sm.cpp", + ], + static_libs: ["libgmock"], +} diff --git a/libs/fakeservicemanager/ServiceManager.cpp b/libs/fakeservicemanager/ServiceManager.cpp new file mode 100644 index 0000000000..69643249e3 --- /dev/null +++ b/libs/fakeservicemanager/ServiceManager.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2020 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 "ServiceManager.h" + +namespace android { + +ServiceManager::ServiceManager() {} + +sp<IBinder> ServiceManager::getService( const String16& name) const { + // Servicemanager is single-threaded and cannot block. This method exists for legacy reasons. + return checkService(name); +} + +sp<IBinder> ServiceManager::checkService( const String16& name) const { + auto it = mNameToService.find(name); + if (it == mNameToService.end()) { + return nullptr; + } + return it->second; +} + +status_t ServiceManager::addService(const String16& name, const sp<IBinder>& service, + bool /*allowIsolated*/, + int /*dumpsysFlags*/) { + mNameToService[name] = service; + return NO_ERROR; +} + +Vector<String16> ServiceManager::listServices(int /*dumpsysFlags*/) { + Vector<String16> services; + for (auto const& [name, service] : mNameToService) { + (void) service; + services.push_back(name); + } + return services; +} + +IBinder* ServiceManager::onAsBinder() { + return nullptr; +} + +sp<IBinder> ServiceManager::waitForService(const String16& name) { + return checkService(name); +} + +bool ServiceManager::isDeclared(const String16& name) { + return mNameToService.find(name) != mNameToService.end(); +} + +} // namespace android diff --git a/libs/fakeservicemanager/ServiceManager.h b/libs/fakeservicemanager/ServiceManager.h new file mode 100644 index 0000000000..62311d4727 --- /dev/null +++ b/libs/fakeservicemanager/ServiceManager.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once + +#include <binder/IServiceManager.h> + +#include <map> + +namespace android { + +/** + * A local host simple implementation of IServiceManager, that does not + * communicate over binder. +*/ +class ServiceManager : public IServiceManager { +public: + ServiceManager(); + + /** + * Equivalent of checkService. + */ + sp<IBinder> getService( const String16& name) const override; + + /** + * Retrieve an existing service, non-blocking. + */ + sp<IBinder> checkService( const String16& name) const override; + + /** + * Register a service. + */ + status_t addService(const String16& name, const sp<IBinder>& service, + bool allowIsolated = false, + int dumpsysFlags = DUMP_FLAG_PRIORITY_DEFAULT) override; + + /** + * Return list of all existing services. + */ + Vector<String16> listServices(int dumpsysFlags = 0) override; + + IBinder* onAsBinder() override; + + /** + * Effectively no-oped in this implementation - equivalent to checkService. + */ + sp<IBinder> waitForService(const String16& name) override; + + /** + * Check if a service is declared (e.g. VINTF manifest). + * + * If this returns true, waitForService should always be able to return the + * service. + */ + bool isDeclared(const String16& name) override; + +private: + std::map<String16, sp<IBinder>> mNameToService; +}; + +} // namespace android diff --git a/libs/fakeservicemanager/test_sm.cpp b/libs/fakeservicemanager/test_sm.cpp new file mode 100644 index 0000000000..71e5abe126 --- /dev/null +++ b/libs/fakeservicemanager/test_sm.cpp @@ -0,0 +1,126 @@ +/* + * 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 <gtest/gtest.h> +#include <gmock/gmock.h> + +#include <binder/Binder.h> +#include <binder/ProcessState.h> +#include <binder/IServiceManager.h> + +#include "ServiceManager.h" + +using android::sp; +using android::BBinder; +using android::IBinder; +using android::OK; +using android::status_t; +using android::ServiceManager; +using android::String16; +using android::IServiceManager; +using testing::ElementsAre; + +static sp<IBinder> getBinder() { + class LinkableBinder : public BBinder { + status_t linkToDeath(const sp<DeathRecipient>&, void*, uint32_t) override { + // let SM linkToDeath + return OK; + } + }; + + return new LinkableBinder; +} + +TEST(AddService, HappyHappy) { + auto sm = new ServiceManager(); + EXPECT_EQ(sm->addService(String16("foo"), getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT), OK); +} + +TEST(AddService, HappyOverExistingService) { + auto sm = new ServiceManager(); + EXPECT_EQ(sm->addService(String16("foo"), getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT), OK); + EXPECT_EQ(sm->addService(String16("foo"), getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT), OK); +} + +TEST(GetService, HappyHappy) { + auto sm = new ServiceManager(); + sp<IBinder> service = getBinder(); + + EXPECT_EQ(sm->addService(String16("foo"), service, false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT), OK); + + EXPECT_EQ(sm->getService(String16("foo")), service); +} + +TEST(GetService, NonExistant) { + auto sm = new ServiceManager(); + + EXPECT_EQ(sm->getService(String16("foo")), nullptr); +} + +TEST(ListServices, AllServices) { + auto sm = new ServiceManager(); + + EXPECT_EQ(sm->addService(String16("sd"), getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT), OK); + EXPECT_EQ(sm->addService(String16("sc"), getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_NORMAL), OK); + EXPECT_EQ(sm->addService(String16("sb"), getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_HIGH), OK); + EXPECT_EQ(sm->addService(String16("sa"), getBinder(), false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL), OK); + + android::Vector<String16> out = sm->listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL); + + // all there and in the right order + EXPECT_THAT(out, ElementsAre(String16("sa"), String16("sb"), String16("sc"), + String16("sd"))); +} + +TEST(WaitForService, NonExistant) { + auto sm = new ServiceManager(); + + EXPECT_EQ(sm->waitForService(String16("foo")), nullptr); +} + +TEST(WaitForService, HappyHappy) { + auto sm = new ServiceManager(); + sp<IBinder> service = getBinder(); + + EXPECT_EQ(sm->addService(String16("foo"), service, false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT), OK); + + EXPECT_EQ(sm->waitForService(String16("foo")), service); +} + +TEST(IsDeclared, NonExistant) { + auto sm = new ServiceManager(); + + EXPECT_FALSE(sm->isDeclared(String16("foo"))); +} + +TEST(IsDeclared, HappyHappy) { + auto sm = new ServiceManager(); + sp<IBinder> service = getBinder(); + + EXPECT_EQ(sm->addService(String16("foo"), service, false /*allowIsolated*/, + IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT), OK); + + EXPECT_TRUE(sm->isDeclared(String16("foo"))); +} |