Snap for 5798008 from 5775907bcca7e98bb25af59e0032ffbea950cb46 to sdk-release
Change-Id: I8d893d948842207a1e6f1a7c85b8d2841f6781fd
diff --git a/base/include/hidl/HidlSupport.h b/base/include/hidl/HidlSupport.h
index adf86a7..c0ae1c0 100644
--- a/base/include/hidl/HidlSupport.h
+++ b/base/include/hidl/HidlSupport.h
@@ -585,8 +585,11 @@
iterator end() { return data()+mSize; }
const_iterator begin() const { return data(); }
const_iterator end() const { return data()+mSize; }
+ iterator find(const T& v) { return std::find(begin(), end(), v); }
+ const_iterator find(const T& v) const { return std::find(begin(), end(), v); }
+ bool contains(const T& v) const { return find(v) != end(); }
-private:
+ private:
details::hidl_pointer<T> mBuffer;
uint32_t mSize;
bool mOwnsBuffer;
diff --git a/libhidlcache/Android.bp b/libhidlcache/Android.bp
deleted file mode 100644
index d28a4f1..0000000
--- a/libhidlcache/Android.bp
+++ /dev/null
@@ -1,71 +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.
-
-cc_library {
- name: "libhidlcache",
- vendor_available: true,
- vndk: {
- enabled: true,
- },
- defaults: ["libhidl-defaults"],
- shared_libs: [
- "libbase",
- "liblog",
- "libutils",
- "libcutils",
- "libhidlbase",
- "libhidlmemory",
- "libhwbinder",
- "libhidltransport",
- "android.hidl.memory@1.0",
- "android.hidl.memory.block@1.0",
- "android.hidl.memory.token@1.0",
- ],
- export_include_dirs: ["include"],
-
- export_shared_lib_headers: [
- "android.hidl.memory@1.0",
- "android.hidl.memory.block@1.0",
- "android.hidl.memory.token@1.0",
- "libhidlbase",
- ],
- srcs: [
- "HidlMemoryCache.cpp",
- "MemoryDealer.cpp",
- "mapping.cpp",
- ],
-}
-
-cc_test {
- name: "libhidlcache_test",
- defaults: ["hidl-gen-defaults"],
-
- shared_libs: [
- "android.hidl.allocator@1.0",
- "android.hidl.memory@1.0",
- "android.hidl.memory.block@1.0",
- "android.hidl.memory.token@1.0",
- "libbase",
- "libcutils",
- "libhidlbase",
- "libhidlmemory",
- "libhidlcache",
- "libhidltransport",
- "libhwbinder",
- "liblog",
- "libutils",
- ],
-
- srcs: ["libhidlcache_test.cpp"],
-}
diff --git a/libhidlcache/HidlCache.h b/libhidlcache/HidlCache.h
deleted file mode 100644
index 39a7b3a..0000000
--- a/libhidlcache/HidlCache.h
+++ /dev/null
@@ -1,143 +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.
- */
-#ifndef ANDROID_HARDWARE_HIDL_CACHE_H
-#define ANDROID_HARDWARE_HIDL_CACHE_H
-
-#include <utils/Log.h>
-
-namespace android {
-namespace hardware {
-
-// A generic cache to map Key to sp<Value>. The cache records are kept with
-// wp<Value>, so that it does not block the Value to be garbage collected
-// when there's no other sp<> externally.
-template <class Key, class Value, class Compare = std::less<Key>>
-class HidlCache : public virtual RefBase {
- using Mutex = std::mutex;
- using Lock = std::lock_guard<Mutex>;
-
- public:
- // A RAII class to manage lock/unlock HidlCache.
- class HidlCacheLock : public virtual RefBase {
- public:
- HidlCacheLock(sp<HidlCache> cache, const Key& key) : mCache(cache), mKey(key) {
- mCache->lock(mKey);
- }
- ~HidlCacheLock() { mCache->unlock(mKey); }
-
- private:
- sp<HidlCache> mCache;
- const Key mKey;
- };
- // lock the IMemory refered by key and keep it alive even if there's no
- // other memory block refers to.
- virtual bool lock(const Key& key);
- virtual sp<Value> unlock(const Key& key);
- virtual bool flush(const Key& key);
- // fetch the sp<Value> with key from cache,
- // make a new instance with fill() if it does not present currently.
- virtual sp<Value> fetch(const Key& key);
- virtual sp<HidlCacheLock> lockGuard(const Key& key) { return new HidlCacheLock(this, key); }
-
- virtual ~HidlCache() {}
-
- protected:
- friend void HidlCacheWhiteBoxTest();
- // This method shall be called with a lock held
- virtual sp<Value> fillLocked(const Key& key) = 0;
-
- // @return nullptr if it does not present currently.
- // @note This method shall be called with a lock held
- virtual sp<Value> getCachedLocked(const Key& key);
- bool cached(Key key) const { return mCached.count(key) > 0; }
- bool locked(Key key) const { return mLocked.count(key) > 0; }
- Mutex mMutex;
-
- std::map<Key, wp<Value>, Compare> mCached;
- std::map<Key, sp<Value>, Compare> mLocked;
-};
-
-template <class Key, class Value, class Compare>
-bool HidlCache<Key, Value, Compare>::lock(const Key& key) {
- {
- Lock lock(mMutex);
- if (cached(key)) {
- sp<Value> im = mCached[key].promote();
- if (im != nullptr) {
- mLocked[key] = im;
- return true;
- } else {
- mCached.erase(key);
- }
- }
- }
- sp<Value> value = fetch(key);
- if (value == nullptr) {
- return false;
- } else {
- Lock lock(mMutex);
- mLocked[key] = value;
- return true;
- }
-}
-
-template <class Key, class Value, class Compare>
-sp<Value> HidlCache<Key, Value, Compare>::unlock(const Key& key) {
- Lock lock(mMutex);
- if (locked(key)) {
- sp<Value> v = mLocked[key];
- mLocked.erase(key);
- return v;
- }
- return nullptr;
-}
-
-template <class Key, class Value, class Compare>
-bool HidlCache<Key, Value, Compare>::flush(const Key& key) {
- Lock lock(mMutex);
- bool contain = cached(key);
- mCached.erase(key);
- return contain;
-}
-
-template <class Key, class Value, class Compare>
-sp<Value> HidlCache<Key, Value, Compare>::getCachedLocked(const Key& key) {
- if (cached(key)) {
- wp<Value> cache = mCached[key];
- sp<Value> mem = cache.promote();
- if (mem != nullptr) {
- return mem;
- } else {
- mCached.erase(key);
- }
- }
- return nullptr;
-}
-
-template <class Key, class Value, class Compare>
-sp<Value> HidlCache<Key, Value, Compare>::fetch(const Key& key) {
- Lock lock(mMutex);
- sp<Value> value = getCachedLocked(key);
-
- if (value == nullptr) {
- value = fillLocked(key);
- }
- return value;
-}
-
-} // namespace hardware
-} // namespace android
-#endif
diff --git a/libhidlcache/HidlMemoryCache.cpp b/libhidlcache/HidlMemoryCache.cpp
deleted file mode 100644
index a23c388..0000000
--- a/libhidlcache/HidlMemoryCache.cpp
+++ /dev/null
@@ -1,127 +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 "HidlMemoryCache"
-#include "HidlMemoryCache.h"
-#include <android/hidl/memory/1.0/IMemory.h>
-#include <android/hidl/memory/token/1.0/IMemoryToken.h>
-#include <hidlmemory/mapping.h>
-#include <sys/mman.h>
-#include <utils/Log.h>
-
-namespace android {
-namespace hardware {
-
-using IMemoryToken = ::android::hidl::memory::token::V1_0::IMemoryToken;
-using IMemory = ::android::hidl::memory::V1_0::IMemory;
-
-class MemoryDecorator : public virtual IMemory {
- public:
- MemoryDecorator(const sp<IMemory>& heap) : mHeap(heap) {}
- virtual ~MemoryDecorator() {}
- Return<void> update() override { return mHeap->update(); }
- Return<void> read() override { return mHeap->read(); }
- Return<void> updateRange(uint64_t start, uint64_t length) override {
- return mHeap->updateRange(start, length);
- }
- Return<void> readRange(uint64_t start, uint64_t length) override {
- return mHeap->readRange(start, length);
- }
- Return<void> commit() override { return mHeap->commit(); }
-
- Return<void*> getPointer() override { return mHeap->getPointer(); }
- Return<uint64_t> getSize() override { return mHeap->getSize(); }
-
- protected:
- sp<IMemory> mHeap;
-};
-
-class MemoryCacheable : public virtual MemoryDecorator {
- public:
- MemoryCacheable(const sp<IMemory>& heap, sp<IMemoryToken> key)
- : MemoryDecorator(heap), mKey(key) {}
- virtual ~MemoryCacheable() { HidlMemoryCache::getInstance()->flush(mKey); }
-
- protected:
- sp<IMemoryToken> mKey;
-};
-
-class MemoryBlockImpl : public virtual IMemory {
- public:
- MemoryBlockImpl(const sp<IMemory>& heap, uint64_t size, uint64_t offset)
- : mHeap(heap), mSize(size), mOffset(offset), mHeapSize(heap->getSize()) {}
- bool validRange(uint64_t start, uint64_t length) {
- return (start + length <= mSize) && (start + length >= start) &&
- (mOffset + mSize <= mHeapSize);
- }
- Return<void> readRange(uint64_t start, uint64_t length) override {
- if (!validRange(start, length)) {
- ALOGE("IMemoryBlock::readRange: out of range");
- return Void();
- }
- return mHeap->readRange(mOffset + start, length);
- }
- Return<void> updateRange(uint64_t start, uint64_t length) override {
- if (!validRange(start, length)) {
- ALOGE("IMemoryBlock::updateRange: out of range");
- return Void();
- }
- return mHeap->updateRange(mOffset + start, length);
- }
- Return<void> read() override { return this->readRange(0, mSize); }
- Return<void> update() override { return this->updateRange(0, mSize); }
- Return<void> commit() override { return mHeap->commit(); }
- Return<uint64_t> getSize() override { return mSize; }
- Return<void*> getPointer() override {
- void* p = mHeap->getPointer();
- return (static_cast<char*>(p) + mOffset);
- }
-
- protected:
- sp<IMemory> mHeap;
- uint64_t mSize;
- uint64_t mOffset;
- uint64_t mHeapSize;
-};
-
-sp<HidlMemoryCache> HidlMemoryCache::getInstance() {
- static sp<HidlMemoryCache> instance = new HidlMemoryCache();
- return instance;
-}
-
-sp<IMemory> HidlMemoryCache::fillLocked(const sp<IMemoryToken>& key) {
- sp<IMemory> memory = nullptr;
- Return<void> ret = key->get(
- [&](const hidl_memory& mem) { memory = new MemoryCacheable(mapMemory(mem), key); });
- if (!ret.isOk()) {
- ALOGE("HidlMemoryCache::fill: cannot IMemoryToken::get.");
- return nullptr;
- }
- mCached[key] = memory;
- return memory;
-}
-
-sp<IMemory> HidlMemoryCache::map(const MemoryBlock& memblk) {
- sp<IMemoryToken> token = memblk.token;
- sp<IMemory> heap = fetch(token);
- if (heap == nullptr) {
- return nullptr;
- }
- return new MemoryBlockImpl(heap, memblk.size, memblk.offset);
-}
-
-} // namespace hardware
-} // namespace android
diff --git a/libhidlcache/HidlMemoryCache.h b/libhidlcache/HidlMemoryCache.h
deleted file mode 100644
index c9a533b..0000000
--- a/libhidlcache/HidlMemoryCache.h
+++ /dev/null
@@ -1,62 +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.
- */
-#ifndef ANDROID_HARDWARD_HIDLMEMORY_CACHE_H
-#define ANDROID_HARDWARD_HIDLMEMORY_CACHE_H
-
-#include <android/hidl/memory/block/1.0/types.h>
-#include <android/hidl/memory/token/1.0/IMemoryToken.h>
-#include <hidl/HidlBinderSupport.h>
-#include <hwbinder/IBinder.h>
-#include <utils/RefBase.h>
-#include "HidlCache.h"
-
-namespace android {
-namespace hardware {
-
-struct IMemoryTokenCompare {
- using IMemoryToken = ::android::hidl::memory::token::V1_0::IMemoryToken;
- bool operator()(const sp<IMemoryToken>& lhs, const sp<IMemoryToken>& rhs) const {
- sp<IBinder> lb = toBinder<IMemoryToken>(lhs);
- sp<IBinder> rb = toBinder<IMemoryToken>(rhs);
- return lb < rb;
- }
-};
-
-// The HidlMemoryCache is a singleton class to provides cache for
-// IMemoryToken => ::android::hidl::memory::V1_0::IMemory
-// It's an abstraction layer on top of the IMapper and supports, but is
-// not limited to, the Ashmem type HidlMemory.
-class HidlMemoryCache
- : public virtual HidlCache<sp<::android::hidl::memory::token::V1_0::IMemoryToken>,
- ::android::hidl::memory::V1_0::IMemory, IMemoryTokenCompare> {
- using IMemoryToken = ::android::hidl::memory::token::V1_0::IMemoryToken;
- using IMemory = ::android::hidl::memory::V1_0::IMemory;
- using MemoryBlock = ::android::hidl::memory::block::V1_0::MemoryBlock;
-
- public:
- virtual sp<IMemory> map(const MemoryBlock& block);
- // get the singleton
- static sp<HidlMemoryCache> getInstance();
-
- protected:
- HidlMemoryCache() {}
- virtual sp<IMemory> fillLocked(const sp<IMemoryToken>& key) override;
-};
-
-} // namespace hardware
-} // namespace android
-
-#endif
diff --git a/libhidlcache/MemoryDealer.cpp b/libhidlcache/MemoryDealer.cpp
deleted file mode 100644
index e5686a7..0000000
--- a/libhidlcache/MemoryDealer.cpp
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * Copyright (C) 2007 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 "MemoryDealer"
-
-#include <hidlcache/MemoryDealer.h>
-#include <hidlmemory/HidlMemoryToken.h>
-#include <hidlmemory/mapping.h>
-
-#include <list>
-
-#include <log/log.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <sys/file.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-using std::string;
-
-namespace android {
-namespace hardware {
-
-class SimpleBestFitAllocator {
- enum { PAGE_ALIGNED = 0x00000001 };
-
- public:
- explicit SimpleBestFitAllocator(size_t size);
- ~SimpleBestFitAllocator();
-
- size_t allocate(size_t size, uint32_t flags = 0);
- status_t deallocate(size_t offset);
- size_t size() const;
- void dump(const char* tag) const;
- void dump(string& res, const char* tag) const;
-
- static size_t getAllocationAlignment() { return kMemoryAlign; }
-
- private:
- struct chunk_t {
- chunk_t(size_t start, size_t size) : start(start), size(size), free(1) {}
- size_t start;
- size_t size : 28;
- int free : 4;
- };
- using List = std::list<chunk_t*>;
- using Iterator = std::list<chunk_t*>::iterator;
- using IteratorConst = std::list<chunk_t*>::const_iterator;
- using Mutex = std::mutex;
- using Lock = std::lock_guard<Mutex>;
-
- ssize_t alloc(size_t size, uint32_t flags);
- chunk_t* dealloc(size_t start);
- void dump_l(const char* tag) const;
- void dump_l(string& res, const char* tag) const;
-
- static const int kMemoryAlign;
- mutable Mutex mLock;
- List mList;
- size_t mHeapSize;
-};
-
-MemoryDealer::MemoryDealer(size_t size) : mAllocator(new SimpleBestFitAllocator(size)) {}
-
-MemoryDealer::~MemoryDealer() {
- delete mAllocator;
-}
-
-ssize_t MemoryDealer::allocateOffset(size_t size) {
- return mAllocator->allocate(size);
-}
-
-void MemoryDealer::deallocate(size_t offset) {
- mAllocator->deallocate(offset);
-}
-
-void MemoryDealer::dump(const char* tag) const {
- mAllocator->dump(tag);
-}
-
-size_t MemoryDealer::getAllocationAlignment() {
- return SimpleBestFitAllocator::getAllocationAlignment();
-}
-
-// align all the memory blocks on a cache-line boundary
-const int SimpleBestFitAllocator::kMemoryAlign = 32;
-
-SimpleBestFitAllocator::SimpleBestFitAllocator(size_t size) {
- size_t pagesize = getpagesize();
- mHeapSize = ((size + pagesize - 1) & ~(pagesize - 1));
-
- chunk_t* node = new chunk_t(0, mHeapSize / kMemoryAlign);
- mList.push_front(node);
-}
-
-SimpleBestFitAllocator::~SimpleBestFitAllocator() {
- while (mList.size() != 0) {
- chunk_t* removed = mList.front();
- mList.pop_front();
-#ifdef __clang_analyzer__
- // Clang static analyzer gets confused in this loop
- // and generates a false positive warning about accessing
- // memory that is already freed.
- // Add an "assert" to avoid the confusion.
- LOG_ALWAYS_FATAL_IF(mList.front() == removed);
-#endif
- delete removed;
- }
-}
-
-size_t SimpleBestFitAllocator::size() const {
- return mHeapSize;
-}
-
-size_t SimpleBestFitAllocator::allocate(size_t size, uint32_t flags) {
- Lock lock(mLock);
- ssize_t offset = alloc(size, flags);
- return offset;
-}
-
-status_t SimpleBestFitAllocator::deallocate(size_t offset) {
- Lock lock(mLock);
- chunk_t const* const freed = dealloc(offset);
- if (freed) {
- return NO_ERROR;
- }
- return NAME_NOT_FOUND;
-}
-
-ssize_t SimpleBestFitAllocator::alloc(size_t size, uint32_t flags) {
- if (size == 0) {
- return 0;
- }
- size = (size + kMemoryAlign - 1) / kMemoryAlign;
- size_t pagesize = getpagesize();
-
- Iterator free_chunk_p = mList.end();
- for (Iterator p = mList.begin(); p != mList.end(); p++) {
- chunk_t* cur = *p;
- int extra = 0;
- if (flags & PAGE_ALIGNED) extra = (-cur->start & ((pagesize / kMemoryAlign) - 1));
-
- // best fit
- if (cur->free && (cur->size >= (size + extra))) {
- if ((free_chunk_p == mList.end()) || (cur->size < (*free_chunk_p)->size)) {
- free_chunk_p = p;
- }
- if (cur->size == size) {
- break;
- }
- }
- }
- if (free_chunk_p != mList.end()) {
- chunk_t* free_chunk = *free_chunk_p;
- const size_t free_size = free_chunk->size;
- free_chunk->free = 0;
- free_chunk->size = size;
- if (free_size > size) {
- int extra = 0;
- if (flags & PAGE_ALIGNED)
- extra = (-free_chunk->start & ((pagesize / kMemoryAlign) - 1));
- if (extra) {
- chunk_t* split = new chunk_t(free_chunk->start, extra);
- free_chunk->start += extra;
- mList.insert(free_chunk_p, split);
- }
-
- ALOGE_IF(
- (flags & PAGE_ALIGNED) && ((free_chunk->start * kMemoryAlign) & (pagesize - 1)),
- "PAGE_ALIGNED requested, but page is not aligned!!!");
-
- const ssize_t tail_free = free_size - (size + extra);
- if (tail_free > 0) {
- chunk_t* split = new chunk_t(free_chunk->start + free_chunk->size, tail_free);
- mList.insert(++free_chunk_p, split);
- }
- }
- return (free_chunk->start) * kMemoryAlign;
- }
- return NO_MEMORY;
-}
-
-SimpleBestFitAllocator::chunk_t* SimpleBestFitAllocator::dealloc(size_t start) {
- start = start / kMemoryAlign;
-
- for (Iterator pos = mList.begin(); pos != mList.end(); pos++) {
- chunk_t* cur = *pos;
- if (cur->start == start) {
- LOG_FATAL_IF(cur->free, "block at offset 0x%08lX of size 0x%08lX already freed",
- cur->start * kMemoryAlign, cur->size * kMemoryAlign);
-
- // merge freed blocks together
- chunk_t* freed = cur;
- cur->free = 1;
- do {
- if (pos != mList.begin()) {
- pos--;
- chunk_t* const p = *pos;
- pos++;
- if (p->free || !cur->size) {
- freed = p;
- p->size += cur->size;
- pos = mList.erase(pos);
- delete cur;
- if (pos == mList.end()) break;
- }
- }
- if (++pos == mList.end()) break;
- cur = *pos;
- } while (cur && cur->free);
-
-#ifndef NDEBUG
- if (!freed->free) {
- dump_l("dealloc (!freed->free)");
- }
-#endif
- LOG_FATAL_IF(!freed->free, "freed block at offset 0x%08lX of size 0x%08lX is not free!",
- freed->start * kMemoryAlign, freed->size * kMemoryAlign);
-
- return freed;
- }
- }
- return nullptr;
-}
-
-void SimpleBestFitAllocator::dump(const char* tag) const {
- Lock lock(mLock);
- dump_l(tag);
-}
-
-void SimpleBestFitAllocator::dump_l(const char* tag) const {
- string result;
- dump_l(result, tag);
- ALOGD("%s", result.c_str());
-}
-
-void SimpleBestFitAllocator::dump(string& result, const char* tag) const {
- Lock lock(mLock);
- dump_l(result, tag);
-}
-
-void SimpleBestFitAllocator::dump_l(string& result, const char* tag) const {
- size_t size = 0;
- int32_t i = 0;
- const size_t SIZE = 256;
- char buffer[SIZE];
- snprintf(buffer, SIZE, " %s (%p, size=%u)\n", tag, this, (unsigned int)mHeapSize);
-
- result.append(buffer);
-
- for (IteratorConst pos = mList.begin(); pos != mList.end(); pos++) {
- chunk_t const* cur = *pos;
-
- if (!cur->free) size += cur->size * kMemoryAlign;
-
- i++;
- }
- snprintf(buffer, SIZE, " size allocated: %u (%u KB)\n", int(size), int(size / 1024));
- result.append(buffer);
-}
-
-bool HidlMemoryDealer::isOk(const MemoryBlock& memblk) {
- return memblk.token != nullptr;
-}
-
-sp<::android::hidl::memory::V1_0::IMemory> HidlMemoryDealer::heap() {
- return mHeap;
-}
-
-// The required heap size alignment is 4096 bytes
-static const uint64_t kHeapSizeAlignment = (0x1ULL << 12);
-
-sp<HidlMemoryDealer> HidlMemoryDealer::getInstance(const hidl_memory& mem) {
- uint64_t msk = (kHeapSizeAlignment - 1);
- if (mem.size() & msk || !(mem.size() & ~msk)) {
- ALOGE("size is not aligned to %x", static_cast<uint32_t>(kHeapSizeAlignment));
- return nullptr;
- }
- sp<IMemory> heap = mapMemory(mem);
- if (heap == nullptr) {
- ALOGE("fail to mapMemory");
- return nullptr;
- }
- return new HidlMemoryDealer(heap, mem);
-}
-
-HidlMemoryDealer::HidlMemoryDealer(sp<IMemory> heap, const hidl_memory& mem)
- : MemoryDealer(heap->getSize()),
- mHeap(heap),
- mToken(new HidlMemoryToken(HidlMemory::getInstance(mem))) {}
-
-::android::hidl::memory::block::V1_0::MemoryBlock HidlMemoryDealer::allocate(size_t size) {
- MemoryBlock memblk = {nullptr, 0xFFFFFFFFULL, 0xFFFFFFFFULL};
- ssize_t offset = allocateOffset(size);
- if (offset >= 0) {
- memblk.token = mToken;
- memblk.size = size;
- memblk.offset = offset;
- }
- return memblk;
-}
-
-}; // namespace hardware
-}; // namespace android
diff --git a/libhidlcache/include/hidlcache/MemoryDealer.h b/libhidlcache/include/hidlcache/MemoryDealer.h
deleted file mode 100644
index fceed83..0000000
--- a/libhidlcache/include/hidlcache/MemoryDealer.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-#ifndef ANDROID_HIDL_MEMORY_DEALER_H
-#define ANDROID_HIDL_MEMORY_DEALER_H
-
-#include <android/hidl/memory/1.0/IMemory.h>
-#include <android/hidl/memory/block/1.0/types.h>
-#include <stdint.h>
-#include <sys/types.h>
-namespace android {
-namespace hardware {
-
-class SimpleBestFitAllocator;
-
-// MemoryDealer allocates/deallocates blocks from a continuous memory region.
-// It operates on size and offset and does not depend on any specific data types.
-class MemoryDealer : public RefBase {
- public:
- /// Allocate a block with size. The allocated block is identified with an
- /// offset. For example:
- /// ssize_t K = dealer->allocateOffset(size);
- /// On success, K is positive and points to a subregion K ~ (K+size-1) in the heap.
- /// It's negative if the allocation fails.
- virtual ssize_t allocateOffset(size_t size);
- /// @param offset It points to the block that allocated with allocateOffset previously.
- virtual void deallocate(size_t offset);
- /// @param tag a string tag used to mark the dump message
- virtual void dump(const char* tag) const;
-
- // allocations are aligned to some value. return that value so clients can account for it.
- static size_t getAllocationAlignment();
-
- MemoryDealer(size_t size);
- virtual ~MemoryDealer();
-
- protected:
- SimpleBestFitAllocator* mAllocator;
-};
-
-// It extends the generic MemoryDealer and uses
-// - sp<IMemory> to represent the main memory region.
-// - MemoryBlock to represent the the block to allocate/deallocate
-class HidlMemoryDealer : public MemoryDealer {
- using IMemory = ::android::hidl::memory::V1_0::IMemory;
- using IMemoryToken = ::android::hidl::memory::token::V1_0::IMemoryToken;
- using MemoryBlock = ::android::hidl::memory::block::V1_0::MemoryBlock;
-
- public:
- static bool isOk(const MemoryBlock& memblk);
- /// @param memory The memory size must align to 4096 bytes
- static sp<HidlMemoryDealer> getInstance(const hidl_memory& memory);
- virtual MemoryBlock allocate(size_t size);
- virtual sp<IMemory> heap();
-
- protected:
- /// @param heap It must be acquired with mapMemory(memory) with its
- /// argument corresponds to the 2nd argument passed to HidlMemoryDealer.
- HidlMemoryDealer(sp<IMemory> heap, const hidl_memory& memory);
- sp<IMemory> mHeap;
- sp<IMemoryToken> mToken;
-};
-
-}; // namespace hardware
-}; // namespace android
-
-#endif // ANDROID_HIDL_MEMORY_DEALER_H
diff --git a/libhidlcache/include/hidlcache/mapping.h b/libhidlcache/include/hidlcache/mapping.h
deleted file mode 100644
index 972b7b5..0000000
--- a/libhidlcache/include/hidlcache/mapping.h
+++ /dev/null
@@ -1,54 +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.
- */
-#ifndef ANDROID_HARDWARE_CACHE_MAPPING_H
-#define ANDROID_HARDWARE_CACHE_MAPPING_H
-
-#include <android/hidl/memory/1.0/IMemory.h>
-#include <android/hidl/memory/block/1.0/types.h>
-#include <android/hidl/memory/token/1.0/IMemoryToken.h>
-
-namespace android {
-namespace hardware {
-
-/**
- * Returns the IMemory instance corresponding to a MemoryBlock. The heap that
- * a MemoryBlock belongs to is stored in an internal cache to reduce the number
- * of invocations to the mapMemory(hidl_memory)
- *
- * Note, a cache entry is maintained by reference count and may be flushed when
- * the count decrease to zero. Performance critical part that does not want its
- * caches to be flushed can use HidlMemoryCacheLock.
- */
-sp<::android::hidl::memory::V1_0::IMemory> mapMemory(
- const ::android::hidl::memory::block::V1_0::MemoryBlock& block);
-
-/**
- * Internally, there's a cache pool to keep IMemory instances for heap regions
- * that are referred by the MemoryBlock. During development, this
- * lockMemoryCache(...) method helps to diagnosis whether the cache is effective
- * for a specific key. It returns a RAII object used to lock an IMemory instance
- * referred by the key and keep it alive even if the instance is not referred by
- * any MemoryBlock. If the cache in interest is already effective. It won't differ
- * much in performance w/ wo/ the lockMemoryCache()
- *
- * @note An IMemory instance that is returned from the mapMemory() is
- * initialized in an unlocked state.
- */
-sp<RefBase> lockMemoryCache(const sp<::android::hidl::memory::token::V1_0::IMemoryToken> key);
-
-} // namespace hardware
-} // namespace android
-#endif
diff --git a/libhidlcache/libhidlcache_test.cpp b/libhidlcache/libhidlcache_test.cpp
deleted file mode 100644
index e514460..0000000
--- a/libhidlcache/libhidlcache_test.cpp
+++ /dev/null
@@ -1,159 +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 "hidl-cache-test"
-
-#include <android/hidl/allocator/1.0/IAllocator.h>
-#include <android/hidl/memory/1.0/IMemory.h>
-#include <android/hidl/memory/token/1.0/IMemoryToken.h>
-#include <gtest/gtest.h>
-#include <hidlcache/MemoryDealer.h>
-#include <hidlcache/mapping.h>
-#include <hidlmemory/HidlMemoryToken.h>
-#include <hidlmemory/mapping.h>
-#include "HidlMemoryCache.h"
-
-#define EXPECT_OK(__ret__) EXPECT_TRUE(isOk(__ret__))
-
-template <typename T>
-static inline ::testing::AssertionResult isOk(const ::android::hardware::Return<T>& ret) {
- return ret.isOk() ? (::testing::AssertionSuccess() << ret.description())
- : (::testing::AssertionFailure() << ret.description());
-}
-
-namespace android {
-
-namespace hardware {
-void HidlCacheWhiteBoxTest() {
- using ::android::hardware::HidlMemoryCache;
- using ::android::hardware::HidlMemoryToken;
- using ::android::hidl::allocator::V1_0::IAllocator;
- using ::android::hidl::memory::V1_0::IMemory;
- using ::android::hidl::memory::token::V1_0::IMemoryToken;
- using ::android::hidl::memory::block::V1_0::MemoryBlock;
-
- sp<IAllocator> ashmemAllocator;
-
- ashmemAllocator = IAllocator::getService("ashmem");
- ASSERT_NE(nullptr, ashmemAllocator.get());
- ASSERT_TRUE(ashmemAllocator->isRemote()); // allocator is always remote
-
- sp<HidlMemory> mem;
- EXPECT_OK(ashmemAllocator->allocate(1024, [&](bool success, const hidl_memory& _mem) {
- ASSERT_TRUE(success);
- mem = HidlMemory::getInstance(_mem);
- }));
-
- sp<IMemoryToken> token = new HidlMemoryToken(mem);
-
- MemoryBlock blk = {token, 0x200 /* size */, 0x100 /* offset */};
- sp<IMemoryToken> mtoken = blk.token;
- mtoken->get([&](const hidl_memory& mem) { sp<IMemory> memory = mapMemory(mem); });
-
- sp<HidlMemoryCache> cache = HidlMemoryCache::getInstance();
- EXPECT_FALSE(cache->cached(token));
-
- MemoryBlock blk2 = {token, 0x200 /* size */, 0x300 /* offset */};
-
- EXPECT_FALSE(cache->cached(token));
-
- {
- sp<IMemory> mem1 = cache->fetch(token);
- EXPECT_TRUE(cache->cached(token));
- EXPECT_NE(nullptr, cache->getCachedLocked(token).get());
- sp<IMemory> mem2 = cache->fetch(token);
- EXPECT_TRUE(cache->cached(token));
- EXPECT_NE(nullptr, cache->getCachedLocked(token).get());
- }
- EXPECT_FALSE(cache->cached(token));
- {
- sp<IMemory> mem1 = mapMemory(blk);
- EXPECT_TRUE(cache->cached(token));
- EXPECT_NE(nullptr, cache->getCachedLocked(token).get());
- uint8_t* data = static_cast<uint8_t*>(static_cast<void*>(mem1->getPointer()));
- EXPECT_NE(nullptr, data);
- }
- {
- sp<IMemory> mem2 = mapMemory(blk);
- EXPECT_TRUE(cache->cached(token));
- EXPECT_NE(nullptr, cache->getCachedLocked(token).get());
- }
- EXPECT_FALSE(cache->cached(token));
- EXPECT_TRUE(cache->lock(token));
- EXPECT_TRUE(cache->cached(token));
- EXPECT_NE(nullptr, cache->getCachedLocked(token).get());
- EXPECT_TRUE(cache->unlock(token));
- EXPECT_FALSE(cache->cached(token));
-}
-} // namespace hardware
-
-class HidlCacheTest : public ::testing::Test {};
-
-TEST_F(HidlCacheTest, TestAll) {
- hardware::HidlCacheWhiteBoxTest();
-}
-
-TEST_F(HidlCacheTest, MemoryDealer) {
- using ::android::hardware::HidlMemory;
- using ::android::hardware::hidl_memory;
- using ::android::hardware::HidlMemoryDealer;
- using ::android::hidl::allocator::V1_0::IAllocator;
- using ::android::hidl::memory::block::V1_0::MemoryBlock;
-
- sp<IAllocator> ashmemAllocator;
-
- ashmemAllocator = IAllocator::getService("ashmem");
- sp<HidlMemory> m1;
- sp<HidlMemory> m2;
- // test MemoryDealer
- EXPECT_OK(ashmemAllocator->allocate(2048, [&m1](bool success, const hidl_memory& mem) {
- ASSERT_TRUE(success);
- m1 = HidlMemory::getInstance(mem);
- }));
-
- EXPECT_OK(ashmemAllocator->allocate(4096, [&m2](bool success, const hidl_memory& mem) {
- ASSERT_TRUE(success);
- m2 = HidlMemory::getInstance(mem);
- }));
-
- sp<HidlMemoryDealer> dealer;
-
- // m1 does not statisfy the alignment requirement and should fail.
- dealer = HidlMemoryDealer::getInstance(*m1);
- EXPECT_EQ(nullptr, dealer.get());
-
- dealer = HidlMemoryDealer::getInstance(*m2);
- EXPECT_NE(nullptr, dealer.get());
-
- EXPECT_EQ(dealer->heap()->getSize(), 4096ULL);
- MemoryBlock blk = dealer->allocate(1024);
- EXPECT_TRUE(HidlMemoryDealer::isOk(blk));
- MemoryBlock blk2 = dealer->allocate(2048);
- EXPECT_TRUE(HidlMemoryDealer::isOk(blk2));
-
- MemoryBlock blk3 = dealer->allocate(2048);
- EXPECT_FALSE(HidlMemoryDealer::isOk(blk3));
- dealer->deallocate(blk2.offset);
- blk3 = dealer->allocate(2048);
- EXPECT_TRUE(HidlMemoryDealer::isOk(blk3));
-}
-
-int main(int argc, char** argv) {
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
-
-} // namespace android
\ No newline at end of file
diff --git a/libhidlcache/mapping.cpp b/libhidlcache/mapping.cpp
deleted file mode 100644
index 2a23e6f..0000000
--- a/libhidlcache/mapping.cpp
+++ /dev/null
@@ -1,47 +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 "libhidlmemory"
-
-#include <map>
-#include <mutex>
-#include <string>
-
-#include <hidlmemory/mapping.h>
-
-#include <android-base/logging.h>
-#include <hidl/HidlSupport.h>
-#include "HidlMemoryCache.h"
-
-using android::hardware::HidlMemoryCache;
-using android::hidl::memory::block::V1_0::MemoryBlock;
-using android::hidl::memory::token::V1_0::IMemoryToken;
-using android::hidl::memory::V1_0::IMemory;
-
-namespace android {
-namespace hardware {
-
-sp<IMemory> mapMemory(const ::android::hidl::memory::block::V1_0::MemoryBlock& block) {
- sp<HidlMemoryCache> c = HidlMemoryCache::getInstance();
- return c->map(block);
-}
-
-sp<RefBase> lockMemoryCache(const sp<::android::hidl::memory::token::V1_0::IMemoryToken> key) {
- sp<HidlMemoryCache> c = HidlMemoryCache::getInstance();
- return c->lockGuard(key);
-}
-
-} // namespace hardware
-} // namespace android
diff --git a/test_main.cpp b/test_main.cpp
index af29f84..7b6781a 100644
--- a/test_main.cpp
+++ b/test_main.cpp
@@ -350,6 +350,41 @@
EXPECT_NE(oldPointer, noCopies.data());
}
+TEST_F(LibHidlTest, VecFindTest) {
+ using android::hardware::hidl_vec;
+ hidl_vec<int32_t> hv1 = {10, 20, 30, 40};
+ const hidl_vec<int32_t> hv2 = {1, 2, 3, 4};
+
+ auto it = hv1.find(20);
+ EXPECT_EQ(20, *it);
+ *it = 21;
+ EXPECT_EQ(21, *it);
+ it = hv1.find(20);
+ EXPECT_EQ(hv1.end(), it);
+ it = hv1.find(21);
+ EXPECT_EQ(21, *it);
+
+ auto cit = hv2.find(4);
+ EXPECT_EQ(4, *cit);
+}
+
+TEST_F(LibHidlTest, VecContainsTest) {
+ using android::hardware::hidl_vec;
+ hidl_vec<int32_t> hv1 = {10, 20, 30, 40};
+ const hidl_vec<int32_t> hv2 = {0, 1, 2, 3, 4};
+
+ EXPECT_TRUE(hv1.contains(10));
+ EXPECT_TRUE(hv1.contains(40));
+ EXPECT_FALSE(hv1.contains(1));
+ EXPECT_FALSE(hv1.contains(0));
+ EXPECT_TRUE(hv2.contains(0));
+ EXPECT_FALSE(hv2.contains(10));
+
+ hv1[0] = 11;
+ EXPECT_FALSE(hv1.contains(10));
+ EXPECT_TRUE(hv1.contains(11));
+}
+
TEST_F(LibHidlTest, ArrayTest) {
using android::hardware::hidl_array;
int32_t array[] = {5, 6, 7};
diff --git a/transport/base/1.0/vts/functional/Android.bp b/transport/base/1.0/vts/functional/Android.bp
index f0bd45c..fb9af33 100644
--- a/transport/base/1.0/vts/functional/Android.bp
+++ b/transport/base/1.0/vts/functional/Android.bp
@@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-
cc_test {
name: "vts_ibase_test",
srcs: [
@@ -29,6 +28,10 @@
"libhwbinder",
"liblog",
"libutils",
+ "libprotobuf-cpp-lite",
+ "libhidl-gen-utils",
+ ],
+ static_libs: [
+ "libinit_test_utils",
],
}
-
diff --git a/transport/base/1.0/vts/functional/vts_ibase_test.cpp b/transport/base/1.0/vts/functional/vts_ibase_test.cpp
index 6d66042..b77b2ad 100644
--- a/transport/base/1.0/vts/functional/vts_ibase_test.cpp
+++ b/transport/base/1.0/vts/functional/vts_ibase_test.cpp
@@ -13,17 +13,32 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#define LOG_TAG "vts_ibase_test"
+#include <algorithm>
#include <functional>
#include <map>
+#include <mutex>
#include <string>
+#include <thread>
+#include <vector>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
#include <android/hidl/base/1.0/IBase.h>
#include <android/hidl/manager/1.0/IServiceManager.h>
#include <gtest/gtest.h>
+#include <hidl-util/FqInstance.h>
#include <hidl/HidlBinderSupport.h>
#include <hidl/ServiceManagement.h>
+#include <init-test-utils/service_utils.h>
+using android::FqInstance;
+using android::FQName;
+using android::sp;
+using android::wp;
+using android::base::Result;
using android::hardware::hidl_array;
using android::hardware::hidl_death_recipient;
using android::hardware::hidl_handle;
@@ -33,8 +48,8 @@
using android::hardware::toBinder;
using android::hidl::base::V1_0::IBase;
using android::hidl::manager::V1_0::IServiceManager;
-using android::sp;
-using android::wp;
+using android::init::ServiceInterfacesMap;
+using PidInterfacesMap = std::map<pid_t, std::set<FqInstance>>;
template <typename T>
static inline ::testing::AssertionResult isOk(const ::android::hardware::Return<T>& ret) {
@@ -47,8 +62,40 @@
struct Hal {
sp<IBase> service;
std::string name; // space separated list of android.hidl.foo@1.0::IFoo/instance-name
+ FqInstance fq_instance;
};
+template <typename T>
+std::string FqInstancesToString(const T& instances) {
+ std::set<std::string> instance_strings;
+ for (const FqInstance& instance : instances) {
+ instance_strings.insert(instance.string());
+ }
+ return android::base::Join(instance_strings, "\n");
+}
+
+pid_t GetServiceDebugPid(const std::string& service) {
+ return android::base::GetIntProperty("init.svc_debug_pid." + service, 0);
+}
+
+std::map<std::string, std::vector<Hal>> gDeclaredServiceHalMap;
+std::mutex gDeclaredServiceHalMapMutex;
+
+void GetHal(const std::string& service, const FqInstance& instance) {
+ if (instance.getFqName() == android::gIBaseFqName) {
+ return;
+ }
+
+ sp<IBase> hal = android::hardware::details::getRawServiceInternal(
+ instance.getFqName().string(), instance.getInstance(), true /*retry*/,
+ false /*getStub*/);
+ // Add to gDeclaredServiceHalMap if getRawServiceInternal() returns (even if
+ // the returned HAL is null). getRawServiceInternal() won't return if the
+ // HAL is in the VINTF but unable to start.
+ std::lock_guard<std::mutex> guard(gDeclaredServiceHalMapMutex);
+ gDeclaredServiceHalMap[service].push_back(Hal{.service = hal, .fq_instance = instance});
+}
+
class VtsHalBaseV1_0TargetTest : public ::testing::Test {
public:
virtual void SetUp() override {
@@ -86,7 +133,7 @@
// include all the names this is registered as for error messages
iter->second.name += " " + strName;
} else {
- all_hals_.insert(iter, {binder, Hal{service, strName}});
+ all_hals_.insert(iter, {binder, Hal{.service = service, .name = strName}});
}
}
}));
@@ -100,6 +147,25 @@
}
}
+ PidInterfacesMap GetPidInterfacesMap() {
+ PidInterfacesMap result;
+ EXPECT_OK(default_manager_->debugDump([&result](const auto& list) {
+ for (const auto& debug_info : list) {
+ if (debug_info.pid != static_cast<int32_t>(IServiceManager::PidConstant::NO_PID)) {
+ FQName fqName;
+ ASSERT_TRUE(fqName.setTo(debug_info.interfaceName.c_str()))
+ << "Unable to parse interface: '" << debug_info.interfaceName.c_str();
+ FqInstance fqInstance;
+ ASSERT_TRUE(fqInstance.setTo(fqName, debug_info.instanceName.c_str()));
+ if (fqInstance.getFqName() != android::gIBaseFqName) {
+ result[debug_info.pid].insert(fqInstance);
+ }
+ }
+ }
+ }));
+ return result;
+ }
+
// default service manager
sp<IServiceManager> default_manager_;
@@ -165,6 +231,76 @@
});
}
+TEST_F(VtsHalBaseV1_0TargetTest, ServiceProvidesAndDeclaresTheSameInterfaces) {
+ Result<ServiceInterfacesMap> service_interfaces_map =
+ android::init::GetOnDeviceServiceInterfacesMap();
+ ASSERT_TRUE(service_interfaces_map) << service_interfaces_map.error();
+
+ // Attempt to get handles to all known declared interfaces. This will cause
+ // any non-running lazy HALs to start up.
+ // Results are saved in gDeclaredServiceHalMap.
+ for (const auto& [service, declared_interfaces] : *service_interfaces_map) {
+ if (declared_interfaces.empty()) {
+ LOG(INFO) << "Service '" << service << "' does not declare any interfaces.";
+ }
+ for (const auto& instance : declared_interfaces) {
+ std::thread(GetHal, service, instance).detach();
+ }
+ }
+ // Allow the threads 5 seconds to attempt to get each HAL. Any HAL whose
+ // thread is stuck during retrieval is excluded from this test.
+ sleep(5);
+
+ std::lock_guard<std::mutex> guard(gDeclaredServiceHalMapMutex);
+ PidInterfacesMap pid_interfaces_map = GetPidInterfacesMap();
+
+ // For each service that had at least one thread return from attempting to
+ // retrieve a HAL:
+ for (const auto& [service, hals] : gDeclaredServiceHalMap) {
+ // Assert that the service is running.
+ pid_t pid = GetServiceDebugPid(service);
+ ASSERT_NE(pid, 0) << "Service '" << service << "' is not running.";
+
+ std::set<FqInstance> declared_interfaces;
+ for (const auto& hal : hals) {
+ declared_interfaces.insert(hal.fq_instance);
+ }
+
+ // Warn for any threads that were stuck when attempting to retrieve a
+ // HAL.
+ std::vector<FqInstance> missing_declared_interfaces;
+ std::set_difference((*service_interfaces_map)[service].begin(),
+ (*service_interfaces_map)[service].end(), declared_interfaces.begin(),
+ declared_interfaces.end(),
+ std::back_inserter(missing_declared_interfaces));
+ if (!missing_declared_interfaces.empty()) {
+ LOG(WARNING)
+ << "Service '" << service
+ << "' declares interfaces that are present in the VINTF but unable to start:"
+ << std::endl
+ << FqInstancesToString(missing_declared_interfaces);
+ }
+
+ // Expect that the set of interfaces running at this PID is the same as
+ // the set of interfaces declared by this service.
+ std::set<FqInstance> served_interfaces = pid_interfaces_map[pid];
+ std::vector<FqInstance> served_declared_diff;
+ std::set_symmetric_difference(declared_interfaces.begin(), declared_interfaces.end(),
+ served_interfaces.begin(), served_interfaces.end(),
+ std::back_inserter(served_declared_diff));
+
+ EXPECT_TRUE(served_declared_diff.empty())
+ << "Service '" << service << "' serves and declares different interfaces."
+ << std::endl
+ << " Served:" << std::endl
+ << FqInstancesToString(served_interfaces) << std::endl
+ << " Declared: " << std::endl
+ << FqInstancesToString(declared_interfaces) << std::endl
+ << " Difference: " << std::endl
+ << FqInstancesToString(served_declared_diff);
+ }
+}
+
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
diff --git a/transport/memory/1.0/default/HidlFetch.cpp b/transport/memory/1.0/default/HidlFetch.cpp
index d47cf97..a636e03 100644
--- a/transport/memory/1.0/default/HidlFetch.cpp
+++ b/transport/memory/1.0/default/HidlFetch.cpp
@@ -16,9 +16,11 @@
#include "HidlFetch.h"
+#include <string_view>
+
#include "AshmemMapper.h"
-static std::string kAshmemMemoryName = "ashmem";
+static constexpr std::string_view kAshmemMemoryName = "ashmem";
namespace android {
namespace hidl {