diff options
| author | 2020-01-31 09:20:28 -0800 | |
|---|---|---|
| committer | 2020-01-31 09:27:04 -0800 | |
| commit | c9ee3304dc2a752cc2b1343713b8b767331fa12f (patch) | |
| tree | ac98509c192013676fbc05d7a3f9fa676ac41c28 | |
| parent | 77d8f5b5d3a5e16ec9dd5b35d1e7c7e6d993eb2f (diff) | |
Add simple fake for native service manager.
Reusing the existing binder-based native service manager has
proved problematic in host/test environments.
So as a workaround, this commit creates a IServiceManager native
implementation that can be communicated with directly.
Bug: 147595993
Test: m fakeservicemanager_test; fakeservicemanager_test
Change-Id: Icfa6f2fd314bd5a7b3d5e8a064b487f92b99b133
| -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"))); +} |