Merge pie-platform-release to aosp-master - DO NOT MERGE
Change-Id: I19d3fcbb4eb71702b49096b780b13a73bd0bd194
diff --git a/Android.bp b/Android.bp
index 032a61a..0f91348 100644
--- a/Android.bp
+++ b/Android.bp
@@ -17,6 +17,7 @@
cflags: [
"-Wall",
"-Werror",
+ "-Wextra-semi",
],
}
diff --git a/adapter/HidlBinderAdapter.cpp b/adapter/HidlBinderAdapter.cpp
index b6aa58e..ed6dad1 100644
--- a/adapter/HidlBinderAdapter.cpp
+++ b/adapter/HidlBinderAdapter.cpp
@@ -36,42 +36,92 @@
const static std::string kDeactivateProp = "test.hidl.adapters.deactivated";
-void usage(const std::string& me) {
- std::cerr << "usage: " << me << " [-p] interface-name instance-name number-of-threads."
+int usage(const std::string& me) {
+ std::cerr << "usage: " << me
+ << " [-p|P] [-n instance-name] interface-name instance-name number-of-threads."
<< std::endl;
std::cerr << " -p: stop based on property " << kDeactivateProp << "and reset it."
<< std::endl;
+ std::cerr << " -P: stop based on interface specific property " << kDeactivateProp
+ << ".<fq-name>.<instance-name>" << std::endl;
+ std::cerr
+ << " -n instance-name: register as a different instance name (does not de-register)"
+ << std::endl;
+ return EINVAL;
}
-bool processArguments(int* argc, char*** argv, bool* propertyStop) {
+enum class StopMethod {
+ NONE,
+ ALL,
+ SPECIFIC,
+};
+
+struct Args {
+ StopMethod stopMethod = StopMethod::NONE;
+ std::string interface; // e.x. IFoo
+ std::string instanceName; // e.x. default
+ int threadNumber;
+ std::string registerInstanceName; // e.x. default
+};
+
+bool processArguments(int argc, char** argv, Args* args) {
int c;
- while ((c = getopt(*argc, *argv, "p")) != -1) {
+ while ((c = getopt(argc, argv, "pPn:")) != -1) {
switch (c) {
case 'p': {
- *propertyStop = true;
+ args->stopMethod = StopMethod::ALL;
+ break;
+ }
+ case 'P': {
+ args->stopMethod = StopMethod::SPECIFIC;
+ break;
+ }
+ case 'n': {
+ args->registerInstanceName = optarg;
break;
}
default: { return false; }
}
}
- *argc -= optind;
- *argv += optind;
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 3) {
+ std::cerr << "ERROR: requires exactly three positional arguments for "
+ "interface, instance name, and number of threads, but "
+ << argc << " provided." << std::endl;
+ return false;
+ }
+
+ args->interface = argv[0];
+ args->instanceName = argv[1];
+ args->threadNumber = std::stoi(argv[2]);
+
+ if (args->threadNumber <= 0) {
+ std::cerr << "ERROR: invalid thread number " << args->threadNumber
+ << " must be a positive integer." << std::endl;
+ return false;
+ }
+
+ if (args->registerInstanceName.empty()) {
+ args->registerInstanceName = args->instanceName;
+ }
+
return true;
}
// only applies for -p argument
-void waitForAdaptersDeactivated() {
+void waitForAdaptersDeactivated(const std::string& property) {
using std::literals::chrono_literals::operator""s;
- while (!WaitForProperty(kDeactivateProp, "true", 30s)) {
+ while (!WaitForProperty(property, "true", 30s)) {
// Log this so that when using this option on testing devices, there is
// a clear indication if adapters are not properly stopped
- LOG(WARNING) << "Adapter use in progress. Waiting for stop based on 'true' "
- << kDeactivateProp;
+ LOG(WARNING) << "Adapter use in progress. Waiting for stop based on 'true' " << property;
}
- SetProperty(kDeactivateProp, "false");
+ SetProperty(property, "false");
}
int adapterMain(const std::string& package, int argc, char** argv,
@@ -82,25 +132,12 @@
const std::string& me = argc > 0 ? argv[0] : "(error)";
- bool propertyStop = false;
- if (!processArguments(&argc, &argv, &propertyStop)) {
- usage(me);
- return EINVAL;
+ Args args;
+ if (!processArguments(argc, argv, &args)) {
+ return usage(me);
}
- if (argc != 3) {
- usage(me);
- return EINVAL;
- }
-
- std::string interfaceName = package + "::" + argv[0];
- std::string instanceName = argv[1];
- int threadNumber = std::stoi(argv[2]);
-
- if (threadNumber <= 0) {
- std::cerr << "ERROR: invalid thread number " << threadNumber
- << " must be a positive integer.";
- }
+ std::string interfaceName = package + "::" + args.interface;
auto it = adapters.find(interfaceName);
if (it == adapters.end()) {
@@ -108,9 +145,10 @@
return 1;
}
- std::cout << "Trying to adapt down " << interfaceName << "/" << instanceName << std::endl;
+ std::cout << "Trying to adapt down " << interfaceName << "/" << args.instanceName << " to "
+ << args.registerInstanceName << std::endl;
- configureRpcThreadpool(threadNumber, false /* callerWillJoin */);
+ configureRpcThreadpool(args.threadNumber, false /* callerWillJoin */);
sp<IServiceManager> manager = IServiceManager::getService();
if (manager == nullptr) {
@@ -118,7 +156,7 @@
return 1;
}
- sp<IBase> implementation = manager->get(interfaceName, instanceName).withDefault(nullptr);
+ sp<IBase> implementation = manager->get(interfaceName, args.instanceName).withDefault(nullptr);
if (implementation == nullptr) {
std::cerr << "ERROR: could not retrieve desired implementation" << std::endl;
return 1;
@@ -130,25 +168,40 @@
return 1;
}
- bool replaced = manager->add(instanceName, adapter).withDefault(false);
+ bool replaced = manager->add(args.registerInstanceName, adapter).withDefault(false);
if (!replaced) {
std::cerr << "ERROR: could not register the service with the service manager." << std::endl;
return 1;
}
- if (propertyStop) {
- std::cout << "Set " << kDeactivateProp << " to true to deactivate." << std::endl;
- waitForAdaptersDeactivated();
- } else {
- std::cout << "Press any key to disassociate adapter." << std::endl;
- getchar();
+ switch (args.stopMethod) {
+ case StopMethod::NONE: {
+ std::cout << "Press any key to disassociate adapter." << std::endl;
+ getchar();
+ break;
+ };
+ case StopMethod::SPECIFIC: {
+ const std::string property =
+ kDeactivateProp + "." + interfaceName + "." + args.registerInstanceName;
+ std::cout << "Set " << property << " to true to deactivate." << std::endl;
+ waitForAdaptersDeactivated(property);
+ break;
+ };
+ case StopMethod::ALL: {
+ std::cout << "Set " << kDeactivateProp << " to true to deactivate." << std::endl;
+ waitForAdaptersDeactivated(kDeactivateProp);
+ break;
+ };
}
- bool restored = manager->add(instanceName, implementation).withDefault(false);
- if (!restored) {
- std::cerr << "ERROR: could not re-register interface with the service manager."
- << std::endl;
- return 1;
+ // automatically unregistered on process exit if it is a new instance name
+ if (args.registerInstanceName == args.instanceName) {
+ bool restored = manager->add(args.instanceName, implementation).withDefault(false);
+ if (!restored) {
+ std::cerr << "ERROR: could not re-register interface with the service manager."
+ << std::endl;
+ return 1;
+ }
}
std::cout << "Success." << std::endl;
diff --git a/base/Android.bp b/base/Android.bp
index 22f5ee1..359ac91 100644
--- a/base/Android.bp
+++ b/base/Android.bp
@@ -14,6 +14,7 @@
cc_library {
name: "libhidlbase",
+ recovery_available: true,
vendor_available: true,
vndk: {
enabled: true,
diff --git a/base/HidlInternal.cpp b/base/HidlInternal.cpp
index babdac1..440b30f 100644
--- a/base/HidlInternal.cpp
+++ b/base/HidlInternal.cpp
@@ -31,16 +31,17 @@
#include <regex>
extern "C" __attribute__((weak)) void __sanitizer_cov_dump();
-const char* kGcovPrefixEnvVar = "GCOV_PREFIX";
-const char* kGcovPrefixOverrideEnvVar = "GCOV_PREFIX_OVERRIDE";
-const char* kGcovPrefixPath = "/data/misc/trace/";
-const char* kSysPropHalCoverage = "hal.coverage.enable";
+
+const char kGcovPrefixEnvVar[] = "GCOV_PREFIX";
+const char kGcovPrefixOverrideEnvVar[] = "GCOV_PREFIX_OVERRIDE";
+const char kGcovPrefixPath[] = "/data/misc/trace/";
+const char kSysPropHalCoverage[] = "hal.coverage.enable";
#if defined(__LP64__)
-const char* kSysPropInstrumentationPath = "hal.instrumentation.lib.path.64";
+const char kSysPropInstrumentationPath[] = "hal.instrumentation.lib.path.64";
#else
-const char* kSysPropInstrumentationPath = "hal.instrumentation.lib.path.32";
+const char kSysPropInstrumentationPath[] = "hal.instrumentation.lib.path.32";
#endif
-#endif
+#endif // LIBHIDL_TARGET_DEBUGGABLE
namespace android {
namespace hardware {
@@ -145,7 +146,9 @@
} else {
static std::string halLibPathVndkSp = android::base::StringPrintf(
HAL_LIBRARY_PATH_VNDK_SP_FOR_VERSION, getVndkVersionStr().c_str());
+#ifndef __ANDROID_VNDK__
instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_SYSTEM);
+#endif
instrumentationLibPaths.push_back(halLibPathVndkSp);
instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_VENDOR);
instrumentationLibPaths.push_back(HAL_LIBRARY_PATH_ODM);
@@ -153,7 +156,7 @@
for (const auto& path : instrumentationLibPaths) {
DIR *dir = opendir(path.c_str());
- if (dir == 0) {
+ if (dir == nullptr) {
LOG(WARNING) << path << " does not exist. ";
return;
}
diff --git a/base/HidlSupport.cpp b/base/HidlSupport.cpp
index 8f3c057..58afa69 100644
--- a/base/HidlSupport.cpp
+++ b/base/HidlSupport.cpp
@@ -56,7 +56,7 @@
}
// move constructor.
-hidl_handle::hidl_handle(hidl_handle &&other) {
+hidl_handle::hidl_handle(hidl_handle&& other) noexcept {
mOwnsHandle = false;
*this = std::move(other);
}
@@ -87,7 +87,7 @@
return *this;
}
-hidl_handle &hidl_handle::operator=(hidl_handle &&other) {
+hidl_handle& hidl_handle::operator=(hidl_handle&& other) noexcept {
if (this != &other) {
freeHandle();
mHandle = other.mHandle;
@@ -167,11 +167,11 @@
copyFrom(s.c_str(), s.size());
}
-hidl_string::hidl_string(hidl_string &&other): hidl_string() {
+hidl_string::hidl_string(hidl_string&& other) noexcept : hidl_string() {
moveFrom(std::forward<hidl_string>(other));
}
-hidl_string &hidl_string::operator=(hidl_string &&other) {
+hidl_string& hidl_string::operator=(hidl_string&& other) noexcept {
if (this != &other) {
clear();
moveFrom(std::forward<hidl_string>(other));
@@ -254,6 +254,14 @@
if (size > UINT32_MAX) {
LOG(FATAL) << "string size can't exceed 2^32 bytes: " << size;
}
+
+ // When the binder driver copies this data into its buffer, it must
+ // have a zero byte there because the remote process will have a pointer
+ // directly into the read-only binder buffer. If we manually copy the
+ // data now to add a zero, then we lose the efficiency of this method.
+ // Checking here (it's also checked in the parceling code later).
+ CHECK(data[size] == '\0');
+
clear();
mBuffer = data;
@@ -307,9 +315,7 @@
: hidl_memory(name, std::move(handle), size) {}
// it's required to have at least one out-of-line method to avoid weak vtable
-HidlMemory::~HidlMemory() {
- hidl_memory::~hidl_memory();
-}
+HidlMemory::~HidlMemory() {}
} // namespace hardware
} // namespace android
diff --git a/base/Status.cpp b/base/Status.cpp
index 1ba91c3..5a4c918 100644
--- a/base/Status.cpp
+++ b/base/Status.cpp
@@ -82,11 +82,17 @@
}
Status Status::fromExceptionCode(int32_t exceptionCode) {
+ if (exceptionCode == EX_TRANSACTION_FAILED) {
+ return Status(exceptionCode, FAILED_TRANSACTION);
+ }
return Status(exceptionCode, OK);
}
Status Status::fromExceptionCode(int32_t exceptionCode,
const char *message) {
+ if (exceptionCode == EX_TRANSACTION_FAILED) {
+ return Status(exceptionCode, FAILED_TRANSACTION, message);
+ }
return Status(exceptionCode, OK, message);
}
@@ -107,7 +113,7 @@
void Status::setException(int32_t ex, const char *message) {
mException = ex;
- mErrorCode = NO_ERROR; // an exception, not a transaction failure.
+ mErrorCode = ex == EX_TRANSACTION_FAILED ? FAILED_TRANSACTION : NO_ERROR;
mMessage = message;
}
@@ -150,7 +156,7 @@
}
}
- return_status &return_status::operator=(return_status &&other) {
+ return_status& return_status::operator=(return_status&& other) noexcept {
if (!mCheckedStatus && !isOk()) {
LOG(FATAL) << "Failed HIDL return status not checked: " << description();
}
diff --git a/base/include/hidl/HidlInternal.h b/base/include/hidl/HidlInternal.h
index 5a08bc3..6377c46 100644
--- a/base/include/hidl/HidlInternal.h
+++ b/base/include/hidl/HidlInternal.h
@@ -48,6 +48,15 @@
// If "ro.vndk.version" is not set or set to "current", it returns empty string.
std::string getVndkVersionStr();
+// Explicitly invokes the parameterized element's destructor;
+// intended to be used alongside the placement new operator.
+template<typename T>
+void destructElement(T* element) {
+ if (element != nullptr) {
+ element->~T();
+ }
+}
+
// HIDL client/server code should *NOT* use this class.
//
// hidl_pointer wraps a pointer without taking ownership,
@@ -62,13 +71,13 @@
}
hidl_pointer(T* ptr) : hidl_pointer() { mPointer = ptr; }
hidl_pointer(const hidl_pointer<T>& other) : hidl_pointer() { mPointer = other.mPointer; }
- hidl_pointer(hidl_pointer<T>&& other) : hidl_pointer() { *this = std::move(other); }
+ hidl_pointer(hidl_pointer<T>&& other) noexcept : hidl_pointer() { *this = std::move(other); }
hidl_pointer &operator=(const hidl_pointer<T>& other) {
mPointer = other.mPointer;
return *this;
}
- hidl_pointer &operator=(hidl_pointer<T>&& other) {
+ hidl_pointer& operator=(hidl_pointer<T>&& other) noexcept {
mPointer = other.mPointer;
other.mPointer = nullptr;
return *this;
diff --git a/base/include/hidl/HidlSupport.h b/base/include/hidl/HidlSupport.h
index f09eb63..2d0dc25 100644
--- a/base/include/hidl/HidlSupport.h
+++ b/base/include/hidl/HidlSupport.h
@@ -40,18 +40,22 @@
namespace hidl {
namespace memory {
namespace V1_0 {
- struct IMemory;
-}; // namespace V1_0
-}; // namespace manager
-}; // namespace hidl
+
+struct IMemory;
+
+} // namespace V1_0
+} // namespace memory
+} // namespace hidl
namespace hidl {
namespace base {
namespace V1_0 {
- struct IBase;
-}; // namespace V1_0
-}; // namespace base
-}; // namespace hidl
+
+struct IBase;
+
+} // namespace V1_0
+} // namespace base
+} // namespace hidl
namespace hardware {
@@ -112,6 +116,10 @@
// explicit conversion
const native_handle_t *getNativeHandle() const;
+
+ // offsetof(hidl_handle, mHandle) exposed since mHandle is private.
+ static const size_t kOffsetOfNativeHandle;
+
private:
void freeHandle();
@@ -155,6 +163,8 @@
// Reference an external char array. Ownership is _not_ transferred.
// Caller is responsible for ensuring that underlying memory is valid
// for the lifetime of this hidl_string.
+ //
+ // size == strlen(data)
void setToExternal(const char *data, size_t size);
// offsetof(hidl_string, mBuffer) exposed since mBuffer is private.
@@ -839,6 +849,10 @@
return (mMajor == other.get_major() && mMinor == other.get_minor());
}
+ bool operator!=(const hidl_version& other) const {
+ return !(*this == other);
+ }
+
bool operator<(const hidl_version& other) const {
return (mMajor < other.get_major() ||
(mMajor == other.get_major() && mMinor < other.get_minor()));
@@ -985,10 +999,17 @@
/**
* Every HIDL generated enum generates an implementation of this function.
- * E.x.: for(const auto v : hidl_enum_iterator<Enum>) { ... }
+ * E.x.: for(const auto v : hidl_enum_range<Enum>) { ... }
*/
-template <typename>
-struct hidl_enum_iterator;
+template <typename T, typename = std::enable_if_t<std::is_enum<T>::value>>
+struct hidl_enum_range;
+
+template <typename T, typename = std::enable_if_t<std::is_enum<T>::value>>
+struct hidl_enum_iterator {
+ static_assert(!std::is_enum<T>::value,
+ "b/78573628: hidl_enum_iterator was renamed to hidl_enum_range because it is not "
+ "actually an iterator. Please use that type instead.");
+};
/**
* Bitfields in HIDL are the underlying type of the enumeration.
diff --git a/base/include/hidl/MQDescriptor.h b/base/include/hidl/MQDescriptor.h
index 23be971..0f61cb5 100644
--- a/base/include/hidl/MQDescriptor.h
+++ b/base/include/hidl/MQDescriptor.h
@@ -59,18 +59,20 @@
template <typename T, MQFlavor flavor>
struct MQDescriptor {
+ // Takes ownership of handle
MQDescriptor(
const std::vector<GrantorDescriptor>& grantors,
native_handle_t* nHandle, size_t size);
+ // Takes ownership of handle
MQDescriptor(size_t bufferSize, native_handle_t* nHandle,
size_t messageSize, bool configureEventFlag = false);
MQDescriptor();
~MQDescriptor();
- explicit MQDescriptor(const MQDescriptor &other);
- MQDescriptor &operator=(const MQDescriptor &other) = delete;
+ explicit MQDescriptor(const MQDescriptor& other) : MQDescriptor() { *this = other; }
+ MQDescriptor& operator=(const MQDescriptor& other);
size_t getSize() const;
@@ -213,12 +215,17 @@
}
}
-template<typename T, MQFlavor flavor>
-MQDescriptor<T, flavor>::MQDescriptor(const MQDescriptor<T, flavor> &other)
- : mGrantors(other.mGrantors),
- mHandle(nullptr),
- mQuantum(other.mQuantum),
- mFlags(other.mFlags) {
+template <typename T, MQFlavor flavor>
+MQDescriptor<T, flavor>& MQDescriptor<T, flavor>::operator=(const MQDescriptor& other) {
+ mGrantors = other.mGrantors;
+ if (mHandle != nullptr) {
+ native_handle_close(mHandle);
+ native_handle_delete(mHandle);
+ mHandle = nullptr;
+ }
+ mQuantum = other.mQuantum;
+ mFlags = other.mFlags;
+
if (other.mHandle != nullptr) {
mHandle = native_handle_create(
other.mHandle->numFds, other.mHandle->numInts);
@@ -231,6 +238,8 @@
&other.mHandle->data[other.mHandle->numFds],
other.mHandle->numInts * sizeof(int));
}
+
+ return *this;
}
template<typename T, MQFlavor flavor>
diff --git a/base/include/hidl/Status.h b/base/include/hidl/Status.h
index 1a2ef6d..b69d4e4 100644
--- a/base/include/hidl/Status.h
+++ b/base/include/hidl/Status.h
@@ -148,10 +148,8 @@
return_status(const return_status &) = delete;
return_status &operator=(const return_status &) = delete;
- return_status(return_status &&other) {
- *this = std::move(other);
- }
- return_status &operator=(return_status &&other);
+ return_status(return_status&& other) noexcept { *this = std::move(other); }
+ return_status& operator=(return_status&& other) noexcept;
~return_status();
@@ -197,8 +195,8 @@
// move-able.
// precondition: "this" has checked status
// postcondition: other is safe to destroy after moving to *this.
- Return(Return &&other) = default;
- Return &operator=(Return &&) = default;
+ Return(Return&& other) noexcept = default;
+ Return& operator=(Return&&) noexcept = default;
~Return() = default;
@@ -226,8 +224,8 @@
// move-able.
// precondition: "this" has checked status
// postcondition: other is safe to destroy after moving to *this.
- Return(Return &&other) = default;
- Return &operator=(Return &&) = default;
+ Return(Return&& other) noexcept = default;
+ Return& operator=(Return&&) noexcept = default;
~Return() = default;
diff --git a/libhidlcache/HidlCache.h b/libhidlcache/HidlCache.h
index db778d3..39a7b3a 100644
--- a/libhidlcache/HidlCache.h
+++ b/libhidlcache/HidlCache.h
@@ -97,7 +97,7 @@
template <class Key, class Value, class Compare>
sp<Value> HidlCache<Key, Value, Compare>::unlock(const Key& key) {
Lock lock(mMutex);
- if (locked(key) > 0) {
+ if (locked(key)) {
sp<Value> v = mLocked[key];
mLocked.erase(key);
return v;
diff --git a/libhidlcache/HidlMemoryCache.cpp b/libhidlcache/HidlMemoryCache.cpp
index 6f9c25c..a23c388 100644
--- a/libhidlcache/HidlMemoryCache.cpp
+++ b/libhidlcache/HidlMemoryCache.cpp
@@ -28,12 +28,12 @@
using IMemoryToken = ::android::hidl::memory::token::V1_0::IMemoryToken;
using IMemory = ::android::hidl::memory::V1_0::IMemory;
-class IMemoryDecorator : public virtual IMemory {
+class MemoryDecorator : public virtual IMemory {
public:
- IMemoryDecorator(sp<IMemory> heap) : mHeap(heap) {}
- virtual ~IMemoryDecorator(){};
+ 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> read() override { return mHeap->read(); }
Return<void> updateRange(uint64_t start, uint64_t length) override {
return mHeap->updateRange(start, length);
}
@@ -49,29 +49,28 @@
sp<IMemory> mHeap;
};
-class IMemoryCacheable : public virtual IMemoryDecorator {
+class MemoryCacheable : public virtual MemoryDecorator {
public:
- IMemoryCacheable(sp<IMemory> heap, sp<IMemoryToken> key) : IMemoryDecorator(heap), mKey(key) {}
- virtual ~IMemoryCacheable() { HidlMemoryCache::getInstance()->flush(mKey); }
+ MemoryCacheable(const sp<IMemory>& heap, sp<IMemoryToken> key)
+ : MemoryDecorator(heap), mKey(key) {}
+ virtual ~MemoryCacheable() { HidlMemoryCache::getInstance()->flush(mKey); }
protected:
sp<IMemoryToken> mKey;
};
-class IMemoryBlock : public virtual IMemoryDecorator {
+class MemoryBlockImpl : public virtual IMemory {
public:
- IMemoryBlock(sp<IMemory> heap, uint64_t size, uint64_t offset)
- : IMemoryDecorator(heap), mSize(size), mOffset(offset), mHeapSize(heap->getSize()) {}
+ 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 (start + length <= mSize) && (start + length >= start) &&
+ (mOffset + mSize <= mHeapSize);
}
- Return<void> readRange(uint64_t start, uint64_t length) {
+ Return<void> readRange(uint64_t start, uint64_t length) override {
if (!validRange(start, length)) {
ALOGE("IMemoryBlock::readRange: out of range");
- Status status;
- status.setException(Status::EX_ILLEGAL_ARGUMENT, "out of range");
- return Return<void>(status);
+ return Void();
}
return mHeap->readRange(mOffset + start, length);
}
@@ -82,6 +81,9 @@
}
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();
@@ -89,6 +91,7 @@
}
protected:
+ sp<IMemory> mHeap;
uint64_t mSize;
uint64_t mOffset;
uint64_t mHeapSize;
@@ -102,7 +105,7 @@
sp<IMemory> HidlMemoryCache::fillLocked(const sp<IMemoryToken>& key) {
sp<IMemory> memory = nullptr;
Return<void> ret = key->get(
- [&](const hidl_memory& mem) { memory = new IMemoryCacheable(mapMemory(mem), key); });
+ [&](const hidl_memory& mem) { memory = new MemoryCacheable(mapMemory(mem), key); });
if (!ret.isOk()) {
ALOGE("HidlMemoryCache::fill: cannot IMemoryToken::get.");
return nullptr;
@@ -117,7 +120,7 @@
if (heap == nullptr) {
return nullptr;
}
- return new IMemoryBlock(heap, memblk.size, memblk.offset);
+ return new MemoryBlockImpl(heap, memblk.size, memblk.offset);
}
} // namespace hardware
diff --git a/libhidlcache/MemoryDealer.cpp b/libhidlcache/MemoryDealer.cpp
index e9196a1..e0e18c7 100644
--- a/libhidlcache/MemoryDealer.cpp
+++ b/libhidlcache/MemoryDealer.cpp
@@ -123,7 +123,7 @@
// 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.head() == removed);
+ LOG_ALWAYS_FATAL_IF(mList.front() == removed);
#endif
delete removed;
}
@@ -240,7 +240,7 @@
return freed;
}
}
- return 0;
+ return nullptr;
}
void SimpleBestFitAllocator::dump(const char* tag) const {
diff --git a/minijail/HardwareMinijail.cpp b/minijail/HardwareMinijail.cpp
index e6b1144..990a689 100644
--- a/minijail/HardwareMinijail.cpp
+++ b/minijail/HardwareMinijail.cpp
@@ -29,7 +29,7 @@
}
struct minijail* jail = minijail_new();
- if (jail == NULL) {
+ if (jail == nullptr) {
LOG(FATAL) << "Failed to create minijail.";
}
diff --git a/test_main.cpp b/test_main.cpp
index 0de46ec..7f80d71 100644
--- a/test_main.cpp
+++ b/test_main.cpp
@@ -390,12 +390,15 @@
hidl_version v3_0b{3,0};
EXPECT_TRUE(v1_0 < v2_0);
+ EXPECT_TRUE(v1_0 != v2_0);
EXPECT_TRUE(v2_0 < v2_1);
EXPECT_TRUE(v2_1 < v3_0);
EXPECT_TRUE(v2_0 > v1_0);
+ EXPECT_TRUE(v2_0 != v1_0);
EXPECT_TRUE(v2_1 > v2_0);
EXPECT_TRUE(v3_0 > v2_1);
EXPECT_TRUE(v3_0 == v3_0b);
+ EXPECT_FALSE(v3_0 != v3_0b);
EXPECT_TRUE(v3_0 <= v3_0b);
EXPECT_TRUE(v2_2 <= v3_0);
EXPECT_TRUE(v3_0 >= v3_0b);
diff --git a/transport/Android.bp b/transport/Android.bp
index 5b0c11c..f783022 100644
--- a/transport/Android.bp
+++ b/transport/Android.bp
@@ -14,11 +14,11 @@
hidl_package_root {
name: "android.hidl",
- path: "system/libhidl/transport",
}
cc_library {
name: "libhidltransport",
+ recovery_available: true,
vendor_available: true,
vndk: {
enabled: true,
@@ -47,16 +47,19 @@
generated_sources: [
"android.hidl.manager@1.0_genc++",
"android.hidl.manager@1.1_genc++",
+ "android.hidl.manager@1.2_genc++",
"android.hidl.base@1.0_genc++"
],
generated_headers: [
"android.hidl.manager@1.0_genc++_headers",
"android.hidl.manager@1.1_genc++_headers",
+ "android.hidl.manager@1.2_genc++_headers",
"android.hidl.base@1.0_genc++_headers"
],
export_generated_headers: [
"android.hidl.manager@1.0_genc++_headers",
"android.hidl.manager@1.1_genc++_headers",
+ "android.hidl.manager@1.2_genc++_headers",
"android.hidl.base@1.0_genc++_headers"
],
@@ -77,4 +80,10 @@
cflags: ["-DENFORCE_VINTF_MANIFEST"]
},
},
+
+ target: {
+ recovery: {
+ exclude_shared_libs: ["libvndksupport"],
+ },
+ },
}
diff --git a/transport/HidlBinderSupport.cpp b/transport/HidlBinderSupport.cpp
index 4f8d7c5..caf7cf8 100644
--- a/transport/HidlBinderSupport.cpp
+++ b/transport/HidlBinderSupport.cpp
@@ -18,6 +18,10 @@
#include <hidl/HidlBinderSupport.h>
+#include <InternalStatic.h> // TODO(b/69122224): remove this include, for getOrCreateCachedBinder
+#include <android/hidl/base/1.0/BpHwBase.h>
+#include <hwbinder/IPCThreadState.h>
+
// C includes
#include <inttypes.h>
#include <unistd.h>
@@ -46,6 +50,30 @@
return mRecipient;
}
+const size_t hidl_handle::kOffsetOfNativeHandle = offsetof(hidl_handle, mHandle);
+static_assert(hidl_handle::kOffsetOfNativeHandle == 0, "wrong offset");
+
+status_t readEmbeddedFromParcel(const hidl_handle& /* handle */,
+ const Parcel &parcel, size_t parentHandle, size_t parentOffset) {
+ const native_handle_t *handle;
+ status_t _hidl_err = parcel.readNullableEmbeddedNativeHandle(
+ parentHandle,
+ parentOffset + hidl_handle::kOffsetOfNativeHandle,
+ &handle);
+
+ return _hidl_err;
+}
+
+status_t writeEmbeddedToParcel(const hidl_handle &handle,
+ Parcel *parcel, size_t parentHandle, size_t parentOffset) {
+ status_t _hidl_err = parcel->writeEmbeddedNativeHandle(
+ handle.getNativeHandle(),
+ parentHandle,
+ parentOffset + hidl_handle::kOffsetOfNativeHandle);
+
+ return _hidl_err;
+}
+
const size_t hidl_memory::kOffsetOfHandle = offsetof(hidl_memory, mHandle);
const size_t hidl_memory::kOffsetOfName = offsetof(hidl_memory, mName);
static_assert(hidl_memory::kOffsetOfHandle == 0, "wrong offset");
@@ -53,6 +81,7 @@
status_t readEmbeddedFromParcel(const hidl_memory& memory,
const Parcel &parcel, size_t parentHandle, size_t parentOffset) {
+ // TODO(b/111883309): Invoke readEmbeddedFromParcel(hidl_handle, ...).
const native_handle_t *handle;
::android::status_t _hidl_err = parcel.readNullableEmbeddedNativeHandle(
parentHandle,
@@ -81,6 +110,7 @@
status_t writeEmbeddedToParcel(const hidl_memory &memory,
Parcel *parcel, size_t parentHandle, size_t parentOffset) {
+ // TODO(b/111883309): Invoke writeEmbeddedToParcel(hidl_handle, ...).
status_t _hidl_err = parcel->writeEmbeddedNativeHandle(
memory.handle(),
parentHandle,
@@ -206,11 +236,63 @@
return status;
}
+sp<IBinder> getOrCreateCachedBinder(::android::hidl::base::V1_0::IBase* ifacePtr) {
+ if (ifacePtr == nullptr) {
+ return nullptr;
+ }
+
+ if (ifacePtr->isRemote()) {
+ using ::android::hidl::base::V1_0::BpHwBase;
+
+ BpHwBase* bpBase = static_cast<BpHwBase*>(ifacePtr);
+ BpHwRefBase* bpRefBase = static_cast<BpHwRefBase*>(bpBase);
+ return sp<IBinder>(bpRefBase->remote());
+ }
+
+ std::string descriptor = details::getDescriptor(ifacePtr);
+ if (descriptor.empty()) {
+ // interfaceDescriptor fails
+ return nullptr;
+ }
+
+ // for get + set
+ std::unique_lock<std::mutex> _lock = details::gBnMap.lock();
+
+ wp<BHwBinder> wBnObj = details::gBnMap.getLocked(ifacePtr, nullptr);
+ sp<IBinder> sBnObj = wBnObj.promote();
+
+ if (sBnObj == nullptr) {
+ auto func = details::getBnConstructorMap().get(descriptor, nullptr);
+ if (!func) {
+ // TODO(b/69122224): remove this static variable when prebuilts updated
+ func = details::gBnConstructorMap.get(descriptor, nullptr);
+ }
+ LOG_ALWAYS_FATAL_IF(func == nullptr, "%s gBnConstructorMap returned null for %s", __func__,
+ descriptor.c_str());
+
+ sBnObj = sp<IBinder>(func(static_cast<void*>(ifacePtr)));
+ LOG_ALWAYS_FATAL_IF(sBnObj == nullptr, "%s Bn constructor function returned null for %s",
+ __func__, descriptor.c_str());
+
+ details::gBnMap.setLocked(ifacePtr, static_cast<BHwBinder*>(sBnObj.get()));
+ }
+
+ return sBnObj;
+}
+
+static bool gThreadPoolConfigured = false;
+
void configureBinderRpcThreadpool(size_t maxThreads, bool callerWillJoin) {
- ProcessState::self()->setThreadPoolConfiguration(maxThreads, callerWillJoin /*callerJoinsPool*/);
+ status_t ret = ProcessState::self()->setThreadPoolConfiguration(
+ maxThreads, callerWillJoin /*callerJoinsPool*/);
+ LOG_ALWAYS_FATAL_IF(ret != OK, "Could not setThreadPoolConfiguration: %d", ret);
+
+ gThreadPoolConfigured = true;
}
void joinBinderRpcThreadpool() {
+ LOG_ALWAYS_FATAL_IF(!gThreadPoolConfigured,
+ "HIDL joinRpcThreadpool without calling configureRpcThreadPool.");
IPCThreadState::self()->joinThreadPool();
}
@@ -218,9 +300,7 @@
int fd;
int err = IPCThreadState::self()->setupPolling(&fd);
- if (err != OK) {
- ALOGE("Failed to setup binder polling: %d (%s)", err, strerror(err));
- }
+ LOG_ALWAYS_FATAL_IF(err != OK, "Failed to setup binder polling: %d (%s)", err, strerror(err));
return err == OK ? fd : -1;
}
@@ -229,5 +309,9 @@
return IPCThreadState::self()->handlePolledCommands();
}
+void addPostCommandTask(const std::function<void(void)> task) {
+ IPCThreadState::self()->addPostCommandTask(task);
+}
+
} // namespace hardware
} // namespace android
diff --git a/transport/HidlPassthroughSupport.cpp b/transport/HidlPassthroughSupport.cpp
index e5eb164..ff68a1e 100644
--- a/transport/HidlPassthroughSupport.cpp
+++ b/transport/HidlPassthroughSupport.cpp
@@ -16,6 +16,8 @@
#include <hidl/HidlPassthroughSupport.h>
+#include <InternalStatic.h> // TODO(b/69122224): remove this include, for tryWrap
+
#include <hidl/HidlTransportUtils.h>
#include <hidl/Static.h>
@@ -28,6 +30,7 @@
static sp<IBase> tryWrap(const std::string& descriptor, sp<IBase> iface) {
auto func = getBsConstructorMap().get(descriptor, nullptr);
if (!func) {
+ // TODO(b/69122224): remove this when prebuilts don't reference it
func = gBsConstructorMap.get(descriptor, nullptr);
}
if (func) {
diff --git a/transport/HidlTransportSupport.cpp b/transport/HidlTransportSupport.cpp
index d0871f6..591ccba 100644
--- a/transport/HidlTransportSupport.cpp
+++ b/transport/HidlTransportSupport.cpp
@@ -13,9 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#include <hidl/HidlTransportSupport.h>
#include <hidl/HidlBinderSupport.h>
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/Static.h>
+#include <android-base/logging.h>
#include <android/hidl/manager/1.0/IServiceManager.h>
namespace android {
@@ -41,24 +43,47 @@
bool setMinSchedulerPolicy(const sp<::android::hidl::base::V1_0::IBase>& service,
int policy, int priority) {
if (service->isRemote()) {
- ALOGE("Can't set scheduler policy on remote service.");
+ LOG(ERROR) << "Can't set scheduler policy on remote service.";
return false;
}
- if (policy != SCHED_NORMAL && policy != SCHED_FIFO && policy != SCHED_RR) {
- ALOGE("Invalid scheduler policy %d", policy);
- return false;
+ switch (policy) {
+ case SCHED_NORMAL: {
+ if (priority < -20 || priority > 19) {
+ LOG(ERROR) << "Invalid priority for SCHED_NORMAL: " << priority;
+ return false;
+ }
+ } break;
+ case SCHED_RR:
+ case SCHED_FIFO: {
+ if (priority < 1 || priority > 99) {
+ LOG(ERROR) << "Invalid priority for " << policy << " policy: " << priority;
+ return false;
+ }
+ } break;
+ default: {
+ LOG(ERROR) << "Invalid scheduler policy " << policy;
+ return false;
+ }
}
- if (policy == SCHED_NORMAL && (priority < -20 || priority > 19)) {
- ALOGE("Invalid priority for SCHED_NORMAL: %d", priority);
- return false;
- } else if (priority < 1 || priority > 99) {
- ALOGE("Invalid priority for real-time policy: %d", priority);
- return false;
- }
+ // Due to ABI considerations, IBase cannot have a destructor to clean this up.
+ // So, because this API is so infrequently used, (expected to be usually only
+ // one time for a process, but it can be more), we are cleaning it up here.
+ // TODO(b/37794345): if ever we update the HIDL ABI for launches in an Android
+ // release in the meta-version sense, we should remove this.
+ std::unique_lock<std::mutex> lock = details::gServicePrioMap.lock();
- details::gServicePrioMap.set(service, { policy, priority });
+ std::vector<wp<::android::hidl::base::V1_0::IBase>> toDelete;
+ for (const auto& kv : details::gServicePrioMap) {
+ if (kv.first.promote() == nullptr) {
+ toDelete.push_back(kv.first);
+ }
+ }
+ for (const auto& k : toDelete) {
+ details::gServicePrioMap.eraseLocked(k);
+ }
+ details::gServicePrioMap.setLocked(service, {policy, priority});
return true;
}
diff --git a/transport/InternalStatic.h b/transport/InternalStatic.h
new file mode 100644
index 0000000..b0fefa9
--- /dev/null
+++ b/transport/InternalStatic.h
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+// This file is for legacy static variables that we are trying to get rid of.
+// TODO(b/69122224): remove this file
+
+#ifndef ANDROID_HARDWARE_HIDL_INTERNAL_STATIC_H
+#define ANDROID_HARDWARE_HIDL_INTERNAL_STATIC_H
+
+#include <hidl/Static.h>
+
+namespace android {
+namespace hardware {
+namespace details {
+
+// deprecated; use getBnConstructorMap instead.
+extern BnConstructorMap gBnConstructorMap;
+// deprecated; use getBsConstructorMap instead.
+extern BsConstructorMap gBsConstructorMap;
+
+} // namespace details
+} // namespace hardware
+} // namespace android
+
+#endif
diff --git a/transport/ServiceManagement.cpp b/transport/ServiceManagement.cpp
index 01f83bd..40a7ff5 100644
--- a/transport/ServiceManagement.cpp
+++ b/transport/ServiceManagement.cpp
@@ -33,17 +33,23 @@
#include <hidl/HidlTransportUtils.h>
#include <hidl/ServiceManagement.h>
#include <hidl/Status.h>
+#include <utils/SystemClock.h>
+#include <android-base/file.h>
#include <android-base/logging.h>
+#include <android-base/parseint.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
#include <hwbinder/IPCThreadState.h>
#include <hwbinder/Parcel.h>
+#if !defined(__ANDROID_RECOVERY__)
#include <vndksupport/linker.h>
+#endif
-#include <android/hidl/manager/1.1/IServiceManager.h>
-#include <android/hidl/manager/1.1/BpHwServiceManager.h>
-#include <android/hidl/manager/1.1/BnHwServiceManager.h>
+#include <android/hidl/manager/1.2/BnHwServiceManager.h>
+#include <android/hidl/manager/1.2/BpHwServiceManager.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
#define RE_COMPONENT "[a-zA-Z_][a-zA-Z_0-9]*"
#define RE_PATH RE_COMPONENT "(?:[.]" RE_COMPONENT ")*"
@@ -51,23 +57,24 @@
using android::base::WaitForProperty;
+using ::android::hidl::base::V1_0::IBase;
using IServiceManager1_0 = android::hidl::manager::V1_0::IServiceManager;
using IServiceManager1_1 = android::hidl::manager::V1_1::IServiceManager;
-using android::hidl::manager::V1_0::IServiceNotification;
-using android::hidl::manager::V1_1::BpHwServiceManager;
-using android::hidl::manager::V1_1::BnHwServiceManager;
+using IServiceManager1_2 = android::hidl::manager::V1_2::IServiceManager;
+using ::android::hidl::manager::V1_0::IServiceNotification;
namespace android {
namespace hardware {
-namespace details {
-extern Mutex gDefaultServiceManagerLock;
-extern sp<android::hidl::manager::V1_1::IServiceManager> gDefaultServiceManager;
-} // namespace details
-
static const char* kHwServicemanagerReadyProperty = "hwservicemanager.ready";
-void waitForHwServiceManager() {
+#if defined(__ANDROID_RECOVERY__)
+static constexpr bool kIsRecovery = true;
+#else
+static constexpr bool kIsRecovery = false;
+#endif
+
+static void waitForHwServiceManager() {
using std::literals::chrono_literals::operator""s;
while (!WaitForProperty(kHwServicemanagerReadyProperty, "true", 1s)) {
@@ -75,17 +82,7 @@
}
}
-bool endsWith(const std::string &in, const std::string &suffix) {
- return in.size() >= suffix.size() &&
- in.substr(in.size() - suffix.size()) == suffix;
-}
-
-bool startsWith(const std::string &in, const std::string &prefix) {
- return in.size() >= prefix.size() &&
- in.substr(0, prefix.size()) == prefix;
-}
-
-std::string binaryName() {
+static std::string binaryName() {
std::ifstream ifs("/proc/self/cmdline");
std::string cmdline;
if (!ifs.is_open()) {
@@ -101,27 +98,27 @@
return cmdline;
}
-std::string packageWithoutVersion(const std::string& packageAndVersion) {
+static std::string packageWithoutVersion(const std::string& packageAndVersion) {
size_t at = packageAndVersion.find('@');
if (at == std::string::npos) return packageAndVersion;
return packageAndVersion.substr(0, at);
}
-void tryShortenProcessName(const std::string& packageAndVersion) {
+static void tryShortenProcessName(const std::string& descriptor) {
const static std::string kTasks = "/proc/self/task/";
// make sure that this binary name is in the same package
std::string processName = binaryName();
// e.x. android.hardware.foo is this package
- if (!startsWith(packageWithoutVersion(processName), packageWithoutVersion(packageAndVersion))) {
+ if (!base::StartsWith(packageWithoutVersion(processName), packageWithoutVersion(descriptor))) {
return;
}
- // e.x. android.hardware.module.foo@1.2 -> foo@1.2
- size_t lastDot = packageAndVersion.rfind('.');
+ // e.x. android.hardware.module.foo@1.2::IFoo -> foo@1.2
+ size_t lastDot = descriptor.rfind('.');
if (lastDot == std::string::npos) return;
- size_t secondDot = packageAndVersion.rfind('.', lastDot - 1);
+ size_t secondDot = descriptor.rfind('.', lastDot - 1);
if (secondDot == std::string::npos) return;
std::string newName = processName.substr(secondDot + 1, std::string::npos);
@@ -145,7 +142,7 @@
fs >> oldComm;
// don't rename if it already has an explicit name
- if (startsWith(packageAndVersion, oldComm)) {
+ if (base::StartsWith(descriptor, oldComm)) {
fs.seekg(0, fs.beg);
fs << newName;
}
@@ -154,22 +151,69 @@
namespace details {
-void onRegistration(const std::string &packageName,
- const std::string& /* interfaceName */,
- const std::string& /* instanceName */) {
- tryShortenProcessName(packageName);
+/*
+ * Returns the age of the current process by reading /proc/self/stat and comparing starttime to the
+ * current time. This is useful for measuring how long it took a HAL to register itself.
+ */
+static long getProcessAgeMs() {
+ constexpr const int PROCFS_STAT_STARTTIME_INDEX = 21;
+ std::string content;
+ android::base::ReadFileToString("/proc/self/stat", &content, false);
+ auto stats = android::base::Split(content, " ");
+ if (stats.size() <= PROCFS_STAT_STARTTIME_INDEX) {
+ LOG(INFO) << "Could not read starttime from /proc/self/stat";
+ return -1;
+ }
+ const std::string& startTimeString = stats[PROCFS_STAT_STARTTIME_INDEX];
+ static const int64_t ticksPerSecond = sysconf(_SC_CLK_TCK);
+ const int64_t uptime = android::uptimeMillis();
+
+ unsigned long long startTimeInClockTicks = 0;
+ if (android::base::ParseUint(startTimeString, &startTimeInClockTicks)) {
+ long startTimeMs = 1000ULL * startTimeInClockTicks / ticksPerSecond;
+ return uptime - startTimeMs;
+ }
+ return -1;
+}
+
+static void onRegistrationImpl(const std::string& descriptor, const std::string& instanceName) {
+ long halStartDelay = getProcessAgeMs();
+ if (halStartDelay >= 0) {
+ // The "start delay" printed here is an estimate of how long it took the HAL to go from
+ // process creation to registering itself as a HAL. Actual start time could be longer
+ // because the process might not have joined the threadpool yet, so it might not be ready to
+ // process transactions.
+ LOG(INFO) << "Registered " << descriptor << "/" << instanceName << " (start delay of "
+ << halStartDelay << "ms)";
+ }
+
+ tryShortenProcessName(descriptor);
+}
+
+void onRegistration(const std::string& packageName, const std::string& interfaceName,
+ const std::string& instanceName) {
+ return onRegistrationImpl(packageName + "::" + interfaceName, instanceName);
}
} // details
sp<IServiceManager1_0> defaultServiceManager() {
- return defaultServiceManager1_1();
+ return defaultServiceManager1_2();
}
sp<IServiceManager1_1> defaultServiceManager1_1() {
+ return defaultServiceManager1_2();
+}
+sp<IServiceManager1_2> defaultServiceManager1_2() {
+ using android::hidl::manager::V1_2::BnHwServiceManager;
+ using android::hidl::manager::V1_2::BpHwServiceManager;
+
+ static std::mutex gDefaultServiceManagerLock;
+ static sp<IServiceManager1_2> gDefaultServiceManager;
+
{
- AutoMutex _l(details::gDefaultServiceManagerLock);
- if (details::gDefaultServiceManager != nullptr) {
- return details::gDefaultServiceManager;
+ std::lock_guard<std::mutex> _l(gDefaultServiceManagerLock);
+ if (gDefaultServiceManager != nullptr) {
+ return gDefaultServiceManager;
}
if (access("/dev/hwbinder", F_OK|R_OK|W_OK) != 0) {
@@ -180,18 +224,18 @@
waitForHwServiceManager();
- while (details::gDefaultServiceManager == nullptr) {
- details::gDefaultServiceManager =
- fromBinder<IServiceManager1_1, BpHwServiceManager, BnHwServiceManager>(
- ProcessState::self()->getContextObject(nullptr));
- if (details::gDefaultServiceManager == nullptr) {
+ while (gDefaultServiceManager == nullptr) {
+ gDefaultServiceManager =
+ fromBinder<IServiceManager1_2, BpHwServiceManager, BnHwServiceManager>(
+ ProcessState::self()->getContextObject(nullptr));
+ if (gDefaultServiceManager == nullptr) {
LOG(ERROR) << "Waited for hwservicemanager, but got nullptr.";
sleep(1);
}
}
}
- return details::gDefaultServiceManager;
+ return gDefaultServiceManager;
}
std::vector<std::string> search(const std::string &path,
@@ -206,8 +250,7 @@
while ((dp = readdir(dir.get())) != nullptr) {
std::string name = dp->d_name;
- if (startsWith(name, prefix) &&
- endsWith(name, suffix)) {
+ if (base::StartsWith(name, prefix) && base::EndsWith(name, suffix)) {
results.push_back(name);
}
}
@@ -226,6 +269,11 @@
}
static void registerReference(const hidl_string &interfaceName, const hidl_string &instanceName) {
+ if (kIsRecovery) {
+ // No hwservicemanager in recovery.
+ return;
+ }
+
sp<IServiceManager1_0> binderizedManager = defaultServiceManager();
if (binderizedManager == nullptr) {
LOG(WARNING) << "Could not registerReference for "
@@ -309,8 +357,12 @@
static std::string halLibPathVndkSp = android::base::StringPrintf(
HAL_LIBRARY_PATH_VNDK_SP_FOR_VERSION, details::getVndkVersionStr().c_str());
- std::vector<std::string> paths = {HAL_LIBRARY_PATH_ODM, HAL_LIBRARY_PATH_VENDOR,
- halLibPathVndkSp, HAL_LIBRARY_PATH_SYSTEM};
+ std::vector<std::string> paths = {
+ HAL_LIBRARY_PATH_ODM, HAL_LIBRARY_PATH_VENDOR, halLibPathVndkSp,
+#ifndef __ANDROID_VNDK__
+ HAL_LIBRARY_PATH_SYSTEM,
+#endif
+ };
#ifdef LIBHIDL_TARGET_DEBUGGABLE
const char* env = std::getenv("TREBLE_TESTING_OVERRIDE");
@@ -341,10 +393,12 @@
for (const std::string &lib : libs) {
const std::string fullPath = path + lib;
- if (path == HAL_LIBRARY_PATH_SYSTEM) {
+ if (kIsRecovery || path == HAL_LIBRARY_PATH_SYSTEM) {
handle = dlopen(fullPath.c_str(), dlMode);
} else {
+#if !defined(__ANDROID_RECOVERY__)
handle = android_load_sphal_library(fullPath.c_str(), dlMode);
+#endif
}
if (handle == nullptr) {
@@ -436,11 +490,21 @@
HAL_LIBRARY_PATH_VNDK_SP_32BIT_FOR_VERSION, details::getVndkVersionStr().c_str());
static std::vector<std::pair<Arch, std::vector<const char*>>> sAllPaths{
{Arch::IS_64BIT,
- {HAL_LIBRARY_PATH_ODM_64BIT, HAL_LIBRARY_PATH_VENDOR_64BIT,
- halLibPathVndkSp64.c_str(), HAL_LIBRARY_PATH_SYSTEM_64BIT}},
+ {
+ HAL_LIBRARY_PATH_ODM_64BIT, HAL_LIBRARY_PATH_VENDOR_64BIT,
+ halLibPathVndkSp64.c_str(),
+#ifndef __ANDROID_VNDK__
+ HAL_LIBRARY_PATH_SYSTEM_64BIT,
+#endif
+ }},
{Arch::IS_32BIT,
- {HAL_LIBRARY_PATH_ODM_32BIT, HAL_LIBRARY_PATH_VENDOR_32BIT,
- halLibPathVndkSp32.c_str(), HAL_LIBRARY_PATH_SYSTEM_32BIT}}};
+ {
+ HAL_LIBRARY_PATH_ODM_32BIT, HAL_LIBRARY_PATH_VENDOR_32BIT,
+ halLibPathVndkSp32.c_str(),
+#ifndef __ANDROID_VNDK__
+ HAL_LIBRARY_PATH_SYSTEM_32BIT,
+#endif
+ }}};
std::map<std::string, InstanceDebugInfo> map;
for (const auto &pair : sAllPaths) {
Arch arch = pair.first;
@@ -563,7 +627,7 @@
return Void();
}
- void wait() {
+ void wait(bool timeout) {
using std::literals::chrono_literals::operator""s;
if (!mRegisteredForNotifications) {
@@ -574,7 +638,7 @@
}
std::unique_lock<std::mutex> lock(mMutex);
- while(true) {
+ do {
mCondition.wait_for(lock, 1s, [this]{
return mRegistered;
});
@@ -583,9 +647,8 @@
break;
}
- LOG(WARNING) << "Waited one second for " << mInterfaceName << "/" << mInstanceName
- << ". Waiting another...";
- }
+ LOG(WARNING) << "Waited one second for " << mInterfaceName << "/" << mInstanceName;
+ } while (!timeout);
}
// Be careful when using this; after calling reset(), you must always try to retrieve
@@ -615,7 +678,7 @@
private:
const std::string mInterfaceName;
const std::string mInstanceName;
- const sp<IServiceManager1_1>& mSm;
+ sp<IServiceManager1_1> mSm;
std::mutex mMutex;
std::condition_variable mCondition;
bool mRegistered = false;
@@ -626,7 +689,7 @@
void waitForHwService(
const std::string &interface, const std::string &instanceName) {
sp<Waiter> waiter = new Waiter(interface, instanceName, defaultServiceManager1_1());
- waiter->wait();
+ waiter->wait(false /* timeout */);
waiter->done();
}
@@ -665,24 +728,30 @@
const std::string& instance,
bool retry, bool getStub) {
using Transport = ::android::hidl::manager::V1_0::IServiceManager::Transport;
- using ::android::hidl::base::V1_0::IBase;
using ::android::hidl::manager::V1_0::IServiceManager;
sp<Waiter> waiter;
- const sp<IServiceManager1_1> sm = defaultServiceManager1_1();
- if (sm == nullptr) {
- ALOGE("getService: defaultServiceManager() is null");
- return nullptr;
+ sp<IServiceManager1_1> sm;
+ Transport transport = Transport::EMPTY;
+ if (kIsRecovery) {
+ transport = Transport::PASSTHROUGH;
+ } else {
+ sm = defaultServiceManager1_1();
+ if (sm == nullptr) {
+ ALOGE("getService: defaultServiceManager() is null");
+ return nullptr;
+ }
+
+ Return<Transport> transportRet = sm->getTransport(descriptor, instance);
+
+ if (!transportRet.isOk()) {
+ ALOGE("getService: defaultServiceManager()->getTransport returns %s",
+ transportRet.description().c_str());
+ return nullptr;
+ }
+ transport = transportRet;
}
- Return<Transport> transportRet = sm->getTransport(descriptor, instance);
-
- if (!transportRet.isOk()) {
- ALOGE("getService: defaultServiceManager()->getTransport returns %s",
- transportRet.description().c_str());
- return nullptr;
- }
- Transport transport = transportRet;
const bool vintfHwbinder = (transport == Transport::HWBINDER);
const bool vintfPassthru = (transport == Transport::PASSTHROUGH);
@@ -736,7 +805,7 @@
if (waiter != nullptr) {
ALOGI("getService: Trying again for %s/%s...", descriptor.c_str(), instance.c_str());
- waiter->wait();
+ waiter->wait(true /* timeout */);
}
}
@@ -758,7 +827,33 @@
return nullptr;
}
-}; // namespace details
+status_t registerAsServiceInternal(const sp<IBase>& service, const std::string& name) {
+ if (service == nullptr) {
+ return UNEXPECTED_NULL;
+ }
-}; // namespace hardware
-}; // namespace android
+ sp<IServiceManager1_2> sm = defaultServiceManager1_2();
+ if (sm == nullptr) {
+ return INVALID_OPERATION;
+ }
+
+ bool registered = false;
+ Return<void> ret = service->interfaceChain([&](const auto& chain) {
+ registered = sm->addWithChain(name.c_str(), service, chain).withDefault(false);
+ });
+
+ if (!ret.isOk()) {
+ LOG(ERROR) << "Could not retrieve interface chain: " << ret.description();
+ }
+
+ if (registered) {
+ onRegistrationImpl(getDescriptor(service.get()), name);
+ }
+
+ return registered ? OK : UNKNOWN_ERROR;
+}
+
+} // namespace details
+
+} // namespace hardware
+} // namespace android
diff --git a/transport/Static.cpp b/transport/Static.cpp
index cbe6add..45ae27c 100644
--- a/transport/Static.cpp
+++ b/transport/Static.cpp
@@ -17,6 +17,7 @@
// All static variables go here, to control initialization and
// destruction order in the library.
+#include <InternalStatic.h>
#include <hidl/Static.h>
#include <android/hidl/manager/1.0/IServiceManager.h>
@@ -26,9 +27,6 @@
namespace hardware {
namespace details {
-Mutex gDefaultServiceManagerLock;
-sp<android::hidl::manager::V1_0::IServiceManager> gDefaultServiceManager;
-
// Deprecated; kept for ABI compatibility. Use getBnConstructorMap.
BnConstructorMap gBnConstructorMap{};
diff --git a/transport/allocator/1.0/default/Android.bp b/transport/allocator/1.0/default/Android.bp
index fc352c3..1fdfb26 100644
--- a/transport/allocator/1.0/default/Android.bp
+++ b/transport/allocator/1.0/default/Android.bp
@@ -21,6 +21,7 @@
"service.cpp"
],
init_rc: ["android.hidl.allocator@1.0-service.rc"],
+ vintf_fragments: ["android.hidl.allocator@1.0-service.xml"],
shared_libs: [
"android.hidl.allocator@1.0",
diff --git a/transport/allocator/1.0/default/AshmemAllocator.cpp b/transport/allocator/1.0/default/AshmemAllocator.cpp
index 0bd4f81..5cc2eea 100644
--- a/transport/allocator/1.0/default/AshmemAllocator.cpp
+++ b/transport/allocator/1.0/default/AshmemAllocator.cpp
@@ -36,8 +36,8 @@
native_handle_t* handle = native_handle_create(1, 0);
handle->data[0] = fd;
- LOG(WARNING) << "ashmem_create_region(" << size << ") returning hidl_memory(" << handle
- << ", " << size << ")";
+ LOG(VERBOSE) << "ashmem_create_region(" << size << ") returning hidl_memory(" << handle << ", "
+ << size << ")";
return hidl_memory("ashmem", handle, size);
}
diff --git a/transport/allocator/1.0/default/android.hidl.allocator@1.0-service.xml b/transport/allocator/1.0/default/android.hidl.allocator@1.0-service.xml
new file mode 100644
index 0000000..5218241
--- /dev/null
+++ b/transport/allocator/1.0/default/android.hidl.allocator@1.0-service.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="framework">
+ <hal>
+ <name>android.hidl.allocator</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>IAllocator</name>
+ <instance>ashmem</instance>
+ </interface>
+ </hal>
+</manifest>
diff --git a/transport/allocator/1.0/vts/functional/Android.bp b/transport/allocator/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..797d3f8
--- /dev/null
+++ b/transport/allocator/1.0/vts/functional/Android.bp
@@ -0,0 +1,28 @@
+//
+// 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.
+//
+
+cc_test {
+ name: "VtsHidlAllocatorV1_0TargetTest",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: ["VtsHidlAllocatorV1_0TargetTest.cpp"],
+ shared_libs: [
+ "libhidlmemory",
+ ],
+ static_libs: [
+ "android.hidl.allocator@1.0",
+ ],
+}
+
diff --git a/transport/allocator/1.0/vts/functional/Android.mk b/transport/allocator/1.0/vts/functional/Android.mk
new file mode 100644
index 0000000..62880ed
--- /dev/null
+++ b/transport/allocator/1.0/vts/functional/Android.mk
@@ -0,0 +1,22 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := VtsHidlAllocatorV1_0Target
+-include test/vts/tools/build/Android.host_config.mk
diff --git a/transport/allocator/1.0/vts/functional/AndroidTest.xml b/transport/allocator/1.0/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..6ac167f
--- /dev/null
+++ b/transport/allocator/1.0/vts/functional/AndroidTest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS VtsHidlAllocatorV1_0Target test cases">
+ <option name="config-descriptor:metadata" key="plan" value="vts-treble" />
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+ <option name="abort-on-push-failure" value="false"/>
+ <option name="push-group" value="HalHidlTargetTest.push"/>
+ </target_preparer>
+ <multi_target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+ <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+ <option name="test-module-name" value="VtsHidlAllocatorV1_0Target"/>
+ <option name="binary-test-working-directory" value="_32bit::/data/nativetest/" />
+ <option name="binary-test-working-directory" value="_64bit::/data/nativetest64/" />
+ <option name="binary-test-source" value="_32bit::DATA/nativetest/VtsHidlAllocatorV1_0TargetTest/VtsHidlAllocatorV1_0TargetTest" />
+ <option name="binary-test-source" value="_64bit::DATA/nativetest64/VtsHidlAllocatorV1_0TargetTest/VtsHidlAllocatorV1_0TargetTest" />
+ <option name="binary-test-type" value="hal_hidl_gtest"/>
+ <option name="test-timeout" value="5m"/>
+ </test>
+</configuration>
diff --git a/transport/allocator/1.0/vts/functional/VtsHidlAllocatorV1_0TargetTest.cpp b/transport/allocator/1.0/vts/functional/VtsHidlAllocatorV1_0TargetTest.cpp
new file mode 100644
index 0000000..39ce606
--- /dev/null
+++ b/transport/allocator/1.0/vts/functional/VtsHidlAllocatorV1_0TargetTest.cpp
@@ -0,0 +1,139 @@
+/*
+ * 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.
+ */
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+#include <android-base/logging.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <hidlmemory/mapping.h>
+
+using ::android::sp;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hidl::allocator::V1_0::IAllocator;
+using ::android::hidl::memory::V1_0::IMemory;
+
+#define ASSERT_OK(ret) ASSERT_TRUE((ret).isOk())
+#define EXPECT_OK(ret) EXPECT_TRUE((ret).isOk())
+
+class AllocatorEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+ public:
+ virtual void registerTestServices() override { registerTestService<IAllocator>(); }
+
+ static AllocatorEnvironment* instance() {
+ static AllocatorEnvironment* instance = new AllocatorEnvironment();
+ return instance;
+ };
+};
+
+class AllocatorHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+ public:
+ virtual void SetUp() override {
+ allocator = getService<IAllocator>(AllocatorEnvironment::instance());
+ ASSERT_NE(allocator, nullptr);
+ }
+
+ sp<IMemory> expectAllocateSuccess(size_t size) {
+ sp<IMemory> memory;
+ EXPECT_OK(allocator->allocate(size, [&](bool success, const hidl_memory& mem) {
+ ASSERT_TRUE(success) << "Allocate failed for size: " << size;
+ EXPECT_EQ(mem.size(), size)
+ << "Allocated " << size << " but got hidl_memory with size " << mem.size();
+ memory = mapMemory(mem);
+ }));
+ EXPECT_NE(nullptr, memory.get());
+ EXPECT_EQ(memory->getSize(), size)
+ << "Allocated " << size << " but got IMemory with size " << memory->getSize();
+ return memory;
+ }
+
+ std::vector<sp<IMemory>> expectBatchAllocateSuccess(size_t size, size_t count) {
+ std::vector<sp<IMemory>> memories;
+ memories.reserve(count);
+ EXPECT_OK(allocator->batchAllocate(
+ size, count, [&](bool success, const hidl_vec<hidl_memory>& mems) {
+ EXPECT_EQ(count, mems.size());
+
+ for (const hidl_memory& mem : mems) {
+ ASSERT_TRUE(success) << "Allocate failed for size: " << size;
+ EXPECT_EQ(mem.size(), size)
+ << "Allocated " << size << " but got hidl_memory with size " << mem.size();
+ memories.push_back(mapMemory(mem));
+ }
+ }));
+ for (const sp<IMemory>& memory : memories) {
+ EXPECT_NE(nullptr, memory.get());
+ EXPECT_EQ(memory->getSize(), size)
+ << "Allocated " << size << " but got IMemory with size " << memory->getSize();
+ }
+ return memories;
+ }
+
+ sp<IAllocator> allocator;
+};
+
+TEST_F(AllocatorHidlTest, TestAllocateSizes) {
+ for (size_t size : {1, 1023, 1024, 1025, 4096}) {
+ expectAllocateSuccess(size);
+ }
+}
+
+TEST_F(AllocatorHidlTest, TestBatchAllocateSizes) {
+ for (size_t count : {1, 1, 2, 3, 10}) {
+ for (size_t size : {1, 1023, 1024, 1025, 4096}) {
+ expectBatchAllocateSuccess(size, count);
+ }
+ }
+}
+
+TEST_F(AllocatorHidlTest, TestCommit) {
+ constexpr size_t kSize = 1337;
+
+ sp<IMemory> memory = expectAllocateSuccess(kSize);
+ for (int i = 0; i < 100; i++) {
+ EXPECT_OK(memory->read());
+ EXPECT_OK(memory->update());
+ EXPECT_OK(memory->commit());
+
+ EXPECT_OK(memory->read());
+ EXPECT_OK(memory->commit());
+
+ EXPECT_OK(memory->update());
+ EXPECT_OK(memory->commit());
+ }
+
+ for (int i = 0; i < kSize; i++) {
+ EXPECT_OK(memory->readRange(i, kSize));
+ EXPECT_OK(memory->updateRange(i, kSize));
+ EXPECT_OK(memory->commit());
+
+ EXPECT_OK(memory->readRange(i, kSize));
+ EXPECT_OK(memory->commit());
+
+ EXPECT_OK(memory->updateRange(i, kSize));
+ EXPECT_OK(memory->commit());
+ }
+}
+
+int main(int argc, char** argv) {
+ ::testing::AddGlobalTestEnvironment(AllocatorEnvironment::instance());
+ ::testing::InitGoogleTest(&argc, argv);
+ AllocatorEnvironment::instance()->init(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/transport/base/1.0/Android.bp b/transport/base/1.0/Android.bp
index bd2ae49..00d2f2b 100644
--- a/transport/base/1.0/Android.bp
+++ b/transport/base/1.0/Android.bp
@@ -3,7 +3,6 @@
hidl_interface {
name: "android.hidl.base@1.0",
root: "android.hidl",
- core_interface: true,
vndk: {
enabled: true,
},
diff --git a/transport/base/1.0/IBase.hal b/transport/base/1.0/IBase.hal
index e862ec8..22007f0 100644
--- a/transport/base/1.0/IBase.hal
+++ b/transport/base/1.0/IBase.hal
@@ -87,7 +87,10 @@
linkToDeath(death_recipient recipient, uint64_t cookie) generates (bool success);
/*
- * Unregisters a previously registered death recipient.
+ * Unregisters the registered death recipient. If this service was registered
+ * multiple times with the same exact death recipient, this unlinks the most
+ * recently registered one.
+ *
* @param recipient a previously registered hidl_death_recipient callback
* @return success whether the death recipient was unregistered successfully.
*/
diff --git a/transport/current.txt b/transport/current.txt
index a48233c..3794dfe 100644
--- a/transport/current.txt
+++ b/transport/current.txt
@@ -22,3 +22,6 @@
# ABI preserving changes to HALs during Android Q
fcde1d0788066a62d5766f4dc19d4c1ec76967d5ddb636f59ccc66603460bcf8 android.hidl.manager@1.0::IServiceNotification
+
+# Clarification for b/67503915
+ec7fd79ed02dfa85bc499426adae3ebe23ef0524f3cd6957139324b83b18ca4c android.hidl.base@1.0::IBase
diff --git a/transport/include/hidl/ConcurrentMap.h b/transport/include/hidl/ConcurrentMap.h
index 4066869..54c1a32 100644
--- a/transport/include/hidl/ConcurrentMap.h
+++ b/transport/include/hidl/ConcurrentMap.h
@@ -76,6 +76,14 @@
return iter->second;
}
+ size_type eraseLocked(const K& k) { return mMap.erase(k); }
+
+ // the concurrent map must be locked in order to iterate over it
+ iterator begin() { return mMap.begin(); }
+ iterator end() { return mMap.end(); }
+ const_iterator begin() const { return mMap.begin(); }
+ const_iterator end() const { return mMap.end(); }
+
private:
mutable std::mutex mMutex;
std::map<K, V> mMap;
diff --git a/transport/include/hidl/HidlBinderSupport.h b/transport/include/hidl/HidlBinderSupport.h
index 9759af1..a098805 100644
--- a/transport/include/hidl/HidlBinderSupport.h
+++ b/transport/include/hidl/HidlBinderSupport.h
@@ -24,11 +24,10 @@
#include <hidl/HidlSupport.h>
#include <hidl/HidlTransportUtils.h>
#include <hidl/MQDescriptor.h>
-#include <hidl/Static.h>
#include <hwbinder/IBinder.h>
-#include <hwbinder/IPCThreadState.h>
#include <hwbinder/Parcel.h>
-#include <hwbinder/ProcessState.h>
+#include <log/log.h> // TODO(b/65843592): remove. Too many users depending on this transitively.
+
// Defines functions for hidl_string, hidl_version, Status, hidl_vec, MQDescriptor,
// etc. to interact with Parcel.
@@ -49,6 +48,14 @@
wp<::android::hidl::base::V1_0::IBase> mBase;
};
+// ---------------------- hidl_handle
+
+status_t readEmbeddedFromParcel(const hidl_handle &handle,
+ const Parcel &parcel, size_t parentHandle, size_t parentOffset);
+
+status_t writeEmbeddedToParcel(const hidl_handle &handle,
+ Parcel *parcel, size_t parentHandle, size_t parentOffset);
+
// ---------------------- hidl_memory
status_t readEmbeddedFromParcel(const hidl_memory &memory,
@@ -301,6 +308,10 @@
// ---------------------- support for casting interfaces
+// Constructs a binder for this interface and caches it. If it has already been created
+// then it returns it.
+sp<IBinder> getOrCreateCachedBinder(::android::hidl::base::V1_0::IBase* ifacePtr);
+
// Construct a smallest possible binder from the given interface.
// If it is remote, then its remote() will be retrieved.
// Otherwise, the smallest possible BnChild is found where IChild is a subclass of IType
@@ -310,43 +321,7 @@
typename = std::enable_if_t<std::is_same<details::i_tag, typename IType::_hidl_tag>::value>>
sp<IBinder> toBinder(sp<IType> iface) {
IType *ifacePtr = iface.get();
- if (ifacePtr == nullptr) {
- return nullptr;
- }
- if (ifacePtr->isRemote()) {
- return ::android::hardware::IInterface::asBinder(
- static_cast<BpInterface<IType>*>(ifacePtr));
- } else {
- std::string myDescriptor = details::getDescriptor(ifacePtr);
- if (myDescriptor.empty()) {
- // interfaceDescriptor fails
- return nullptr;
- }
-
- // for get + set
- std::unique_lock<std::mutex> _lock = details::gBnMap.lock();
-
- wp<BHwBinder> wBnObj = details::gBnMap.getLocked(ifacePtr, nullptr);
- sp<IBinder> sBnObj = wBnObj.promote();
-
- if (sBnObj == nullptr) {
- auto func = details::getBnConstructorMap().get(myDescriptor, nullptr);
- if (!func) {
- func = details::gBnConstructorMap.get(myDescriptor, nullptr);
- if (!func) {
- return nullptr;
- }
- }
-
- sBnObj = sp<IBinder>(func(static_cast<void*>(ifacePtr)));
-
- if (sBnObj != nullptr) {
- details::gBnMap.setLocked(ifacePtr, static_cast<BHwBinder*>(sBnObj.get()));
- }
- }
-
- return sBnObj;
- }
+ return getOrCreateCachedBinder(ifacePtr);
}
template <typename IType, typename ProxyType, typename StubType>
@@ -374,6 +349,8 @@
int setupBinderPolling();
status_t handleBinderPoll();
+void addPostCommandTask(const std::function<void(void)> task);
+
} // namespace hardware
} // namespace android
diff --git a/transport/include/hidl/ServiceManagement.h b/transport/include/hidl/ServiceManagement.h
index 4df156b..a962034 100644
--- a/transport/include/hidl/ServiceManagement.h
+++ b/transport/include/hidl/ServiceManagement.h
@@ -28,21 +28,21 @@
namespace manager {
namespace V1_0 {
struct IServiceManager;
-}; // namespace V1_0
+} // namespace V1_0
namespace V1_1 {
- struct IServiceManager;
-}; // namespace V1_0
-}; // namespace manager
-}; // namespace hidl
+struct IServiceManager;
+} // namespace V1_1
+namespace V1_2 {
+struct IServiceManager;
+} // namespace V1_2
+} // namespace manager
+} // namespace hidl
namespace hardware {
namespace details {
-// e.x.: android.hardware.foo@1.0, IFoo, default
-void onRegistration(const std::string &packageName,
- const std::string &interfaceName,
- const std::string &instanceName);
+// Will not attempt to start a lazy HAL
// e.x.: android.hardware.foo@1.0::IFoo, default
void waitForHwService(const std::string &interface, const std::string &instanceName);
@@ -57,12 +57,16 @@
sp<::android::hidl::base::V1_0::IBase> getRawServiceInternal(const std::string& descriptor,
const std::string& instance,
bool retry, bool getStub);
-};
+
+status_t registerAsServiceInternal(const sp<::android::hidl::base::V1_0::IBase>& service,
+ const std::string& name);
+} // namespace details
// 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_1::IServiceManager> defaultServiceManager1_1();
+sp<::android::hidl::manager::V1_2::IServiceManager> defaultServiceManager1_2();
sp<::android::hidl::manager::V1_0::IServiceManager> getPassthroughServiceManager();
sp<::android::hidl::manager::V1_1::IServiceManager> getPassthroughServiceManager1_1();
@@ -77,8 +81,8 @@
details::preloadPassthroughService(I::descriptor);
}
-}; // namespace hardware
-}; // namespace android
+} // namespace hardware
+} // namespace android
#endif // ANDROID_HARDWARE_ISERVICE_MANAGER_H
diff --git a/transport/include/hidl/Static.h b/transport/include/hidl/Static.h
index 0522e44..b50c173 100644
--- a/transport/include/hidl/Static.h
+++ b/transport/include/hidl/Static.h
@@ -17,6 +17,9 @@
// All static variables go here, to control initialization and
// destruction order in the library.
+#ifndef ANDROID_HARDWARE_HIDL_STATIC_H
+#define ANDROID_HARDWARE_HIDL_STATIC_H
+
#include <functional>
#include <android/hidl/base/1.0/IBase.h>
@@ -44,8 +47,6 @@
// For HidlBinderSupport and autogenerated code
// value function receives reinterpret_cast<void *>(static_cast<IFoo *>(foo)),
// returns sp<IBinder>
-// deprecated; use getBnConstructorMap instead.
-extern BnConstructorMap gBnConstructorMap;
BnConstructorMap& getBnConstructorMap();
using BsConstructorMap = ConcurrentMap<std::string,
@@ -53,9 +54,9 @@
// For HidlPassthroughSupport and autogenerated code
// value function receives reinterpret_cast<void *>(static_cast<IFoo *>(foo)),
// returns sp<IBase>
-// deprecated; use getBsConstructorMap instead.
-extern BsConstructorMap gBsConstructorMap;
BsConstructorMap& getBsConstructorMap();
} // namespace details
} // namespace hardware
} // namespace android
+
+#endif
diff --git a/transport/manager/1.0/Android.bp b/transport/manager/1.0/Android.bp
index e4a120b..869c58e 100644
--- a/transport/manager/1.0/Android.bp
+++ b/transport/manager/1.0/Android.bp
@@ -3,7 +3,6 @@
hidl_interface {
name: "android.hidl.manager@1.0",
root: "android.hidl",
- core_interface: true,
vndk: {
enabled: true,
},
diff --git a/transport/manager/1.1/Android.bp b/transport/manager/1.1/Android.bp
index cde68a7..407dfa3 100644
--- a/transport/manager/1.1/Android.bp
+++ b/transport/manager/1.1/Android.bp
@@ -3,7 +3,6 @@
hidl_interface {
name: "android.hidl.manager@1.1",
root: "android.hidl",
- core_interface: true,
vndk: {
enabled: true,
},
diff --git a/transport/manager/1.2/Android.bp b/transport/manager/1.2/Android.bp
new file mode 100644
index 0000000..3f02f78
--- /dev/null
+++ b/transport/manager/1.2/Android.bp
@@ -0,0 +1,20 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hidl.manager@1.2",
+ root: "android.hidl",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "IClientCallback.hal",
+ "IServiceManager.hal",
+ ],
+ interfaces: [
+ "android.hidl.base@1.0",
+ "android.hidl.manager@1.0",
+ "android.hidl.manager@1.1",
+ ],
+ gen_java: true,
+}
+
diff --git a/transport/manager/1.2/IClientCallback.hal b/transport/manager/1.2/IClientCallback.hal
new file mode 100644
index 0000000..1189e44
--- /dev/null
+++ b/transport/manager/1.2/IClientCallback.hal
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+package android.hidl.manager@1.2;
+
+interface IClientCallback {
+ /**
+ * This is called when there is a transition between having >= 1 clients and having 0 clients
+ * (or vice versa).
+ *
+ * @param registered binder 'server' registered with IServiceManager's registerClientCallback
+ * @param hasClients whether there are currently clients
+ * true - when there are >= 1 clients. This must be called as soon as IServiceManager::get
+ * is called (no race).
+ * false - when there are 0 clients. This may be delayed if it is thought that another
+ * may be used again soon.
+ */
+ oneway onClients(interface registered, bool hasClients);
+};
diff --git a/transport/manager/1.2/IServiceManager.hal b/transport/manager/1.2/IServiceManager.hal
new file mode 100644
index 0000000..ae3fdfd
--- /dev/null
+++ b/transport/manager/1.2/IServiceManager.hal
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+package android.hidl.manager@1.2;
+
+import @1.1::IServiceManager;
+
+import IClientCallback;
+
+interface IServiceManager extends @1.1::IServiceManager {
+ // TODO(b/66921961): additional functionality for the next release:
+ // - Better notifications (onRegistration will contain the interface)
+ // - Method to list interfaces in the manifest (for b/76108617, since if they are
+ // lazy, they will no longer show up in listByInterface)
+
+ /**
+ * Adds a callback that must be called when the specified server has no clients.
+ *
+ * If the service has clients at the time of registration, the callback is called with
+ * hasClients true. After that, it is called based on the changes in clientele.
+ *
+ * @param server non-null service waiting to have no clients
+ * @param cb non-null callback to call when there are no clients
+ * @return success
+ * true on success
+ * false if either
+ * - the server or cb parameters are null
+ * - this is called by a process other than the server process
+ */
+ registerClientCallback(interface server, IClientCallback cb) generates (bool success);
+
+ /**
+ * Removes a callback previously registered with registerClientCallback.
+ *
+ * If server is null, then this must remove the cb from all matching services.
+ *
+ * @param server service registered with registerClientCallback
+ * @param cb non-null callback to remove
+ * @return success
+ * true if the server(s) have been removed
+ * false if cb is null or if the client callback or server could not be found
+ */
+ unregisterClientCallback(interface server, IClientCallback cb) generates (bool success);
+
+ /**
+ * Exactly the same as @1.0::IServiceManager.add, but the interfaceChain of the service is
+ * provided in the same call.
+ *
+ * @param name Instance name. Must also be used to retrieve service.
+ * @param service Handle to registering service.
+ * @param chain service->interfaceChain
+ *
+ * @return success Whether or not the service was registered.
+ */
+ addWithChain(string name, interface service, vec<string> chain) generates (bool success);
+};
diff --git a/transport/safe_union/1.0/Android.bp b/transport/safe_union/1.0/Android.bp
new file mode 100644
index 0000000..0fc2305
--- /dev/null
+++ b/transport/safe_union/1.0/Android.bp
@@ -0,0 +1,17 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hidl.safe_union@1.0",
+ root: "android.hidl",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "types.hal",
+ ],
+ types: [
+ "Monostate",
+ ],
+ gen_java: true,
+}
+
diff --git a/transport/safe_union/1.0/types.hal b/transport/safe_union/1.0/types.hal
new file mode 100644
index 0000000..bc3dbc2
--- /dev/null
+++ b/transport/safe_union/1.0/types.hal
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+package android.hidl.safe_union@1.0;
+
+/**
+ * Unit type easily available to be used with safe_union.
+ *
+ * Example usage:
+ *
+ * safe_union MaybeFoo {
+ * Monostate no_init;
+ * Foo foo;
+ * };
+ */
+struct Monostate {};
diff --git a/transport/token/1.0/utils/Android.bp b/transport/token/1.0/utils/Android.bp
index fcb1613..d706cf6 100644
--- a/transport/token/1.0/utils/Android.bp
+++ b/transport/token/1.0/utils/Android.bp
@@ -19,6 +19,7 @@
vndk: {
enabled: true,
},
+ double_loadable: true,
srcs: [
"HybridInterface.cpp",
diff --git a/transport/token/1.0/utils/include/hidl/HybridInterface.h b/transport/token/1.0/utils/include/hidl/HybridInterface.h
index 984555e..595c2e3 100644
--- a/transport/token/1.0/utils/include/hidl/HybridInterface.h
+++ b/transport/token/1.0/utils/include/hidl/HybridInterface.h
@@ -240,6 +240,10 @@
onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
if (code == GET_HAL_TOKEN) {
+ if (!data.enforceInterface(BaseInterface::getInterfaceDescriptor())) {
+ return BAD_TYPE;
+ }
+
HalToken token;
bool result;
result = createHalToken(mBase, &token);
diff --git a/update-makefiles.sh b/update-makefiles.sh
index fd0a23c..cf13c83 100755
--- a/update-makefiles.sh
+++ b/update-makefiles.sh
@@ -5,7 +5,9 @@
android.hidl.base@1.0
android.hidl.manager@1.0
android.hidl.manager@1.1
+ android.hidl.manager@1.2
android.hidl.memory@1.0
+ android.hidl.safe_union@1.0
android.hidl.token@1.0
)
diff --git a/vintfdata/Android.mk b/vintfdata/Android.mk
index bc7a55a..232ef6f 100644
--- a/vintfdata/Android.mk
+++ b/vintfdata/Android.mk
@@ -17,6 +17,10 @@
LOCAL_PATH := $(call my-dir)
FRAMEWORK_MANIFEST_INPUT_FILES := $(LOCAL_PATH)/manifest.xml
+# TODO(b/110487738): replace with vintf_fragment
+ifdef USE_VR_FLINGER
+ FRAMEWORK_MANIFEST_INPUT_FILES += $(LOCAL_PATH)/manifest_vr_hwc.xml
+endif
ifdef DEVICE_FRAMEWORK_MANIFEST_FILE
FRAMEWORK_MANIFEST_INPUT_FILES += $(DEVICE_FRAMEWORK_MANIFEST_FILE)
endif
@@ -62,15 +66,6 @@
GEN := $(local-generated-sources-dir)/manifest.xml
-$(GEN): PRIVATE_FLAGS :=
-
-ifeq ($(PRODUCT_ENFORCE_VINTF_MANIFEST),true)
-ifdef BUILT_VENDOR_MATRIX
-$(GEN): $(BUILT_VENDOR_MATRIX)
-$(GEN): PRIVATE_FLAGS += -c "$(BUILT_VENDOR_MATRIX)"
-endif
-endif
-
$(GEN): PRIVATE_VINTF_VNDK_VERSION := $(VINTF_VNDK_VERSION)
$(GEN): PRIVATE_FRAMEWORK_MANIFEST_INPUT_FILES := $(FRAMEWORK_MANIFEST_INPUT_FILES)
$(GEN): $(FRAMEWORK_MANIFEST_INPUT_FILES) $(HOST_OUT_EXECUTABLES)/assemble_vintf
@@ -78,7 +73,7 @@
PLATFORM_SYSTEMSDK_VERSIONS="$(PLATFORM_SYSTEMSDK_VERSIONS)" \
$(HOST_OUT_EXECUTABLES)/assemble_vintf \
-i $(call normalize-path-list,$(PRIVATE_FRAMEWORK_MANIFEST_INPUT_FILES)) \
- -o $@ $(PRIVATE_FLAGS)
+ -o $@
LOCAL_PREBUILT_MODULE_FILE := $(GEN)
include $(BUILD_PREBUILT)
@@ -86,4 +81,4 @@
VINTF_VNDK_VERSION :=
FRAMEWORK_MANIFEST_INPUT_FILES :=
-DEVICE_MATRIX_INPUT_FILE :=
+DEVICE_MATRIX_INPUT_FILE :=
\ No newline at end of file
diff --git a/vintfdata/manifest.xml b/vintfdata/manifest.xml
index 51d68eb..27919d3 100644
--- a/vintfdata/manifest.xml
+++ b/vintfdata/manifest.xml
@@ -2,22 +2,13 @@
<hal>
<name>android.hidl.manager</name>
<transport>hwbinder</transport>
- <version>1.1</version>
+ <version>1.2</version>
<interface>
<name>IServiceManager</name>
<instance>default</instance>
</interface>
</hal>
<hal>
- <name>android.hidl.allocator</name>
- <transport>hwbinder</transport>
- <version>1.0</version>
- <interface>
- <name>IAllocator</name>
- <instance>ashmem</instance>
- </interface>
- </hal>
- <hal>
<name>android.hidl.memory</name>
<transport arch="32+64">passthrough</transport>
<version>1.0</version>
@@ -80,25 +71,6 @@
<instance>default</instance>
</interface>
</hal>
- <hal>
- <name>android.hardware.graphics.composer</name>
- <transport>hwbinder</transport>
- <version>2.1</version>
- <interface>
- <name>IComposer</name>
- <instance>vr</instance>
- </interface>
- </hal>
- <hal>
- <name>android.hardware.health</name>
- <transport>hwbinder</transport>
- <version>2.0</version>
- <interface>
- <name>IHealth</name>
- <!-- The backup instance provided by healthd. -->
- <instance>backup</instance>
- </interface>
- </hal>
<hal format="native">
<name>netutils-wrapper</name>
<!--
diff --git a/vintfdata/manifest_healthd_exclude.xml b/vintfdata/manifest_healthd_exclude.xml
deleted file mode 100644
index b4060f0..0000000
--- a/vintfdata/manifest_healthd_exclude.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<!--
- Include this file to DEVICE_FRAMEWORK_MANIFEST_FILE to disable
- having an healthd on the device which is not needed if you have
- an alternative implementation like the following:
- (1) Device has android.hardware.health@2.0-service.override
- (2) Device has android.hardware.health@2.0-service.<device>, which
- contains the following:
- overrides: ["healthd"]
--->
-<manifest version="1.0" type="framework">
- <hal format="hidl" override="true">
- <name>android.hardware.health</name>
- <transport>hwbinder</transport>
- </hal>
-</manifest>
diff --git a/vintfdata/manifest_vr_hwc.xml b/vintfdata/manifest_vr_hwc.xml
new file mode 100644
index 0000000..1068cac
--- /dev/null
+++ b/vintfdata/manifest_vr_hwc.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="framework">
+ <hal>
+ <name>android.hardware.graphics.composer</name>
+ <transport>hwbinder</transport>
+ <version>2.1</version>
+ <interface>
+ <name>IComposer</name>
+ <instance>vr</instance>
+ </interface>
+ </hal>
+</manifest>