Loading libcutils/Android.bp +20 −17 Original line number Diff line number Diff line Loading @@ -155,23 +155,18 @@ cc_library { "fs_config.cpp", ], }, not_windows: { srcs: libcutils_nonwindows_sources + [ "ashmem-host.cpp", host: { srcs: [ "trace-host.cpp", "ashmem-host.cpp", ], }, not_windows: { srcs: libcutils_nonwindows_sources, }, windows: { host_ldlibs: ["-lws2_32"], srcs: [ "trace-host.cpp", ], enabled: true, cflags: [ "-D_GNU_SOURCE", ], host_ldlibs: ["-lws2_32"], }, android: { sanitize: { Loading Loading @@ -240,6 +235,7 @@ cc_library { cc_defaults { name: "libcutils_test_default", srcs: [ "ashmem_base_test.cpp", "native_handle_test.cpp", "properties_test.cpp", "sockets_test.cpp", Loading Loading @@ -298,20 +294,26 @@ cc_test { cc_defaults { name: "libcutils_test_static_defaults", defaults: ["libcutils_test_default"], static_libs: [ "libc", "libcgrouprc_format", ] + test_libraries + always_static_test_libraries, stl: "libc++_static", require_root: true, target: { android: { static_executable: true, static_libs: [ "libcgrouprc_format", ] + test_libraries + always_static_test_libraries, }, not_windows: { static_libs: test_libraries + always_static_test_libraries, }, windows: { static_libs: [ "libbase", "libcutils", "libcutils_sockets", ], host_ldlibs: ["-lws2_32"], enabled: true, }, }, Loading @@ -319,6 +321,7 @@ cc_defaults { cc_test { name: "libcutils_test_static", host_supported: true, test_suites: ["device-tests"], defaults: ["libcutils_test_static_defaults"], } Loading libcutils/ashmem-host.cpp +35 −20 Original line number Diff line number Diff line Loading @@ -17,10 +17,13 @@ #include <cutils/ashmem.h> /* * Implementation of the user-space ashmem API for the simulator, which lacks * an ashmem-enabled kernel. See ashmem-dev.c for the real ashmem-based version. * Implementation of the user-space ashmem API for the simulator, which lacks an * ashmem-enabled kernel. See ashmem-dev.c for the real ashmem-based version. A * disk-backed temp file is the best option that is consistently supported * across all host platforms. */ #include <android-base/unique_fd.h> #include <errno.h> #include <fcntl.h> #include <limits.h> Loading @@ -31,8 +34,10 @@ #include <sys/types.h> #include <time.h> #include <unistd.h> #include <utils/Compat.h> #include <memory> using android::base::unique_fd; static bool ashmem_validate_stat(int fd, struct stat* buf) { int result = fstat(fd, buf); Loading @@ -40,15 +45,20 @@ static bool ashmem_validate_stat(int fd, struct stat* buf) { return false; } /* * Check if this is an "ashmem" region. * TODO: This is very hacky, and can easily break. * We need some reliable indicator. */ if (!(buf->st_nlink == 0 && S_ISREG(buf->st_mode))) { // Check if this is an ashmem region. Since there's no such thing on the host, // we can't actually implement that. Check that it's at least a regular file. if (!S_ISREG(buf->st_mode)) { errno = ENOTTY; return false; } // In Win32, unlike Unix, the temp file is not unlinked immediately after // creation. #if !defined(_WIN32) if (buf->st_nlink != 0) { errno = ENOTTY; return false; } #endif return true; } Loading @@ -58,19 +68,24 @@ int ashmem_valid(int fd) { } int ashmem_create_region(const char* /*ignored*/, size_t size) { char pattern[PATH_MAX]; snprintf(pattern, sizeof(pattern), "/tmp/android-ashmem-%d-XXXXXXXXX", getpid()); int fd = mkstemp(pattern); if (fd == -1) return -1; unlink(pattern); // Files returned by tmpfile are automatically removed. std::unique_ptr<FILE, decltype(&fclose)> tmp(tmpfile(), &fclose); if (TEMP_FAILURE_RETRY(ftruncate(fd, size)) == -1) { close(fd); if (!tmp) { return -1; } return fd; int fd = fileno(tmp.get()); if (fd == -1) { return -1; } unique_fd dupfd = unique_fd(dup(fd)); if (dupfd == -1) { return -1; } if (TEMP_FAILURE_RETRY(ftruncate(dupfd, size)) == -1) { return -1; } return dupfd.release(); } int ashmem_set_prot_region(int /*fd*/, int /*prot*/) { Loading libcutils/ashmem_base_test.cpp 0 → 100644 +63 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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 <unistd.h> #include <android-base/mapped_file.h> #include <android-base/unique_fd.h> #include <cutils/ashmem.h> /* * Tests in AshmemBaseTest are designed to run on Android as well as host * platforms (Linux, Mac, Windows). */ #if defined(_WIN32) static inline size_t getpagesize() { return 4096; } #endif using android::base::unique_fd; TEST(AshmemBaseTest, BasicTest) { const size_t size = getpagesize(); std::vector<uint8_t> data(size); std::generate(data.begin(), data.end(), [n = 0]() mutable { return n++ & 0xFF; }); unique_fd fd = unique_fd(ashmem_create_region(nullptr, size)); ASSERT_TRUE(fd >= 0); ASSERT_TRUE(ashmem_valid(fd)); ASSERT_EQ(size, static_cast<size_t>(ashmem_get_size_region(fd))); std::unique_ptr<android::base::MappedFile> mapped = android::base::MappedFile::FromFd(fd, 0, size, PROT_READ | PROT_WRITE); EXPECT_TRUE(mapped.get() != nullptr); void* region1 = mapped->data(); EXPECT_TRUE(region1 != nullptr); memcpy(region1, data.data(), size); ASSERT_EQ(0, memcmp(region1, data.data(), size)); std::unique_ptr<android::base::MappedFile> mapped2 = android::base::MappedFile::FromFd(fd, 0, size, PROT_READ | PROT_WRITE); EXPECT_TRUE(mapped2.get() != nullptr); void* region2 = mapped2->data(); EXPECT_TRUE(region2 != nullptr); ASSERT_EQ(0, memcmp(region2, data.data(), size)); } libcutils/ashmem_test.cpp +0 −22 Original line number Diff line number Diff line Loading @@ -69,28 +69,6 @@ void FillData(std::vector<uint8_t>& data) { } } TEST(AshmemTest, BasicTest) { const size_t size = getpagesize(); std::vector<uint8_t> data(size); FillData(data); unique_fd fd; ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ | PROT_WRITE)); void* region1 = nullptr; ASSERT_NO_FATAL_FAILURE(TestMmap(fd, size, PROT_READ | PROT_WRITE, ®ion1)); memcpy(region1, data.data(), size); ASSERT_EQ(0, memcmp(region1, data.data(), size)); EXPECT_EQ(0, munmap(region1, size)); void *region2; ASSERT_NO_FATAL_FAILURE(TestMmap(fd, size, PROT_READ, ®ion2)); ASSERT_EQ(0, memcmp(region2, data.data(), size)); EXPECT_EQ(0, munmap(region2, size)); } TEST(AshmemTest, ForkTest) { const size_t size = getpagesize(); std::vector<uint8_t> data(size); Loading libcutils/sockets_test.cpp +0 −2 Original line number Diff line number Diff line Loading @@ -19,8 +19,6 @@ // should be the case for loopback communication, but is not guaranteed. #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <time.h> #include <cutils/sockets.h> Loading Loading
libcutils/Android.bp +20 −17 Original line number Diff line number Diff line Loading @@ -155,23 +155,18 @@ cc_library { "fs_config.cpp", ], }, not_windows: { srcs: libcutils_nonwindows_sources + [ "ashmem-host.cpp", host: { srcs: [ "trace-host.cpp", "ashmem-host.cpp", ], }, not_windows: { srcs: libcutils_nonwindows_sources, }, windows: { host_ldlibs: ["-lws2_32"], srcs: [ "trace-host.cpp", ], enabled: true, cflags: [ "-D_GNU_SOURCE", ], host_ldlibs: ["-lws2_32"], }, android: { sanitize: { Loading Loading @@ -240,6 +235,7 @@ cc_library { cc_defaults { name: "libcutils_test_default", srcs: [ "ashmem_base_test.cpp", "native_handle_test.cpp", "properties_test.cpp", "sockets_test.cpp", Loading Loading @@ -298,20 +294,26 @@ cc_test { cc_defaults { name: "libcutils_test_static_defaults", defaults: ["libcutils_test_default"], static_libs: [ "libc", "libcgrouprc_format", ] + test_libraries + always_static_test_libraries, stl: "libc++_static", require_root: true, target: { android: { static_executable: true, static_libs: [ "libcgrouprc_format", ] + test_libraries + always_static_test_libraries, }, not_windows: { static_libs: test_libraries + always_static_test_libraries, }, windows: { static_libs: [ "libbase", "libcutils", "libcutils_sockets", ], host_ldlibs: ["-lws2_32"], enabled: true, }, }, Loading @@ -319,6 +321,7 @@ cc_defaults { cc_test { name: "libcutils_test_static", host_supported: true, test_suites: ["device-tests"], defaults: ["libcutils_test_static_defaults"], } Loading
libcutils/ashmem-host.cpp +35 −20 Original line number Diff line number Diff line Loading @@ -17,10 +17,13 @@ #include <cutils/ashmem.h> /* * Implementation of the user-space ashmem API for the simulator, which lacks * an ashmem-enabled kernel. See ashmem-dev.c for the real ashmem-based version. * Implementation of the user-space ashmem API for the simulator, which lacks an * ashmem-enabled kernel. See ashmem-dev.c for the real ashmem-based version. A * disk-backed temp file is the best option that is consistently supported * across all host platforms. */ #include <android-base/unique_fd.h> #include <errno.h> #include <fcntl.h> #include <limits.h> Loading @@ -31,8 +34,10 @@ #include <sys/types.h> #include <time.h> #include <unistd.h> #include <utils/Compat.h> #include <memory> using android::base::unique_fd; static bool ashmem_validate_stat(int fd, struct stat* buf) { int result = fstat(fd, buf); Loading @@ -40,15 +45,20 @@ static bool ashmem_validate_stat(int fd, struct stat* buf) { return false; } /* * Check if this is an "ashmem" region. * TODO: This is very hacky, and can easily break. * We need some reliable indicator. */ if (!(buf->st_nlink == 0 && S_ISREG(buf->st_mode))) { // Check if this is an ashmem region. Since there's no such thing on the host, // we can't actually implement that. Check that it's at least a regular file. if (!S_ISREG(buf->st_mode)) { errno = ENOTTY; return false; } // In Win32, unlike Unix, the temp file is not unlinked immediately after // creation. #if !defined(_WIN32) if (buf->st_nlink != 0) { errno = ENOTTY; return false; } #endif return true; } Loading @@ -58,19 +68,24 @@ int ashmem_valid(int fd) { } int ashmem_create_region(const char* /*ignored*/, size_t size) { char pattern[PATH_MAX]; snprintf(pattern, sizeof(pattern), "/tmp/android-ashmem-%d-XXXXXXXXX", getpid()); int fd = mkstemp(pattern); if (fd == -1) return -1; unlink(pattern); // Files returned by tmpfile are automatically removed. std::unique_ptr<FILE, decltype(&fclose)> tmp(tmpfile(), &fclose); if (TEMP_FAILURE_RETRY(ftruncate(fd, size)) == -1) { close(fd); if (!tmp) { return -1; } return fd; int fd = fileno(tmp.get()); if (fd == -1) { return -1; } unique_fd dupfd = unique_fd(dup(fd)); if (dupfd == -1) { return -1; } if (TEMP_FAILURE_RETRY(ftruncate(dupfd, size)) == -1) { return -1; } return dupfd.release(); } int ashmem_set_prot_region(int /*fd*/, int /*prot*/) { Loading
libcutils/ashmem_base_test.cpp 0 → 100644 +63 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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 <unistd.h> #include <android-base/mapped_file.h> #include <android-base/unique_fd.h> #include <cutils/ashmem.h> /* * Tests in AshmemBaseTest are designed to run on Android as well as host * platforms (Linux, Mac, Windows). */ #if defined(_WIN32) static inline size_t getpagesize() { return 4096; } #endif using android::base::unique_fd; TEST(AshmemBaseTest, BasicTest) { const size_t size = getpagesize(); std::vector<uint8_t> data(size); std::generate(data.begin(), data.end(), [n = 0]() mutable { return n++ & 0xFF; }); unique_fd fd = unique_fd(ashmem_create_region(nullptr, size)); ASSERT_TRUE(fd >= 0); ASSERT_TRUE(ashmem_valid(fd)); ASSERT_EQ(size, static_cast<size_t>(ashmem_get_size_region(fd))); std::unique_ptr<android::base::MappedFile> mapped = android::base::MappedFile::FromFd(fd, 0, size, PROT_READ | PROT_WRITE); EXPECT_TRUE(mapped.get() != nullptr); void* region1 = mapped->data(); EXPECT_TRUE(region1 != nullptr); memcpy(region1, data.data(), size); ASSERT_EQ(0, memcmp(region1, data.data(), size)); std::unique_ptr<android::base::MappedFile> mapped2 = android::base::MappedFile::FromFd(fd, 0, size, PROT_READ | PROT_WRITE); EXPECT_TRUE(mapped2.get() != nullptr); void* region2 = mapped2->data(); EXPECT_TRUE(region2 != nullptr); ASSERT_EQ(0, memcmp(region2, data.data(), size)); }
libcutils/ashmem_test.cpp +0 −22 Original line number Diff line number Diff line Loading @@ -69,28 +69,6 @@ void FillData(std::vector<uint8_t>& data) { } } TEST(AshmemTest, BasicTest) { const size_t size = getpagesize(); std::vector<uint8_t> data(size); FillData(data); unique_fd fd; ASSERT_NO_FATAL_FAILURE(TestCreateRegion(size, fd, PROT_READ | PROT_WRITE)); void* region1 = nullptr; ASSERT_NO_FATAL_FAILURE(TestMmap(fd, size, PROT_READ | PROT_WRITE, ®ion1)); memcpy(region1, data.data(), size); ASSERT_EQ(0, memcmp(region1, data.data(), size)); EXPECT_EQ(0, munmap(region1, size)); void *region2; ASSERT_NO_FATAL_FAILURE(TestMmap(fd, size, PROT_READ, ®ion2)); ASSERT_EQ(0, memcmp(region2, data.data(), size)); EXPECT_EQ(0, munmap(region2, size)); } TEST(AshmemTest, ForkTest) { const size_t size = getpagesize(); std::vector<uint8_t> data(size); Loading
libcutils/sockets_test.cpp +0 −2 Original line number Diff line number Diff line Loading @@ -19,8 +19,6 @@ // should be the case for loopback communication, but is not guaranteed. #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <time.h> #include <cutils/sockets.h> Loading