diff options
author | Tri Vo <trong@google.com> | 2019-02-05 13:45:17 -0800 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2019-02-05 13:45:17 -0800 |
commit | dc048f17154e42bb66d1efdecf96315938b8a1d4 (patch) | |
tree | 2c4e7b3f0657b43e1b61c9b3e3569f405e4a101a | |
parent | 9759c00041f21d4a4c5696f0be1f1b21da4faffe (diff) | |
parent | df205799f399528a822fefce5ae1e6e46cea5410 (diff) | |
download | platform_system_ashmemd-dc048f17154e42bb66d1efdecf96315938b8a1d4.tar.gz platform_system_ashmemd-dc048f17154e42bb66d1efdecf96315938b8a1d4.tar.bz2 platform_system_ashmemd-dc048f17154e42bb66d1efdecf96315938b8a1d4.zip |
ashmemd: daemon that provides /dev/ashmem fds
am: df205799f3
Change-Id: I45720cf5fd010b0ff654b4cad97f8394a8049e22
-rw-r--r-- | Android.bp | 60 | ||||
-rw-r--r-- | OWNERS | 1 | ||||
-rw-r--r-- | aidl/android/ashmemd/IAshmemDeviceService.aidl | 23 | ||||
-rw-r--r-- | ashmemd.cpp | 59 | ||||
-rw-r--r-- | ashmemd.rc | 4 | ||||
-rw-r--r-- | ashmemd_client.cpp | 49 | ||||
-rw-r--r-- | tests/ashmemd_test.cpp | 94 |
7 files changed, 290 insertions, 0 deletions
diff --git a/Android.bp b/Android.bp new file mode 100644 index 0000000..37699f8 --- /dev/null +++ b/Android.bp @@ -0,0 +1,60 @@ +// Copyright (C) 2018 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. + +aidl_interface { + name: "ashmemd_aidl_interface", + local_include_dir: "aidl", + srcs: [ + "aidl/android/ashmemd/IAshmemDeviceService.aidl", + ], +} + +cc_defaults { + name: "ashmemd_defaults", + shared_libs: [ + "ashmemd_aidl_interface-cpp", + "libbase", + "libbinder", + "libutils", + ], + cflags: [ + "-Wall", + "-Werror", + ], +} + +cc_binary { + name: "ashmemd", + defaults: ["ashmemd_defaults"], + srcs: ["ashmemd.cpp"], + init_rc: ["ashmemd.rc"], +} + +// This library is used to communicate with ashmemd using dlopen/dlsym. We do +// this to avoid shared library dependecy cycles. +cc_library { + name: "libashmemd_client", + defaults: ["ashmemd_defaults"], + srcs: ["ashmemd_client.cpp"], + cflags: [ + "-Wexit-time-destructors", + "-fno-c++-static-destructors", + ], +} + +cc_test { + name: "ashmemd_test", + defaults: ["ashmemd_defaults"], + srcs: ["tests/ashmemd_test.cpp"], +} @@ -0,0 +1 @@ +trong@google.com diff --git a/aidl/android/ashmemd/IAshmemDeviceService.aidl b/aidl/android/ashmemd/IAshmemDeviceService.aidl new file mode 100644 index 0000000..283db13 --- /dev/null +++ b/aidl/android/ashmemd/IAshmemDeviceService.aidl @@ -0,0 +1,23 @@ +/* + * 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. + */ + +package android.ashmemd; + +/** {@hide} */ +interface IAshmemDeviceService { + /* Opens a file descriptor to /dev/ashmem */ + ParcelFileDescriptor open(); +} diff --git a/ashmemd.cpp b/ashmemd.cpp new file mode 100644 index 0000000..9d12ed3 --- /dev/null +++ b/ashmemd.cpp @@ -0,0 +1,59 @@ +/* + * 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 <android-base/unique_fd.h> +#include <binder/BinderService.h> +#include <binder/IPCThreadState.h> +#include <binder/IServiceManager.h> +#include <binder/ProcessState.h> +#include <binder/Status.h> +#include <utils/String16.h> + +#include <android/ashmemd/BnAshmemDeviceService.h> + +using android::String16; +using android::base::unique_fd; + +namespace android { +namespace ashmemd { + +class AshmemDeviceService : public BnAshmemDeviceService { + public: + binder::Status open(os::ParcelFileDescriptor* ashmemFd) override { + ashmemFd->reset(unique_fd(TEMP_FAILURE_RETRY(::open("/dev/ashmem", O_RDWR | O_CLOEXEC)))); + return binder::Status::ok(); + } +}; + +void CreateAndRegisterService() { + sp<AshmemDeviceService> ashmemService = new AshmemDeviceService(); + defaultServiceManager()->addService(String16("ashmem_device_service"), ashmemService, + true /* allowIsolated */); +} + +void JoinThreadPool() { + sp<ProcessState> ps = ProcessState::self(); + IPCThreadState::self()->joinThreadPool(); // should not return +} + +} // namespace ashmemd +} // namespace android + +int main() { + android::ashmemd::CreateAndRegisterService(); + android::ashmemd::JoinThreadPool(); + std::abort(); // unreachable +} diff --git a/ashmemd.rc b/ashmemd.rc new file mode 100644 index 0000000..ee16d95 --- /dev/null +++ b/ashmemd.rc @@ -0,0 +1,4 @@ +service ashmemd /system/bin/ashmemd + class core + user nobody + group nobody diff --git a/ashmemd_client.cpp b/ashmemd_client.cpp new file mode 100644 index 0000000..1984358 --- /dev/null +++ b/ashmemd_client.cpp @@ -0,0 +1,49 @@ +/* + * 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 <android/ashmemd/IAshmemDeviceService.h> +#include <binder/IServiceManager.h> + +using android::IBinder; +using android::IServiceManager; +using android::String16; +using android::ashmemd::IAshmemDeviceService; +using android::os::ParcelFileDescriptor; + +namespace android { +namespace ashmemd { + +sp<IAshmemDeviceService> getAshmemService() { + sp<IServiceManager> sm = android::defaultServiceManager(); + sp<IBinder> binder = sm->getService(String16("ashmem_device_service")); + return interface_cast<IAshmemDeviceService>(binder); +} + +extern "C" int openAshmemdFd() { + static sp<IAshmemDeviceService> ashmemService = getAshmemService(); + if (!ashmemService) return -1; + + ParcelFileDescriptor fd; + auto status = ashmemService->open(&fd); + if (!status.isOk()) return -1; + + // unique_fd is the underlying type of ParcelFileDescriptor, i.e. fd is + // closed when it falls out of scope, so we make a dup. + return dup(fd.get()); +} + +} // namespace ashmemd +} // namespace android diff --git a/tests/ashmemd_test.cpp b/tests/ashmemd_test.cpp new file mode 100644 index 0000000..ed3cfe3 --- /dev/null +++ b/tests/ashmemd_test.cpp @@ -0,0 +1,94 @@ +/* + * 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 <dlfcn.h> + +#include <binder/IServiceManager.h> +#include <gtest/gtest.h> +#include <linux/ashmem.h> +#include <sys/mman.h> + +#include <android/ashmemd/IAshmemDeviceService.h> + +using android::IBinder; +using android::IServiceManager; +using android::String16; +using android::ashmemd::IAshmemDeviceService; +using android::os::ParcelFileDescriptor; + +namespace android { +namespace ashmemd { + +class AshmemdTest : public ::testing::Test { + public: + virtual void SetUp() override { + sp<IServiceManager> sm = android::defaultServiceManager(); + sp<IBinder> binder = sm->getService(String16("ashmem_device_service")); + ASSERT_NE(binder, nullptr); + + ashmemService = android::interface_cast<IAshmemDeviceService>(binder); + ASSERT_NE(ashmemService, nullptr); + } + + void openFd(ParcelFileDescriptor* fd) { + auto status = ashmemService->open(fd); + ASSERT_TRUE(status.isOk()); + ASSERT_GE(fd->get(), 0); + } + + sp<IAshmemDeviceService> ashmemService; +}; + +TEST_F(AshmemdTest, OpenFd) { + ParcelFileDescriptor fd; + openFd(&fd); +} + +TEST_F(AshmemdTest, OpenMultipleFds) { + ParcelFileDescriptor fd1; + ParcelFileDescriptor fd2; + openFd(&fd1); + openFd(&fd2); + ASSERT_NE(fd1.get(), fd2.get()); +} + +TEST_F(AshmemdTest, MmapFd) { + ParcelFileDescriptor pfd; + openFd(&pfd); + int fd = pfd.get(); + size_t testSize = 2097152; + + ASSERT_EQ(ioctl(fd, ASHMEM_SET_NAME, "AshmemdTest"), 0); + ASSERT_EQ(ioctl(fd, ASHMEM_SET_SIZE, testSize), 0); + + void* data = mmap(NULL, testSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + ASSERT_NE(data, MAP_FAILED) << "Failed to mmap() ashmem fd"; + ASSERT_EQ(munmap(data, testSize), 0) << "Failed to munmap() ashmem fd"; +} + +TEST(LibAshmemdClientTest, OpenFd) { + void* handle = dlopen("libashmemd_client.so", RTLD_NOW); + ASSERT_NE(handle, nullptr) << "Failed to dlopen() libashmemd_client.so: " << dlerror(); + + auto function = (int (*)())dlsym(handle, "openAshmemdFd"); + ASSERT_NE(function, nullptr) << "Failed to dlsym() openAshmemdFd() function: " << dlerror(); + + int fd = function(); + ASSERT_GE(fd, 0) << "Failed to open /dev/ashmem"; +} + +} // namespace ashmemd +} // namespace android |