Tests for Return crashes.
am: 9cafed562a
Change-Id: I8e9de90ee15ecf7d4d96bf44902700d3c5ee83ce
diff --git a/Android.bp b/Android.bp
index 4bd5eb3..dbc9fa2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -54,3 +54,60 @@
"-g",
],
}
+
+cc_defaults {
+ name: "libhidlbase-combined-impl",
+
+ defaults: [
+ "libhwbinder-impl-shared-libs",
+ "libhidlbase-impl-shared-libs",
+ "libhidltransport-impl-shared-libs",
+ ],
+
+ whole_static_libs: [
+ "libhidlbase-impl-internal",
+ "libhidltransport-impl-internal",
+ ],
+}
+
+cc_library {
+ name: "libhidlbase",
+ defaults: ["libhidlbase-combined-impl"],
+ recovery_available: true,
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ support_system_process: true,
+ },
+ whole_static_libs: [
+ "libhwbinder-impl-internal",
+ ],
+}
+
+// Only libhwbinder_benchmark needs to have pgo enabled. When all places
+// support having PGO selectively enabled, all places can use libhwbinder.
+//
+// http://b/77320844
+cc_library {
+ name: "libhidlbase_pgo",
+ defaults: [
+ "libhidlbase-combined-impl",
+ "hwbinder_benchmark_pgo",
+ ],
+ whole_static_libs: [
+ "libhwbinder_pgo-impl-internal",
+ ],
+}
+
+// WARNING: deprecated
+// This library is no longer required, and dependencies should be taken
+// on libhidlbase instead.
+cc_library {
+ name: "libhidltransport",
+ recovery_available: true,
+ vendor_available: true,
+ vndk: {
+ enabled: true,
+ support_system_process: true,
+ },
+}
diff --git a/base/Android.bp b/base/Android.bp
index 359ac91..8fe2702 100644
--- a/base/Android.bp
+++ b/base/Android.bp
@@ -12,15 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-cc_library {
- name: "libhidlbase",
- recovery_available: true,
- vendor_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- },
- defaults: ["libhidl-defaults"],
+cc_defaults {
+ name: "libhidlbase-impl-shared-libs",
shared_libs: [
"libbase",
"libcutils",
@@ -31,6 +24,16 @@
"libutils",
"libcutils", // for native_handle.h
],
+}
+
+cc_library {
+ name: "libhidlbase-impl-internal",
+ vendor_available: true,
+ recovery_available: true,
+ defaults: [
+ "libhidlbase-impl-shared-libs",
+ "libhidl-defaults"
+ ],
local_include_dirs: ["include"],
export_include_dirs: ["include"],
diff --git a/base/HidlSupport.cpp b/base/HidlSupport.cpp
index c15d326..f97f216 100644
--- a/base/HidlSupport.cpp
+++ b/base/HidlSupport.cpp
@@ -57,7 +57,7 @@
}
// move constructor.
-hidl_handle::hidl_handle(hidl_handle&& other) noexcept {
+hidl_handle::hidl_handle(hidl_handle&& other) noexcept : hidl_handle() {
mOwnsHandle = false;
*this = std::move(other);
}
diff --git a/base/include/hidl/HidlSupport.h b/base/include/hidl/HidlSupport.h
index adf86a7..5be02b5 100644
--- a/base/include/hidl/HidlSupport.h
+++ b/base/include/hidl/HidlSupport.h
@@ -350,19 +350,7 @@
*this = std::move(other);
}
- hidl_vec(const std::initializer_list<T> list) : hidl_vec() {
- if (list.size() > UINT32_MAX) {
- details::logAlwaysFatal("hidl_vec can't hold more than 2^32 elements.");
- }
- mSize = static_cast<uint32_t>(list.size());
- mBuffer = new T[mSize]();
- mOwnsBuffer = true;
-
- size_t idx = 0;
- for (auto it = list.begin(); it != list.end(); ++it) {
- mBuffer[idx++] = *it;
- }
- }
+ hidl_vec(const std::initializer_list<T> list) : hidl_vec() { *this = list; }
hidl_vec(const std::vector<T> &other) : hidl_vec() {
*this = other;
@@ -467,7 +455,7 @@
delete[] mBuffer;
}
mSize = static_cast<uint32_t>(list.size());
- mBuffer = new T[mSize];
+ mBuffer = new T[mSize]();
mOwnsBuffer = true;
size_t idx = 0;
diff --git a/transport/Android.bp b/transport/Android.bp
index 6518177..50f277e 100644
--- a/transport/Android.bp
+++ b/transport/Android.bp
@@ -16,30 +16,43 @@
name: "android.hidl",
}
-cc_library {
- name: "libhidltransport",
- recovery_available: true,
- vendor_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- },
- defaults: [
- "libhidl-defaults",
- "hidl-module-defaults",
- ],
+cc_defaults {
+ name: "libhidltransport-impl-shared-libs",
shared_libs: [
"libbase",
"liblog",
"libutils",
- "libhidlbase",
"libhwbinder",
"libcutils",
- "libvndksupport",
+ "libvndksupport"
],
export_shared_lib_headers: [
"libutils",
- "libhidlbase",
+ ],
+
+ target: {
+ recovery: {
+ exclude_shared_libs: ["libvndksupport"],
+ },
+ },
+}
+
+cc_library_static {
+ name: "libhidltransport-impl-internal",
+ vendor_available: true,
+ recovery_available: true,
+
+ defaults: [
+ "hidl-module-defaults",
+ "libhidl-defaults",
+ "libhidltransport-impl-shared-libs",
+ ],
+
+ static_libs: [
+ "libhidlbase-impl-internal",
+ ],
+ export_static_lib_headers: [
+ "libhidlbase-impl-internal",
],
export_include_dirs: ["include"],
@@ -81,10 +94,4 @@
cflags: ["-DENFORCE_VINTF_MANIFEST"]
},
},
-
- target: {
- recovery: {
- exclude_shared_libs: ["libvndksupport"],
- },
- },
}
diff --git a/transport/HidlBinderSupport.cpp b/transport/HidlBinderSupport.cpp
index f3af124..02d10d0 100644
--- a/transport/HidlBinderSupport.cpp
+++ b/transport/HidlBinderSupport.cpp
@@ -171,22 +171,6 @@
return status;
}
- // Skip over fat response headers. Not used (or propagated) in native code.
- if (exception == Status::EX_HAS_REPLY_HEADER) {
- // Note that the header size includes the 4 byte size field.
- const int32_t header_start = parcel.dataPosition();
- int32_t header_size;
- status = parcel.readInt32(&header_size);
- if (status != OK) {
- s->setFromStatusT(status);
- return status;
- }
- parcel.setDataPosition(header_start + header_size);
- // And fat response headers are currently only used when there are no
- // exceptions, so act like there was no error.
- exception = Status::EX_NONE;
- }
-
if (exception == Status::EX_NONE) {
*s = Status::ok();
return status;
diff --git a/transport/token/1.0/utils/Android.bp b/transport/token/1.0/utils/Android.bp
index 5a8d51c..cdbdd97 100644
--- a/transport/token/1.0/utils/Android.bp
+++ b/transport/token/1.0/utils/Android.bp
@@ -25,22 +25,16 @@
"HybridInterface.cpp",
],
- header_libs: [
- "libbinder_headers",
- ],
-
shared_libs: [
- "libutils",
- "liblog",
- "libhidlbase",
"android.hidl.token@1.0",
- ],
-
- export_header_lib_headers: [
- "libbinder_headers",
+ "libbinder",
+ "libhidlbase",
+ "liblog",
+ "libutils",
],
export_shared_lib_headers: [
+ "libbinder",
"libhidlbase",
],
diff --git a/transport/token/1.0/utils/include/hidl/HybridInterface.h b/transport/token/1.0/utils/include/hidl/HybridInterface.h
index 595c2e3..125d5e8 100644
--- a/transport/token/1.0/utils/include/hidl/HybridInterface.h
+++ b/transport/token/1.0/utils/include/hidl/HybridInterface.h
@@ -23,6 +23,9 @@
#include <binder/Parcel.h>
#include <hidl/HidlSupport.h>
+#include <cinttypes>
+#include <variant>
+
/**
* Hybrid Interfaces
* =================
@@ -47,50 +50,130 @@
*
* To demonstrate how this is done, here is an example. Suppose `INTERFACE` is
* `IFoo` and `HALINTERFACE` is `HFoo`. The required steps are:
- * 1. Use DECLARE_HYBRID_META_INTERFACE instead of DECLARE_META_INTERFACE in the
- * definition of `IFoo`. The usage is
- * DECLARE_HYBRID_META_INTERFACE(IFoo, HFoo)
- * inside the body of `IFoo`.
+ * 1. Use `DECLARE_HYBRID_META_INTERFACE` instead of `DECLARE_META_INTERFACE` in
+ * the declaration of `IFoo`. `DECLARE_HYBRID_META_INTERFACE` takes an
+ * additional argument that is the hidl interface to be converted into a
+ * binder interface. Example:
+ * Change from `DECLARE_META_INTERFACE(Foo)`
+ * to `DECLARE_HYBRID_META_INTERFACE(Foo, HFoo)`
* 2. Create a converter class that derives from
- * `H2BConverter<HFoo, IFoo, BnFoo>`. Let us call this `H2BFoo`.
+ * `H2BConverter<HFoo, BnFoo>`. Let us call this `H2BFoo`.
* 3. Add the following constructor in `H2BFoo` that call the corresponding
* constructors in `H2BConverter`:
- * H2BFoo(const sp<HalInterface>& base) : CBase(base) {}
- * Note: `CBase = H2BConverter<HFoo, IFoo, BnFoo>` and `HalInterface = HFoo`
- * are member typedefs of `H2BConverter<HFoo, IFoo, BnFoo>`, so the above
- * line can be copied into `H2BFoo`.
+ * `H2BFoo(const sp<HalInterface>& base) : CBase(base) {}`
+ * Note: `CBase = H2BConverter<HFoo, BnFoo>` and `HalInterface = HFoo` are
+ * member typedefs of `H2BConverter<HFoo, BnFoo>`, so the above line can be
+ * copied verbatim into `H2BFoo`.
* 4. Implement `IFoo` in `H2BFoo` on top of `HFoo`. `H2BConverter` provides a
* protected `mBase` of type `sp<HFoo>` that can be used to access the `HFoo`
- * instance. (There is also a public function named `getHalInterface()` that
- * returns `mBase`.)
+ * instance. (There is also a public function named `getBase()` that returns
+ * `mBase`.)
* 5. Create a hardware proxy class that derives from
* `HpInterface<BpFoo, H2BFoo>`. Name this class `HpFoo`. (This name cannot
* deviate. See step 8 below.)
* 6. Add the following constructor to `HpFoo`:
- * HpFoo(const sp<IBinder>& base): PBase(base) {}
+ * `HpFoo(const sp<IBinder>& base): PBase(base) {}`
* Note: `PBase` a member typedef of `HpInterface<BpFoo, H2BFoo>` that is
* equal to `HpInterface<BpFoo, H2BFoo>` itself, so the above line can be
* copied verbatim into `HpFoo`.
- * 7. Delegate all functions in `HpFoo` that come from `IFoo` except
- * `getHalInterface` to the protected member `mBase`,
- * which is defined in `HpInterface<BpFoo, H2BFoo>` (hence in `HpFoo`) with
- * type `IFoo`. (There is also a public function named `getBaseInterface()`
- * that returns `mBase`.)
- * 8. Replace the existing `IMPLEMENT_META_INTERFACE` for INTERFACE by
- * `IMPLEMENT_HYBRID_META_INTERFACE`. Note that this macro relies on the
- * exact naming of `HpFoo`, where `Foo` comes from the interface name `IFoo`.
- * An example usage is
- * IMPLEMENT_HYBRID_META_INTERFACE(IFoo, HFoo, "example.interface.foo");
+ * 7. Delegate all functions in `HpFoo` that come from `IFoo` (except those that
+ * are defined by the macro `DECLARE_HYBRID_META_INTERFACE`) to the protected
+ * member `mBase`. `mBase` is defined in `HpInterface<BpFoo, H2BFoo>` (hence
+ * in `HpFoo`) with type `IFoo`. There is also a public function named
+ * `getBase()` that returns `mBase`.
+ * 8. Replace the existing `IMPLEMENT_META_INTERFACE` for `IFoo` by
+ * `IMPLEMENT_HYBRID_META_INTERFACE`. This macro assumes that the subclass of
+ * `HpInterface` for `IFoo` is named `HpFoo`.
*
- * `GETTOKEN` Template Argument
- * ============================
+ * After the hybrid interface has been put in place properly, it can be used to
+ * do the following tasks:
+ * 1. Create an `IFoo` instance from an `HFoo` by passing `sp<HFoo>` to
+ * the constructor of `H2BFoo`.
+ * 2. Retrieve an `HFoo` from an `HpFoo` instance by calling
+ * `HpFoo::getHalInterface<HFoo>()`. This function may return `nullptr` if
+ * the `HpFoo` object is not backed by `HFoo`. The template parameter is
+ * required because `HpFoo` in fact may be backed by multiple H2B converter
+ * classes.
*
- * Following the instructions above, `H2BConverter` and `HpInterface` would use
- * `transact()` to send over tokens, with `code` (the first argument of
- * `transact()`) equal to `DEFAULT_GET_HAL_TOKEN_TRANSACTION_CODE`. If this
- * value clashes with other values already in use in the `Bp` class, it can be
- * changed by supplying the last optional template argument to `H2BConverter`
- * and `HpInterface`.
+ * Multiple H2B Converters
+ * =======================
+ *
+ * Because the system may support multiple versions of hidl interfaces for the
+ * same object, one binder interface may correspond to multiple H2B converters.
+ * The hybrid interface is designed to handle this as
+ * well---`DECLARE_HYBRID_META_INTERFACE` and `HpInterface` can take a variable
+ * number of arguments.
+ *
+ * As a concrete example, suppose `IFoo` is a binder interface that corresponds
+ * to two hidl interfaces `HFoo1` and `HFoo2`. That means `HpFoo`, the hybrid
+ * interface presenting `IFoo`, may be backed by `HFoo1` or `HFoo2`. This is
+ * achievable by
+ *
+ * - Replacing `DECLARE_META_INTERFACE(Foo)` by
+ * `DECLARE_HYBRID_META_INTERFACE(Foo, HFoo1, HFoo2)` in the declaration of
+ * `IFoo`.
+ * - Creating `H2BFoo1` as a subclass of `H2BConverter<HFoo1, BnFoo>`;
+ * - Creating `H2BFoo2` as a subclass of `H2BConverter<HFoo2, BnFoo>`; and
+ * - Creating `HpFoo` as a subclass of `HpInterface<BpFoo, H2BFoo1, H2BFoo2>`.
+ *
+ * It is important that `HFoo1` and `HFoo2` are different hidl interfaces. [The
+ * actual requirement is that for each pair `<HFoo, IFoo>`, there can be only
+ * one subclass of `H2BConverter<HFoo, BnFoo>`.]
+ *
+ * As mentioned in the previous section, `HpFoo::getHalInterface` requires a
+ * template argument because it must be able to return different hidl
+ * interface types based on which hidl interface is being used. The user of
+ * `HpFoo` can query the type of the underlying hidl interface by calling
+ * `HpFoo::getHalIndex()`. The return value is a 1-based index into the list of
+ * all the supported hidl interfaces. In the example with 2 hidl interfaces
+ * `HFoo1` and `HFoo2`, index 1 corresponds to `HFoo1` and index 2 corresponds
+ * to `HFoo2`. A typical code block that accesses the underlying hidl interface
+ * of would look like this:
+ *
+ * void someFunction(const sp<IFoo> &foo) {
+ *
+ * switch (foo->getHalIndex()) {
+ * case 1: {
+ * sp<HFoo1> hFoo1 = foo->getHalInterface<HFoo1>();
+ * ...
+ * break;
+ * }
+ * case 2: {
+ * sp<HFoo2> hFoo2 = foo->getHalInterface<HFoo2>();
+ * ...
+ * break;
+ * }
+ * default: // Not backed by a hidl interface.
+ * // Alternatively, "case 0:" can be used.
+ * }
+ *
+ * }
+ *
+ * Error State
+ * ===========
+ *
+ * A corrupted transaction may cause an `HpInterface` to be in an error state.
+ * This could cause `getHalInterface<ExpectedHalInterface>()` to return
+ * `nullptr` even though `getHalIndex()` returns a non-zero index and
+ * `ExpectedHalInterface` is the corresponding hidl interface. It is therefore
+ * recommended that a null check be performed on the return value of
+ * `getHalInterface` before using it.
+ *
+ * DECLARE_HYBRID_META_INTERFACE_WITH_CODE
+ * =======================================
+ *
+ * `H2BConverter` and `HpInterface` use `transact()` to send over tokens with
+ * the transaction code (the first argument of `transact()`) equal to `_GHT`,
+ * which is defined as a global constant named
+ * `DEFAULT_GET_HAL_TOKEN_TRANSACTION_CODE`.
+ *
+ * In the rare occasion that this value clashes with other values already used
+ * by the `Bp` class and modifying the `Bp` class is difficult, the
+ * "GET_HAL_TOKEN" transaction code can be changed to a different value simply
+ * by replacing `DECLARE_HYBRID_META_INTERFACE` with
+ * `DECLARE_HYBRID_META_INTERFACE_WITH_CODE` in the declaration of the base
+ * interface and supplying the new transaction code in the first argument of
+ * this macro.
*
*/
@@ -106,23 +189,19 @@
bool createHalToken(const sp<HInterface>& interface, HalToken* token);
bool deleteHalToken(const HalToken& token);
-template <
- typename HINTERFACE,
- typename INTERFACE,
- typename BNINTERFACE,
- uint32_t GETTOKEN = DEFAULT_GET_HAL_TOKEN_TRANSACTION_CODE>
+template <typename HINTERFACE,
+ typename BNINTERFACE>
class H2BConverter : public BNINTERFACE {
public:
- typedef H2BConverter<HINTERFACE, INTERFACE, BNINTERFACE, GETTOKEN> CBase; // Converter Base
- typedef INTERFACE BaseInterface;
+ typedef H2BConverter<HINTERFACE, BNINTERFACE> CBase; // Converter Base
+ typedef typename BNINTERFACE::BaseInterface BaseInterface;
typedef HINTERFACE HalInterface;
- static constexpr uint32_t GET_HAL_TOKEN = GETTOKEN;
+ typedef typename BaseInterface::HalVariant HalVariant;
+ using BaseInterface::sGetHalTokenTransactionCode;
- H2BConverter(const sp<HalInterface>& base) : mBase(base) {}
+ H2BConverter(const sp<HalInterface>& base) : mBase{base} {}
virtual status_t onTransact(uint32_t code,
const Parcel& data, Parcel* reply, uint32_t flags = 0);
- virtual sp<HalInterface> getHalInterface() { return mBase; }
- HalInterface* getBaseInterface() { return mBase.get(); }
virtual status_t linkToDeath(
const sp<IBinder::DeathRecipient>& recipient,
void* cookie = nullptr,
@@ -132,9 +211,13 @@
void* cookie = nullptr,
uint32_t flags = 0,
wp<IBinder::DeathRecipient>* outRecipient = nullptr);
+ virtual HalVariant getHalVariant() const override { return { mBase }; }
+ HalInterface* getBase() { return mBase.get(); }
protected:
sp<HalInterface> mBase;
+
+private:
struct Obituary : public hardware::hidl_death_recipient {
wp<IBinder::DeathRecipient> recipient;
void* cookie;
@@ -168,78 +251,174 @@
};
std::mutex mObituariesLock;
std::vector<sp<Obituary> > mObituaries;
+
+ template <size_t Index = std::variant_size_v<HalVariant> - 1>
+ static constexpr size_t _findIndex() {
+ if constexpr (Index == 0) {
+ return Index;
+ } else if constexpr (
+ std::is_same_v<
+ std::variant_alternative_t<Index, HalVariant>,
+ sp<HalInterface>>) {
+ return Index;
+ } else {
+ return _findIndex<Index - 1>();
+ }
+ }
+
+ static constexpr size_t sHalIndex = _findIndex<>();
+ static_assert(sHalIndex != 0,
+ "H2BConverter from an unrecognized HAL interface.");
};
-template <
- typename BPINTERFACE,
- typename CONVERTER,
- uint32_t GETTOKEN = DEFAULT_GET_HAL_TOKEN_TRANSACTION_CODE>
+template <typename BPINTERFACE, typename CONVERTER, typename... CONVERTERS>
class HpInterface : public CONVERTER::BaseInterface {
public:
- typedef HpInterface<BPINTERFACE, CONVERTER, GETTOKEN> PBase; // Proxy Base
+ typedef HpInterface<BPINTERFACE, CONVERTER, CONVERTERS...> PBase; // Proxy Base
typedef typename CONVERTER::BaseInterface BaseInterface;
- typedef typename CONVERTER::HalInterface HalInterface;
- static constexpr uint32_t GET_HAL_TOKEN = GETTOKEN;
+ typedef typename BaseInterface::HalVariant HalVariant;
+ using BaseInterface::sGetHalTokenTransactionCode;
explicit HpInterface(const sp<IBinder>& impl);
- virtual sp<HalInterface> getHalInterface() { return mHal; }
- BaseInterface* getBaseInterface() { return mBase.get(); }
+ BaseInterface* getBase() { return mBase.get(); }
+ virtual HalVariant getHalVariant() const override { return mHalVariant; }
protected:
- IBinder* mImpl;
+ IBinder* mBpBinder;
sp<BPINTERFACE> mBp;
sp<BaseInterface> mBase;
- sp<HalInterface> mHal;
- IBinder* onAsBinder() override { return mImpl; }
+ HalVariant mHalVariant;
+ bool mHasConverter{false};
+ IBinder* onAsBinder() override { return mBpBinder; }
+
+private:
+ typedef std::variant<std::monostate,
+ CONVERTER, CONVERTERS...> _ConverterVar;
+ typedef std::variant<std::monostate,
+ typename CONVERTER::HalInterface,
+ typename CONVERTERS::HalInterface...> _ConverterHalVar;
+ typedef std::variant<std::monostate,
+ sp<typename CONVERTER::HalInterface>,
+ sp<typename CONVERTERS::HalInterface>...> _ConverterHalPointerVar;
+
+ static_assert(std::is_same_v<_ConverterHalPointerVar, HalVariant>,
+ "Converter classes do not match HAL interfaces.");
+
+ template <size_t Index = std::variant_size_v<HalVariant> - 1>
+ bool _castFromHalBaseAndConvert(size_t halIndex,
+ const sp<HInterface>& halBase) {
+ if constexpr (Index == 0) {
+ return false;
+ } else {
+ if (halIndex != Index) {
+ return _castFromHalBaseAndConvert<Index - 1>(halIndex, halBase);
+ }
+ typedef std::variant_alternative_t<Index, _ConverterHalVar>
+ HalInterface;
+ sp<HalInterface> halInterface = HalInterface::castFrom(halBase);
+ mHalVariant.template emplace<Index>(halInterface);
+ if (!halInterface) {
+ return false;
+ }
+ if (mHasConverter) {
+ typedef std::variant_alternative_t<Index, _ConverterVar>
+ Converter;
+ sp<Converter> converter = new Converter(halInterface);
+ if (converter) {
+ mBase = converter;
+ } else {
+ ALOGW("HpInterface: Failed to create an H2B converter -- "
+ "index = %zu.", Index);
+ }
+ }
+ return true;
+ }
+ }
+
+ bool castFromHalBaseAndConvert(size_t halIndex,
+ const sp<HInterface>& halBase) {
+ if (!_castFromHalBaseAndConvert<>(halIndex, halBase)) {
+ return false;
+ }
+ return true;
+ }
+
};
// ----------------------------------------------------------------------
-#define DECLARE_HYBRID_META_INTERFACE(INTERFACE, HAL) \
- static const ::android::String16 descriptor; \
- static ::android::sp<I##INTERFACE> asInterface( \
- const ::android::sp<::android::IBinder>& obj); \
- virtual const ::android::String16& getInterfaceDescriptor() const; \
- I##INTERFACE(); \
- virtual ~I##INTERFACE(); \
- virtual sp<HAL> getHalInterface(); \
+#define DECLARE_HYBRID_META_INTERFACE(INTERFACE, ...) \
+ DECLARE_HYBRID_META_INTERFACE_WITH_CODE( \
+ ::android::DEFAULT_GET_HAL_TOKEN_TRANSACTION_CODE, \
+ INTERFACE, __VA_ARGS__) \
-#define IMPLEMENT_HYBRID_META_INTERFACE(INTERFACE, HAL, NAME) \
- const ::android::String16 I##INTERFACE::descriptor(NAME); \
- const ::android::String16& \
- I##INTERFACE::getInterfaceDescriptor() const { \
- return I##INTERFACE::descriptor; \
- } \
- ::android::sp<I##INTERFACE> I##INTERFACE::asInterface( \
- const ::android::sp<::android::IBinder>& obj) \
- { \
- ::android::sp<I##INTERFACE> intr; \
- if (obj != nullptr) { \
- intr = static_cast<I##INTERFACE*>( \
- obj->queryLocalInterface( \
- I##INTERFACE::descriptor).get()); \
- if (intr == nullptr) { \
- intr = new Hp##INTERFACE(obj); \
- } \
- } \
- return intr; \
- } \
- I##INTERFACE::I##INTERFACE() { } \
- I##INTERFACE::~I##INTERFACE() { } \
- sp<HAL> I##INTERFACE::getHalInterface() { return nullptr; } \
+#define DECLARE_HYBRID_META_INTERFACE_WITH_CODE(GTKCODE, INTERFACE, ...) \
+private: \
+ typedef ::std::variant<::std::monostate, __VA_ARGS__> _HalVariant; \
+ template <typename... Types> \
+ using _SpVariant = \
+ ::std::variant<::std::monostate, ::android::sp<Types>...>; \
+public: \
+ typedef _SpVariant<__VA_ARGS__> HalVariant; \
+ virtual HalVariant getHalVariant() const; \
+ size_t getHalIndex() const; \
+ template <size_t Index> \
+ using HalInterface = ::std::variant_alternative_t<Index, _HalVariant>;\
+ template <typename HAL> \
+ sp<HAL> getHalInterface() const { \
+ HalVariant halVariant = getHalVariant(); \
+ const sp<HAL>* hal = std::get_if<sp<HAL>>(&halVariant); \
+ return hal ? *hal : nullptr; \
+ } \
+ \
+ static const ::android::String16 descriptor; \
+ static ::android::sp<I##INTERFACE> asInterface( \
+ const ::android::sp<::android::IBinder>& obj); \
+ virtual const ::android::String16& getInterfaceDescriptor() const; \
+ I##INTERFACE(); \
+ virtual ~I##INTERFACE(); \
+ static constexpr uint32_t sGetHalTokenTransactionCode = GTKCODE; \
+
+
+#define IMPLEMENT_HYBRID_META_INTERFACE(INTERFACE, NAME) \
+ I##INTERFACE::HalVariant I##INTERFACE::getHalVariant() const { \
+ return HalVariant{std::in_place_index<0>}; \
+ } \
+ size_t I##INTERFACE::getHalIndex() const { \
+ return getHalVariant().index(); \
+ } \
+ constexpr uint32_t I##INTERFACE::sGetHalTokenTransactionCode; \
+ const ::android::String16 I##INTERFACE::descriptor(NAME); \
+ const ::android::String16& \
+ I##INTERFACE::getInterfaceDescriptor() const { \
+ return I##INTERFACE::descriptor; \
+ } \
+ ::android::sp<I##INTERFACE> I##INTERFACE::asInterface( \
+ const ::android::sp<::android::IBinder>& obj) \
+ { \
+ ::android::sp<I##INTERFACE> intr; \
+ if (obj != nullptr) { \
+ intr = static_cast<I##INTERFACE*>( \
+ obj->queryLocalInterface( \
+ I##INTERFACE::descriptor).get()); \
+ if (intr == nullptr) { \
+ intr = new Hp##INTERFACE(obj); \
+ } \
+ } \
+ return intr; \
+ } \
+ I##INTERFACE::I##INTERFACE() { } \
+ I##INTERFACE::~I##INTERFACE() { } \
// ----------------------------------------------------------------------
-template <
- typename HINTERFACE,
- typename INTERFACE,
- typename BNINTERFACE,
- uint32_t GETTOKEN>
-status_t H2BConverter<HINTERFACE, INTERFACE, BNINTERFACE, GETTOKEN>::
+template <typename HINTERFACE,
+ typename BNINTERFACE>
+status_t H2BConverter<HINTERFACE, BNINTERFACE>::
onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
- if (code == GET_HAL_TOKEN) {
+ if (code == sGetHalTokenTransactionCode) {
if (!data.enforceInterface(BaseInterface::getInterfaceDescriptor())) {
return BAD_TYPE;
}
@@ -247,27 +426,35 @@
HalToken token;
bool result;
result = createHalToken(mBase, &token);
+ // Write whether a HAL token is present.
+ reply->writeBool(result);
if (!result) {
ALOGE("H2BConverter: Failed to create HAL token.");
+ return NO_ERROR;
}
- reply->writeBool(result);
+
+ // Write the HAL token.
reply->writeByteArray(token.size(), token.data());
+
+ // Write the HAL index.
+ reply->writeUint32(static_cast<uint32_t>(sHalIndex));
+
+ // Write a flag indicating that a converter needs to be created.
+ reply->writeBool(true);
+
return NO_ERROR;
}
return BNINTERFACE::onTransact(code, data, reply, flags);
}
-template <
- typename HINTERFACE,
- typename INTERFACE,
- typename BNINTERFACE,
- uint32_t GETTOKEN>
-status_t H2BConverter<HINTERFACE, INTERFACE, BNINTERFACE, GETTOKEN>::
- linkToDeath(
+template <typename HINTERFACE,
+ typename BNINTERFACE>
+status_t H2BConverter<HINTERFACE, BNINTERFACE>::linkToDeath(
const sp<IBinder::DeathRecipient>& recipient,
void* cookie, uint32_t flags) {
- LOG_ALWAYS_FATAL_IF(recipient == nullptr,
- "linkToDeath(): recipient must be non-nullptr");
+ LOG_ALWAYS_FATAL_IF(
+ recipient == nullptr,
+ "linkToDeath(): recipient must not be null.");
{
std::lock_guard<std::mutex> lock(mObituariesLock);
mObituaries.push_back(new Obituary(recipient, cookie, flags, this));
@@ -278,13 +465,9 @@
return NO_ERROR;
}
-template <
- typename HINTERFACE,
- typename INTERFACE,
- typename BNINTERFACE,
- uint32_t GETTOKEN>
-status_t H2BConverter<HINTERFACE, INTERFACE, BNINTERFACE, GETTOKEN>::
- unlinkToDeath(
+template <typename HINTERFACE,
+ typename BNINTERFACE>
+status_t H2BConverter<HINTERFACE, BNINTERFACE>::unlinkToDeath(
const wp<IBinder::DeathRecipient>& recipient,
void* cookie, uint32_t flags,
wp<IBinder::DeathRecipient>* outRecipient) {
@@ -304,37 +487,70 @@
return NAME_NOT_FOUND;
}
-template <typename BPINTERFACE, typename CONVERTER, uint32_t GETTOKEN>
-HpInterface<BPINTERFACE, CONVERTER, GETTOKEN>::HpInterface(
- const sp<IBinder>& impl) :
- mImpl(impl.get()),
- mBp(new BPINTERFACE(impl)) {
+template <typename BPINTERFACE, typename CONVERTER, typename... CONVERTERS>
+HpInterface<BPINTERFACE, CONVERTER, CONVERTERS...>::HpInterface(
+ const sp<IBinder>& impl)
+ : mBpBinder{impl.get()},
+ mBp{new BPINTERFACE(impl)} {
mBase = mBp;
- if (mImpl->remoteBinder() == nullptr) {
+ if (!mBpBinder->remoteBinder()) {
return;
}
Parcel data, reply;
data.writeInterfaceToken(BaseInterface::getInterfaceDescriptor());
- if (mImpl->transact(GET_HAL_TOKEN, data, &reply) == NO_ERROR) {
- bool tokenCreated = reply.readBool();
+ if (mBpBinder->transact(sGetHalTokenTransactionCode,
+ data, &reply) == NO_ERROR) {
+ // Read whether a HAL token is present.
+ bool tokenCreated;
+ if (reply.readBool(&tokenCreated) != OK) {
+ ALOGW("HpInterface: Corrupted parcel from GET_HAL_TOKEN "
+ "(tokenCreated).");
+ }
+ if (!tokenCreated) {
+ ALOGW("HpInterface: No HAL token was created.");
+ return;
+ }
+
+ // Read the HAL token.
std::vector<uint8_t> tokenVector;
- reply.readByteVector(&tokenVector);
- HalToken token = HalToken(tokenVector);
+ if (reply.readByteVector(&tokenVector) != OK) {
+ ALOGW("HpInterface: Corrupted parcel from GET_HAL_TOKEN "
+ "(halToken).");
+ return;
+ }
- if (tokenCreated) {
- sp<HInterface> hBase = retrieveHalInterface(token);
- if (hBase != nullptr) {
- mHal = HalInterface::castFrom(hBase);
- if (mHal != nullptr) {
- mBase = new CONVERTER(mHal);
- } else {
- ALOGE("HpInterface: Wrong interface type.");
- }
- } else {
- ALOGE("HpInterface: Invalid HAL token.");
- }
- deleteHalToken(token);
+ // Retrieve the HAL interface from the token.
+ HalToken token{tokenVector};
+ sp<HInterface> halBase = retrieveHalInterface(token);
+ deleteHalToken(token);
+
+ if (!halBase) {
+ ALOGW("HpInterface: Failed to retrieve HAL interface.");
+ return;
+ }
+
+ uint32_t halIndex;
+ // Read the hal index.
+ if (reply.readUint32(&halIndex) != OK) {
+ ALOGW("HpInterface: Corrupted parcel from GET_HAL_TOKEN "
+ "(halIndex).");
+ return;
+ }
+
+ // Read the converter flag.
+ if (reply.readBool(&mHasConverter) != OK) {
+ ALOGW("HpInterface: Corrupted parcel from GET_HAL_TOKEN "
+ "(hasConverter).");
+ return;
+ }
+
+ // Call castFrom from the right HAL interface and create a converter if
+ // needed.
+ if (!castFromHalBaseAndConvert(static_cast<size_t>(halIndex),
+ halBase)) {
+ ALOGW("HpInterface: Failed to cast to the correct HAL interface -- "
+ "HAL index = %" PRIu32 ".", halIndex);
}
}
}
diff --git a/vintfdata/Android.mk b/vintfdata/Android.mk
index ffe361f..7a30668 100644
--- a/vintfdata/Android.mk
+++ b/vintfdata/Android.mk
@@ -23,10 +23,6 @@
# installed on product partition.
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
diff --git a/vintfdata/manifest_vr_hwc.xml b/vintfdata/manifest_vr_hwc.xml
deleted file mode 100644
index 1068cac..0000000
--- a/vintfdata/manifest_vr_hwc.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<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>