Update for hidlized service manager.
Test: end to end (runs on device, nfc registers with it and runs)
Test: hidl_test
Bug: 32313592
Change-Id: I8a98e8f46c2f2216a097018599c7ac81701b008b
diff --git a/Android.bp b/Android.bp
index 46c33b0..6bfa6c5 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,20 +1,28 @@
cc_binary {
name: "hwservicemanager",
- srcs: ["hw_service_manager.cpp"],
+ init_rc: [
+ "hwservicemanager.rc",
+ ],
+ srcs: [
+ "ServiceManager.cpp",
+ "service.cpp",
+ ],
cflags: [
"-Wall",
"-Wextra",
"-Werror",
],
shared_libs: [
+ "libhidl",
"liblog",
"libselinux",
- "libhidl",
"libhwbinder",
"libcutils",
"libutils",
],
- export_shared_lib_headers: ["libhwbinder"],
+ export_shared_lib_headers: [
+ "libhwbinder"
+ ],
product_variables: {
binder32bit: {
cflags: ["-DBINDER_IPC_32BIT=1"],
diff --git a/ServiceManager.cpp b/ServiceManager.cpp
new file mode 100644
index 0000000..ff0e9c5
--- /dev/null
+++ b/ServiceManager.cpp
@@ -0,0 +1,64 @@
+#include "ServiceManager.h"
+
+#include <hidl/HidlSupport.h>
+
+namespace android {
+namespace hidl {
+namespace manager {
+namespace V1_0 {
+namespace implementation {
+
+// Methods from ::android::hidl::manager::V1_0::IServiceManager follow.
+Return<void> ServiceManager::get(const hidl_string& name, const Version& version, get_cb _hidl_cb) {
+ const std::string name_str = name.c_str();
+ auto numEntries = mServiceMap.count(name_str);
+ auto it = mServiceMap.find(name_str);
+
+ hidl_version hidlVersion (version.major, version.minor);
+
+ while (numEntries > 0) {
+ if (it->second->supportsVersion(hidlVersion)) {
+ _hidl_cb(it->second->getService());
+ return Void();
+ }
+ --numEntries;
+ ++it;
+ }
+
+ _hidl_cb(nullptr);
+ return Void();
+}
+
+Return<bool> ServiceManager::add(const hidl_string& name, const sp<IBinder>& service, const Version& version) {
+ const std::string name_str = name.c_str();
+ size_t numEntries = mServiceMap.count(name_str);
+ auto service_iter = mServiceMap.find(name_str);
+ bool replaced = false;
+
+ const hidl_version hidlVersion (version.major, version.minor);
+
+ while (numEntries > 0) {
+ if (service_iter->second->getVersion() == hidlVersion) {
+ // Just update service reference
+ service_iter->second->setService(service);
+ replaced = true;
+ break;
+ }
+ --numEntries;
+ ++service_iter;
+ }
+ if (!replaced) {
+ mServiceMap.insert({name_str, std::unique_ptr<HidlService>(
+ new HidlService(name_str, service, version, ""))});
+ }
+
+ // TODO link to death so we know when it dies
+
+ return true;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace manager
+} // namespace hidl
+} // namespace android
diff --git a/ServiceManager.h b/ServiceManager.h
new file mode 100644
index 0000000..185425e
--- /dev/null
+++ b/ServiceManager.h
@@ -0,0 +1,83 @@
+#ifndef HIDL_GENERATED_android_hardware_manager_V1_0_ServiceManager_H_
+#define HIDL_GENERATED_android_hardware_manager_V1_0_ServiceManager_H_
+
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <hidl/Status.h>
+#include <hidl/MQDescriptor.h>
+#include <map>
+
+namespace android {
+namespace hidl {
+namespace manager {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_version;
+using ::android::hardware::IBinder;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hidl::manager::V1_0::IServiceManager;
+using ::android::sp;
+
+using Version = ::android::hidl::manager::V1_0::IServiceManager::Version;
+
+struct HidlService {
+ HidlService(const std::string &name,
+ const sp<IBinder>& service,
+ const Version& version,
+ const std::string &metaVersion)
+ : mName(name),
+ mVersion(version.major, version.minor),
+ mMetaVersion(metaVersion),
+ mService(service) {}
+
+ sp<IBinder> getService() const {
+ return mService;
+ }
+
+ void setService(const sp<IBinder>& service) {
+ mService = service;
+ }
+
+ const hidl_version& getVersion() const {
+ return mVersion;
+ }
+
+ bool supportsVersion(hidl_version version) {
+ if (version.get_major() == mVersion.get_major() &&
+ version.get_minor() <= mVersion.get_minor()) {
+ return true;
+ }
+ // TODO remove log
+ ALOGE("Service doesn't support version %u.%u", version.get_major(), version.get_minor());
+ return false;
+ }
+
+private:
+ const std::string mName;
+ const hidl_version mVersion;
+ const std::string mMetaVersion;
+ sp<IBinder> mService;
+};
+
+struct ServiceManager : public IServiceManager {
+ // Methods from ::android::hidl::manager::V1_0::IServiceManager follow.
+ Return<void> get(const hidl_string& name, const Version& version, get_cb _hidl_cb) override;
+ Return<bool> add(const hidl_string& name, const sp<IBinder>& service, const Version& version) override;
+
+private:
+
+ // Access to this map doesn't need to be locked, since hwservicemanager
+ // is single-threaded.
+ std::multimap<std::string, std::unique_ptr<HidlService>> mServiceMap;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace manager
+} // namespace hidl
+} // namespace android
+
+#endif // HIDL_GENERATED_android_hardware_manager_V1_0_ServiceManager_H_
diff --git a/hw_service_manager.cpp b/hw_service_manager.cpp
deleted file mode 100644
index 98a8a20..0000000
--- a/hw_service_manager.cpp
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#define LOG_TAG "hwservicemanager"
-#include <utils/Log.h>
-
-#include <map>
-
-#include <inttypes.h>
-#include <unistd.h>
-
-#include <cutils/properties.h>
-#include <hidl/IServiceManager.h>
-#include <hidl/Status.h>
-#include <hwbinder/IInterface.h>
-#include <hwbinder/IPCThreadState.h>
-#include <hwbinder/ProcessState.h>
-#include <utils/Errors.h>
-#include <utils/Looper.h>
-#include <utils/StrongPointer.h>
-
-// libutils:
-using android::BAD_TYPE;
-using android::Looper;
-using android::LooperCallback;
-using android::OK;
-using android::sp;
-using android::status_t;
-using android::String16;
-
-// libbinder:
-using android::hardware::BBinder;
-using android::hardware::BnInterface;
-using android::hardware::defaultServiceManager;
-using android::hardware::IBinder;
-using android::hardware::IInterface;
-using android::hardware::IPCThreadState;
-using android::hardware::Parcel;
-using android::hardware::ProcessState;
-using android::hardware::Status;
-using android::hardware::hidl_version;
-
-// Standard library
-using std::multimap;
-using std::string;
-using std::unique_ptr;
-using std::vector;
-
-// Service manager definition
-using android::hardware::IServiceManager;
-using android::hardware::IHwServiceManager;
-
-namespace {
-
-class BinderCallback : public LooperCallback {
- public:
- BinderCallback() {}
- ~BinderCallback() override {}
-
- int handleEvent(int /* fd */, int /* events */, void* /* data */) override {
- IPCThreadState::self()->handlePolledCommands();
- return 1; // Continue receiving callbacks.
- }
-};
-
-class HidlService {
- public:
- HidlService(const string &name, const sp<IBinder>& service, const hidl_version& version,
- const string &metaVersion) : mName(name), mVersion(version),
- mMetaVersion(metaVersion), mService(service) {
- }
- sp<IBinder> getService() {
- return mService;
- }
- void setService(const sp<IBinder>& service) {
- mService = service;
- }
-
- hidl_version& getVersion() {
- return mVersion;
- }
-
- bool supportsVersion(hidl_version version) {
- if (version.get_major() == mVersion.get_major() &&
- version.get_minor() <= mVersion.get_minor()) {
- return true;
- }
- ALOGE("Service doesn't support version %u.%u", version.get_major(), version.get_minor());
- return false;
- }
- private:
- string mName; // Service name
- hidl_version mVersion; // Supported interface version
- string mMetaVersion; // Meta-version of the HIDL interface
- sp<IBinder> mService; // Binder handle to service
-
-};
-
-class HwServiceManager : public BnInterface<IServiceManager, IHwServiceManager> {
- public:
- // Access to this map doesn't need to be locked, since hwservicemanager
- // is single-threaded.
- multimap<string, unique_ptr<HidlService>> mServiceMap;
-
- HwServiceManager() : BnInterface<IServiceManager, IHwServiceManager>(
- sp<IServiceManager>(this)) {
-
- }
-
- /*
- **************************************************************************
- IServiceManager methods
- **************************************************************************
- */
-
- /**
- * getService() is an interface not used on the server-side; it's used
- * on the client-side to block on calling checkService().
- */
- virtual sp<IBinder> getService( const String16& name,
- const hidl_version& version) const {
- return checkService(name, version);
- }
-
- virtual sp<IBinder> checkService( const String16& name,
- const hidl_version& version) const {
- const string name_str = String16::std_string(name);
- auto numEntries = mServiceMap.count(name_str);
- auto service_iter = mServiceMap.find(name_str);
-
- while (numEntries > 0) {
- if (service_iter->second->supportsVersion(version)) {
- return service_iter->second->getService();
- }
- --numEntries;
- ++service_iter;
- }
- return nullptr;
- }
-
- /**
- * Register a service.
- */
- virtual status_t addService( const String16& name,
- const sp<IBinder>& service,
- const hidl_version& version,
- bool /*allowIsolated = false*/) {
- const string name_str = String16::std_string(name);
- auto numEntries = mServiceMap.count(name_str);
- auto service_iter = mServiceMap.find(name_str);
- bool replaced = false;
- while (numEntries > 0) {
- if (service_iter->second->getVersion() == version) {
- // Just update service reference
- service_iter->second->setService(service);
- replaced = true;
- break;
- }
- --numEntries;
- ++service_iter;
- }
- if (!replaced) {
- mServiceMap.insert({name_str, unique_ptr<HidlService>(
- new HidlService(name_str, service, version, ""))});
- }
-
- // TODO link to death so we know when it dies
- return OK;
- }
- /*
- **************************************************************************
- BnInterface methods
- **************************************************************************
- */
-
- virtual status_t onTransact(uint32_t code, const Parcel& parcel_in, Parcel* parcel_out,
- uint32_t flags, TransactCallback callback) {
- status_t ret_status = OK;
- switch (code) {
- case GET_SERVICE_TRANSACTION:
- {
- String16 serviceName;
- hidl_version *version;
- if (!(parcel_in.checkInterface(this))) {
- ret_status = BAD_TYPE;
- break;
- }
- ret_status = parcel_in.readString16(&serviceName);
- if (ret_status != OK) {
- break;
- }
- version = hidl_version::readFromParcel(parcel_in);
- if (version == nullptr) {
- break;
- }
- // TODO SELinux access control
- sp<IBinder> service = getService(serviceName, *version);
- ret_status = parcel_out->writeStrongBinder(service);
- if (ret_status != OK) {
- break;
- } else if (callback != nullptr) {
- callback(*parcel_out);
- }
- break;
- }
- case CHECK_SERVICE_TRANSACTION:
- {
- String16 serviceName;
- hidl_version *version;
- if (!(parcel_in.checkInterface(this))) {
- ret_status = BAD_TYPE;
- break;
- }
- ret_status = parcel_in.readString16(&serviceName);
- if (ret_status != OK) {
- break;
- }
- version = hidl_version::readFromParcel(parcel_in);
- if (version == nullptr) {
- break;
- }
- // TODO SELinux access control
- sp<IBinder> service = getService(serviceName, *version);
- ret_status = parcel_out->writeStrongBinder(service);
- if (ret_status != OK) {
- break;
- } else if (callback != nullptr) {
- callback(*parcel_out);
- }
- break;
- }
- case ADD_SERVICE_TRANSACTION:
- {
- String16 serviceName;
- sp<IBinder> service;
- hidl_version *version;
- if (!(parcel_in.checkInterface(this))) {
- ret_status = BAD_TYPE;
- break;
- }
- ret_status = parcel_in.readString16(&serviceName);
- if (ret_status != OK) {
- break;
- }
- ret_status = parcel_in.readStrongBinder(&service);
- if (ret_status != OK) {
- break;
- }
- version = hidl_version::readFromParcel(parcel_in);
- if (version == nullptr) {
- break;
- }
- // TODO need isolation param?
- // TODO SELinux access control
- ret_status = addService(serviceName, service, *version, false);
- parcel_out->writeInt32(ret_status);
- if (ret_status != OK) {
- break;
- } else if (callback != nullptr) {
- callback(*parcel_out);
- }
- break;
- }
- default:
- {
- ret_status = BBinder::onTransact(code, parcel_in, parcel_out, flags, callback);
- break;
- }
- }
-
- return ret_status;
- }
-};
-
-int Run() {
- android::sp<HwServiceManager> service = new HwServiceManager();
- sp<Looper> looper(Looper::prepare(0 /* opts */));
-
- int binder_fd = -1;
-
- IPCThreadState::self()->setupPolling(&binder_fd);
- if (binder_fd < 0) {
- ALOGE("Failed to aquire binder FD; staying around but doing nothing");
- // hwservicemanager is a critical service; until support for /dev/hwbinder
- // is checked in for all devices, prevent it from exiting; if it were to
- // exit, it would get restarted again and fail again several times,
- // eventually causing the device to boot into recovery mode.
- // TODO: revert
- while (true) {
- sleep(UINT_MAX);
- }
- return -1;
- }
-
- sp<BinderCallback> cb(new BinderCallback);
- if (looper->addFd(binder_fd, Looper::POLL_CALLBACK, Looper::EVENT_INPUT, cb,
- nullptr) != 1) {
- ALOGE("Failed to add binder FD to Looper");
- return -1;
- }
-
- // Tell IPCThreadState we're the service manager
- IPCThreadState::self()->setTheContextObject(service);
- // Then tell binder kernel
- ioctl(binder_fd, BINDER_SET_CONTEXT_MGR, 0);
-
- int rc = property_set("hwservicemanager.ready", "true");
- if (rc) {
- ALOGE("Failed to set \"hwservicemanager.ready\" (error %d). "\
- "HAL services will not launch!\n", rc);
- }
-
- while (true) {
- looper->pollAll(-1 /* timeoutMillis */);
- }
-
- return 0;
-}
-
-} // namespace
-
-int main(int /* argc */, char* /* argv */ []) {
- return Run();
-}
diff --git a/hwservicemanager.rc b/hwservicemanager.rc
new file mode 100644
index 0000000..60af172
--- /dev/null
+++ b/hwservicemanager.rc
@@ -0,0 +1,9 @@
+service hwservicemanager /system/bin/hwservicemanager
+ user system
+ disabled
+ group system readproc
+ critical
+ writepid /dev/cpuset/system-background/tasks
+
+on property:hwservicemanager.ready=true
+ class_start hal
\ No newline at end of file
diff --git a/service.cpp b/service.cpp
new file mode 100644
index 0000000..b03353e
--- /dev/null
+++ b/service.cpp
@@ -0,0 +1,109 @@
+#define LOG_TAG "android.hardware.manager@1.0-service"
+
+#include <utils/Log.h>
+
+#include <inttypes.h>
+#include <unistd.h>
+
+#include <android/hidl/manager/1.0/BnServiceManager.h>
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <cutils/properties.h>
+#include <hidl/Status.h>
+#include <hwbinder/IPCThreadState.h>
+#include <hwbinder/ProcessState.h>
+#include <utils/Errors.h>
+#include <utils/Looper.h>
+#include <utils/StrongPointer.h>
+
+#include "ServiceManager.h"
+
+// libutils:
+using android::BAD_TYPE;
+using android::Looper;
+using android::LooperCallback;
+using android::OK;
+using android::sp;
+using android::status_t;
+
+// libhwbinder:
+using android::hardware::IPCThreadState;
+using android::hardware::ProcessState;
+
+// libhidl
+using android::hardware::hidl_string;
+
+// android.hardware.manager@1.0
+using android::hidl::manager::V1_0::BnServiceManager;
+using android::hidl::manager::V1_0::IServiceManager;
+using Version = android::hidl::manager::V1_0::IServiceManager::Version;
+
+// android.hardware.manager@1.0-service
+using android::hidl::manager::V1_0::implementation::ServiceManager;
+
+static std::string serviceName = "manager";
+
+class BinderCallback : public LooperCallback {
+public:
+ BinderCallback() {}
+ ~BinderCallback() override {}
+
+ int handleEvent(int /* fd */, int /* events */, void* /* data */) override {
+ IPCThreadState::self()->handlePolledCommands();
+ return 1; // Continue receiving callbacks.
+ }
+};
+
+int main() {
+ ServiceManager *manager = new ServiceManager();
+ sp<BnServiceManager> service = new BnServiceManager(manager);
+
+ hidl_string name;
+ name.setToExternal(serviceName.c_str(), serviceName.size());
+ Version version {
+ .major = IServiceManager::version.get_major(),
+ .minor = IServiceManager::version.get_minor(),
+ };
+ manager->add(name, service, version);
+
+ sp<Looper> looper(Looper::prepare(0 /* opts */));
+
+ int binder_fd = -1;
+
+ IPCThreadState::self()->setupPolling(&binder_fd);
+ if (binder_fd < 0) {
+ ALOGE("Failed to aquire binder FD; staying around but doing nothing");
+ // hwservicemanager is a critical service; until support for /dev/hwbinder
+ // is checked in for all devices, prevent it from exiting; if it were to
+ // exit, it would get restarted again and fail again several times,
+ // eventually causing the device to boot into recovery mode.
+ // TODO: revert
+ while (true) {
+ sleep(UINT_MAX);
+ }
+ return -1;
+ }
+
+ sp<BinderCallback> cb(new BinderCallback);
+ if (looper->addFd(binder_fd, Looper::POLL_CALLBACK, Looper::EVENT_INPUT, cb,
+ nullptr) != 1) {
+ ALOGE("Failed to add binder FD to Looper");
+ return -1;
+ }
+
+ // Tell IPCThreadState we're the service manager
+ IPCThreadState::self()->setTheContextObject(service);
+ // Then tell binder kernel
+ ioctl(binder_fd, BINDER_SET_CONTEXT_MGR, 0);
+
+ int rc = property_set("hwservicemanager.ready", "true");
+ if (rc) {
+ ALOGE("Failed to set \"hwservicemanager.ready\" (error %d). "\
+ "HAL services will not launch!\n", rc);
+ }
+
+ while (true) {
+ looper->pollAll(-1 /* timeoutMillis */);
+ }
+
+ return 0;
+}
\ No newline at end of file