Merge "Allow setting a minimum scheduler policy for a service."
diff --git a/base/include/hidl/HidlSupport.h b/base/include/hidl/HidlSupport.h
index d7c3b83..3f45afd 100644
--- a/base/include/hidl/HidlSupport.h
+++ b/base/include/hidl/HidlSupport.h
@@ -316,6 +316,27 @@
*this = other;
}
+ template <typename InputIterator,
+ typename = typename std::enable_if<std::is_convertible<
+ typename std::iterator_traits<InputIterator>::iterator_category,
+ std::input_iterator_tag>::value>::type>
+ hidl_vec(InputIterator first, InputIterator last) : mOwnsBuffer(true) {
+ auto size = std::distance(first, last);
+ if (size > static_cast<int64_t>(UINT32_MAX)) {
+ details::logAlwaysFatal("hidl_vec can't hold more than 2^32 elements.");
+ }
+ if (size < 0) {
+ details::logAlwaysFatal("size can't be negative.");
+ }
+ mSize = static_cast<uint32_t>(size);
+ mBuffer = new T[mSize];
+
+ size_t idx = 0;
+ for (; first != last; ++first) {
+ mBuffer[idx++] = static_cast<T>(*first);
+ }
+ }
+
~hidl_vec() {
if (mOwnsBuffer) {
delete[] mBuffer;
diff --git a/test_main.cpp b/test_main.cpp
index bce9294..1f2f845 100644
--- a/test_main.cpp
+++ b/test_main.cpp
@@ -262,6 +262,30 @@
EXPECT_TRUE(hv1 != hv3);
}
+TEST_F(LibHidlTest, VecRangeCtorTest) {
+ struct ConvertibleType {
+ int val;
+
+ explicit ConvertibleType(int val) : val(val) {}
+ explicit operator int() const { return val; }
+ bool operator==(const int& other) const { return val == other; }
+ };
+
+ std::vector<ConvertibleType> input{
+ ConvertibleType(1), ConvertibleType(2), ConvertibleType(3),
+ };
+
+ android::hardware::hidl_vec<int> hv(input.begin(), input.end());
+
+ EXPECT_EQ(input.size(), hv.size());
+ int sum = 0;
+ for (unsigned i = 0; i < input.size(); i++) {
+ EXPECT_EQ(input[i], hv[i]);
+ sum += hv[i];
+ }
+ EXPECT_EQ(sum, 1 + 2 + 3);
+}
+
TEST_F(LibHidlTest, ArrayTest) {
using android::hardware::hidl_array;
int32_t array[] = {5, 6, 7};
diff --git a/transport/ServiceManagement.cpp b/transport/ServiceManagement.cpp
index 0b7ec34..8be2c76 100644
--- a/transport/ServiceManagement.cpp
+++ b/transport/ServiceManagement.cpp
@@ -248,21 +248,20 @@
}
struct PassthroughServiceManager : IServiceManager {
- Return<sp<IBase>> get(const hidl_string& fqName,
- const hidl_string& name) override {
- std::string stdFqName(fqName.c_str());
-
+ static void openLibs(const std::string& fqName,
+ std::function<bool /* continue */(void* /* handle */,
+ const std::string& /* lib */, const std::string& /* sym */)> eachLib) {
//fqName looks like android.hardware.foo@1.0::IFoo
- size_t idx = stdFqName.find("::");
+ size_t idx = fqName.find("::");
if (idx == std::string::npos ||
- idx + strlen("::") + 1 >= stdFqName.size()) {
+ idx + strlen("::") + 1 >= fqName.size()) {
LOG(ERROR) << "Invalid interface name passthrough lookup: " << fqName;
- return nullptr;
+ return;
}
- std::string packageAndVersion = stdFqName.substr(0, idx);
- std::string ifaceName = stdFqName.substr(idx + strlen("::"));
+ std::string packageAndVersion = fqName.substr(0, idx);
+ std::string ifaceName = fqName.substr(idx + strlen("::"));
const std::string prefix = packageAndVersion + "-impl";
const std::string sym = "HIDL_FETCH_" + ifaceName;
@@ -270,9 +269,6 @@
const int dlMode = RTLD_LAZY;
void *handle = nullptr;
- // TODO: lookup in VINTF instead
- // TODO(b/34135607): Remove HAL_LIBRARY_PATH_SYSTEM
-
dlerror(); // clear
for (const std::string &path : {
@@ -291,31 +287,41 @@
continue;
}
- IBase* (*generator)(const char* name);
- *(void **)(&generator) = dlsym(handle, sym.c_str());
- if(!generator) {
- const char* error = dlerror();
- LOG(ERROR) << "Passthrough lookup opened " << lib
- << " but could not find symbol " << sym << ": "
- << (error == nullptr ? "unknown error" : error);
- dlclose(handle);
- continue;
+ if (!eachLib(handle, lib, sym)) {
+ return;
}
-
- IBase *interface = (*generator)(name.c_str());
-
- if (interface == nullptr) {
- dlclose(handle);
- continue; // this module doesn't provide this instance name
- }
-
- registerReference(fqName, name);
-
- return interface;
}
}
+ }
- return nullptr;
+ Return<sp<IBase>> get(const hidl_string& fqName,
+ const hidl_string& name) override {
+ sp<IBase> ret = nullptr;
+
+ openLibs(fqName, [&](void* handle, const std::string &lib, const std::string &sym) {
+ IBase* (*generator)(const char* name);
+ *(void **)(&generator) = dlsym(handle, sym.c_str());
+ if(!generator) {
+ const char* error = dlerror();
+ LOG(ERROR) << "Passthrough lookup opened " << lib
+ << " but could not find symbol " << sym << ": "
+ << (error == nullptr ? "unknown error" : error);
+ dlclose(handle);
+ return true;
+ }
+
+ ret = (*generator)(name.c_str());
+
+ if (ret == nullptr) {
+ dlclose(handle);
+ return true; // this module doesn't provide this instance name
+ }
+
+ registerReference(fqName, name);
+ return false;
+ });
+
+ return ret;
}
Return<bool> add(const hidl_string& /* name */,
@@ -406,6 +412,14 @@
namespace details {
+void preloadPassthroughService(const std::string &descriptor) {
+ PassthroughServiceManager::openLibs(descriptor,
+ [&](void* /* handle */, const std::string& /* lib */, const std::string& /* sym */) {
+ // do nothing
+ return true; // open all libs
+ });
+}
+
struct Waiter : IServiceNotification {
Return<void> onRegistration(const hidl_string& /* fqName */,
const hidl_string& /* name */,
diff --git a/transport/allocator/1.0/IAllocator.hal b/transport/allocator/1.0/IAllocator.hal
index 814c69d..6f531dd 100644
--- a/transport/allocator/1.0/IAllocator.hal
+++ b/transport/allocator/1.0/IAllocator.hal
@@ -29,4 +29,14 @@
* @return memory Unmapped memory object.
*/
allocate(uint64_t size) generates (bool success, memory mem);
+
+ /**
+ * Return memory must have instance name corresponding to this type of memory.
+ *
+ * @param size Size of memory to allocate in bytes.
+ * @param count Number of memory instances to allocate.
+ * @return success Whether allocation succeeded (returns false if any allocation failed).
+ * @return batch Unmapped memory objects.
+ */
+ batchAllocate(uint64_t size, uint64_t count) generates (bool success, vec<memory> batch);
};
\ No newline at end of file
diff --git a/transport/allocator/1.0/default/AshmemAllocator.cpp b/transport/allocator/1.0/default/AshmemAllocator.cpp
index ce6dbf7..0bd4f81 100644
--- a/transport/allocator/1.0/default/AshmemAllocator.cpp
+++ b/transport/allocator/1.0/default/AshmemAllocator.cpp
@@ -14,6 +14,9 @@
* limitations under the License.
*/
+#define LOG_TAG "AshmemAllocator"
+#include <android-base/logging.h>
+
#include "AshmemAllocator.h"
#include <cutils/ashmem.h>
@@ -24,21 +27,70 @@
namespace V1_0 {
namespace implementation {
-// Methods from ::android::hidl::allocator::V1_0::IAllocator follow.
-Return<void> AshmemAllocator::allocate(uint64_t size, allocate_cb _hidl_cb) {
+static hidl_memory allocateOne(uint64_t size) {
int fd = ashmem_create_region("AshmemAllocator_hidl", size);
if (fd < 0) {
- _hidl_cb(false /* success */, hidl_memory());
- return Void();
+ LOG(WARNING) << "ashmem_create_region(" << size << ") fails with " << fd;
+ return hidl_memory();
}
native_handle_t* handle = native_handle_create(1, 0);
handle->data[0] = fd;
- hidl_memory memory("ashmem", handle, size);
+ LOG(WARNING) << "ashmem_create_region(" << size << ") returning hidl_memory(" << handle
+ << ", " << size << ")";
+ return hidl_memory("ashmem", handle, size);
+}
- _hidl_cb(true /* success */, memory);
- native_handle_close(handle);
- native_handle_delete(handle);
+static void cleanup(hidl_memory&& memory) {
+ if (memory.handle() == nullptr) {
+ return;
+ }
+
+ native_handle_close(const_cast<native_handle_t *>(memory.handle()));
+ native_handle_delete(const_cast<native_handle_t *>(memory.handle()));
+}
+
+Return<void> AshmemAllocator::allocate(uint64_t size, allocate_cb _hidl_cb) {
+ hidl_memory memory = allocateOne(size);
+ _hidl_cb(memory.handle() != nullptr /* success */, memory);
+ cleanup(std::move(memory));
+
+ return Void();
+}
+
+Return<void> AshmemAllocator::batchAllocate(uint64_t size, uint64_t count, batchAllocate_cb _hidl_cb) {
+ // resize fails if count > 2^32
+ if (count > UINT32_MAX) {
+ _hidl_cb(false /* success */, {});
+ return Void();
+ }
+
+ hidl_vec<hidl_memory> batch;
+ batch.resize(count);
+
+ uint64_t allocated;
+ for (allocated = 0; allocated < count; allocated++) {
+ batch[allocated] = allocateOne(size);
+
+ if (batch[allocated].handle() == nullptr) {
+ LOG(WARNING) << "batchAllocate(" << size << ", " << count << ") fails @ #" << allocated;
+ break;
+ }
+ }
+
+ // batch[i].handle() != nullptr for i in [0, allocated - 1].
+ // batch[i].handle() == nullptr for i in [allocated, count - 1].
+
+ if (allocated < count) {
+ _hidl_cb(false /* success */, {});
+ } else {
+ _hidl_cb(true /* success */, batch);
+ }
+
+ for (uint64_t i = 0; i < allocated; i++) {
+ cleanup(std::move(batch[i]));
+ }
+
return Void();
}
diff --git a/transport/allocator/1.0/default/AshmemAllocator.h b/transport/allocator/1.0/default/AshmemAllocator.h
index 307cb5a..131417d 100644
--- a/transport/allocator/1.0/default/AshmemAllocator.h
+++ b/transport/allocator/1.0/default/AshmemAllocator.h
@@ -39,7 +39,7 @@
struct AshmemAllocator : public IAllocator {
// Methods from ::android::hidl::allocator::V1_0::IAllocator follow.
Return<void> allocate(uint64_t size, allocate_cb _hidl_cb) override;
-
+ Return<void> batchAllocate(uint64_t size, uint64_t count, batchAllocate_cb _hidl_cb) override;
};
} // namespace implementation
diff --git a/transport/include/hidl/ServiceManagement.h b/transport/include/hidl/ServiceManagement.h
index 2b2266b..324a584 100644
--- a/transport/include/hidl/ServiceManagement.h
+++ b/transport/include/hidl/ServiceManagement.h
@@ -32,12 +32,6 @@
namespace hardware {
-// These functions are for internal use by hidl. If you want to get ahold
-// of an interface, the best way to do this is by calling IFoo::getService()
-
-sp<::android::hidl::manager::V1_0::IServiceManager> defaultServiceManager();
-sp<::android::hidl::manager::V1_0::IServiceManager> getPassthroughServiceManager();
-
namespace details {
// e.x.: android.hardware.foo@1.0, IFoo, default
void onRegistration(const std::string &packageName,
@@ -46,8 +40,26 @@
// e.x.: android.hardware.foo@1.0::IFoo, default
void waitForHwService(const std::string &interface, const std::string &instanceName);
+
+void preloadPassthroughService(const std::string &descriptor);
};
+// These functions are for internal use by hidl. If you want to get ahold
+// of an interface, the best way to do this is by calling IFoo::getService()
+sp<::android::hidl::manager::V1_0::IServiceManager> defaultServiceManager();
+sp<::android::hidl::manager::V1_0::IServiceManager> getPassthroughServiceManager();
+
+/**
+ * Given a service that is in passthrough mode, this function will go ahead and load the
+ * required passthrough module library (but not call HIDL_FETCH_I* functions to instantiate it).
+ *
+ * E.x.: preloadPassthroughService<IFoo>();
+ */
+template<typename I>
+static inline void preloadPassthroughService() {
+ details::preloadPassthroughService(I::descriptor);
+}
+
}; // namespace hardware
}; // namespace android