diff options
author | Devin Moore <devinmoore@google.com> | 2023-11-13 22:35:19 +0000 |
---|---|---|
committer | Devin Moore <devinmoore@google.com> | 2023-11-13 22:39:51 +0000 |
commit | 96424c6d697d4c49ab60c43b178c94b1a1ce636f (patch) | |
tree | 7c34838186b38cb08f17b28cc8b8177e4e13ca16 | |
parent | 11e2d034780c4d4ece2a468f235617d96b19e857 (diff) | |
download | libhidl-96424c6d697d4c49ab60c43b178c94b1a1ce636f.tar.gz |
Reapply "Add local impl of mapper for libhidlmemory"
This reverts commit 5410c8c04a03527289f69df063cfe9ea30349d2c.
Test: atest CtsMediaAudioTestCases
Tets: remove android.hidl.memory@1.0-impl.so from device &&
atest CtsMediaAudioTestCases && check for call_once log
Bug: 205764958
Bug: 310700278
Bug: 310680652
Change-Id: Iebaf64882949d5923362f80e79eeed8f8fece7bb
-rw-r--r-- | libhidlmemory/AshmemMemory.h | 61 | ||||
-rw-r--r-- | libhidlmemory/mapping.cpp | 38 |
2 files changed, 97 insertions, 2 deletions
diff --git a/libhidlmemory/AshmemMemory.h b/libhidlmemory/AshmemMemory.h new file mode 100644 index 0000000..ffb9c00 --- /dev/null +++ b/libhidlmemory/AshmemMemory.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2023 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 <android/hidl/memory/1.0/IMemory.h> +#include <hidl/Status.h> +#include <inttypes.h> +#include <log/log.h> +#include <sys/mman.h> + +namespace android { +namespace hardware { +namespace impl { + +using ::android::sp; +using ::android::hardware::hidl_memory; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hidl::memory::V1_0::IMemory; + +struct AshmemMemory : public IMemory { + AshmemMemory(const hidl_memory& memory, void* data) : mMemory(memory), mData(data) {} + + ~AshmemMemory() { munmap(mData, mMemory.size()); } + + // Methods from ::android::hidl::memory::V1_0::IMemory follow. + Return<void*> getPointer() override { return mData; } + Return<uint64_t> getSize() override { return mMemory.size(); } + // NOOPs (since non0remoted memory) + Return<void> update() override { return Void(); } + Return<void> updateRange(uint64_t /*start*/, uint64_t /*length*/) override { return Void(); } + Return<void> read() override { return Void(); } + Return<void> readRange(uint64_t /*start*/, uint64_t /*length*/) override { return Void(); } + Return<void> commit() override { return Void(); } + + private: + // Holding onto hidl_memory reference because it contains + // handle and size, and handle will also be required for + // the remoted case. + hidl_memory mMemory; + + // Mapped memory in process. + void* mData; +}; + +} // namespace impl +} // namespace hardware +} // namespace android diff --git a/libhidlmemory/mapping.cpp b/libhidlmemory/mapping.cpp index 8f0bcf4..3fcc354 100644 --- a/libhidlmemory/mapping.cpp +++ b/libhidlmemory/mapping.cpp @@ -19,6 +19,7 @@ #include <mutex> #include <string> +#include <AshmemMemory.h> #include <hidlmemory/mapping.h> #include <android-base/logging.h> @@ -35,6 +36,33 @@ namespace hardware { static std::map<std::string, sp<IMapper>> gMappersByName; static std::mutex gMutex; +static std::once_flag gOnceFlagLog; + +static sp<IMemory> createAshmemMemory(const hidl_memory& mem) { + if (mem.handle()->numFds == 0) { + return nullptr; + } + + // If ashmem service runs in 32-bit (size_t is uint32_t) and a 64-bit + // client process requests a memory > 2^32 bytes, the size would be + // converted to a 32-bit number in mmap. mmap could succeed but the + // mapped memory's actual size would be smaller than the reported size. + if (mem.size() > SIZE_MAX) { + ALOGE("Cannot map %" PRIu64 " bytes of memory because it is too large.", mem.size()); + android_errorWriteLog(0x534e4554, "79376389"); + return nullptr; + } + + int fd = mem.handle()->data[0]; + void* data = mmap(0, mem.size(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (data == MAP_FAILED) { + // mmap never maps at address zero without MAP_FIXED, so we can avoid + // exposing clients to MAP_FAILED. + return nullptr; + } + + return new impl::AshmemMemory(mem, data); +} static inline sp<IMapper> getMapperService(const std::string& name) { std::unique_lock<std::mutex> _lock(gMutex); @@ -55,8 +83,14 @@ sp<IMemory> mapMemory(const hidl_memory& memory) { sp<IMapper> mapper = getMapperService(memory.name()); if (mapper == nullptr) { - LOG(ERROR) << "Could not fetch mapper for " << memory.name() << " shared memory"; - return nullptr; + if (memory.name() == "ashmem") { + std::call_once(gOnceFlagLog, + [&]() { LOG(INFO) << "Using libhidlmemory mapper for ashmem."; }); + return createAshmemMemory(memory); + } else { + LOG(ERROR) << "Could not fetch mapper for " << memory.name() << " shared memory"; + return nullptr; + } } if (mapper->isRemote()) { |