Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 254d9b3f authored by Jooyung Han's avatar Jooyung Han Committed by Gerrit Code Review
Browse files

Merge changes from topic "nested-interface"

* changes:
  binder_ndk: sanitize binder descriptor for logging
  Support APIs for arrays of interfaces
parents 6096e141 1f9dcd33
Loading
Loading
Loading
Loading
+27 −0
Original line number Original line Diff line number Diff line
@@ -207,6 +207,23 @@ public:
    status_t            writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val) __attribute__((deprecated("use std::optional version instead")));
    status_t            writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val) __attribute__((deprecated("use std::optional version instead")));
    status_t            writeStrongBinderVector(const std::vector<sp<IBinder>>& val);
    status_t            writeStrongBinderVector(const std::vector<sp<IBinder>>& val);


    // Write an IInterface or a vector of IInterface's
    template <typename T,
              std::enable_if_t<std::is_base_of_v<::android::IInterface, T>, bool> = true>
    status_t writeStrongBinder(const sp<T>& val) {
        return writeStrongBinder(T::asBinder(val));
    }
    template <typename T,
              std::enable_if_t<std::is_base_of_v<::android::IInterface, T>, bool> = true>
    status_t writeStrongBinderVector(const std::vector<sp<T>>& val) {
        return writeData(val);
    }
    template <typename T,
              std::enable_if_t<std::is_base_of_v<::android::IInterface, T>, bool> = true>
    status_t writeStrongBinderVector(const std::optional<std::vector<sp<T>>>& val) {
        return writeData(val);
    }

    // Write an Enum vector with underlying type int8_t.
    // Write an Enum vector with underlying type int8_t.
    // Does not use padding; each byte is contiguous.
    // Does not use padding; each byte is contiguous.
    template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
    template<typename T, std::enable_if_t<std::is_enum_v<T> && std::is_same_v<typename std::underlying_type_t<T>,int8_t>, bool> = 0>
@@ -421,6 +438,16 @@ public:
    status_t            readStrongBinderVector(std::optional<std::vector<sp<IBinder>>>* val) const;
    status_t            readStrongBinderVector(std::optional<std::vector<sp<IBinder>>>* val) const;
    status_t            readStrongBinderVector(std::unique_ptr<std::vector<sp<IBinder>>>* val) const __attribute__((deprecated("use std::optional version instead")));
    status_t            readStrongBinderVector(std::unique_ptr<std::vector<sp<IBinder>>>* val) const __attribute__((deprecated("use std::optional version instead")));
    status_t            readStrongBinderVector(std::vector<sp<IBinder>>* val) const;
    status_t            readStrongBinderVector(std::vector<sp<IBinder>>* val) const;
    template <typename T,
              std::enable_if_t<std::is_base_of_v<::android::IInterface, T>, bool> = true>
    status_t readStrongBinderVector(std::vector<sp<T>>* val) const {
        return readData(val);
    }
    template <typename T,
              std::enable_if_t<std::is_base_of_v<::android::IInterface, T>, bool> = true>
    status_t readStrongBinderVector(std::optional<std::vector<sp<T>>>* val) const {
        return readData(val);
    }


    status_t            readByteVector(std::optional<std::vector<int8_t>>* val) const;
    status_t            readByteVector(std::optional<std::vector<int8_t>>* val) const;
    status_t            readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const __attribute__((deprecated("use std::optional version instead")));
    status_t            readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const __attribute__((deprecated("use std::optional version instead")));
+12 −1
Original line number Original line Diff line number Diff line
@@ -104,6 +104,17 @@ std::optional<bool> AIBinder::associateClassInternal(const AIBinder_Class* clazz
    return {};
    return {};
}
}


// b/175635923 libcxx causes "implicit-conversion" with a string with invalid char
static std::string SanitizeString(const String16& str) {
    std::string sanitized{String8(str)};
    for (auto& c : sanitized) {
        if (!isprint(c)) {
            c = '?';
        }
    }
    return sanitized;
}

bool AIBinder::associateClass(const AIBinder_Class* clazz) {
bool AIBinder::associateClass(const AIBinder_Class* clazz) {
    if (clazz == nullptr) return false;
    if (clazz == nullptr) return false;


@@ -118,7 +129,7 @@ bool AIBinder::associateClass(const AIBinder_Class* clazz) {
    if (descriptor != newDescriptor) {
    if (descriptor != newDescriptor) {
        if (getBinder()->isBinderAlive()) {
        if (getBinder()->isBinderAlive()) {
            LOG(ERROR) << __func__ << ": Expecting binder to have class '" << newDescriptor
            LOG(ERROR) << __func__ << ": Expecting binder to have class '" << newDescriptor
                       << "' but descriptor is actually '" << descriptor << "'.";
                       << "' but descriptor is actually '" << SanitizeString(descriptor) << "'.";
        } else {
        } else {
            // b/155793159
            // b/155793159
            LOG(ERROR) << __func__ << ": Cannot associate class '" << newDescriptor
            LOG(ERROR) << __func__ << ": Cannot associate class '" << newDescriptor
+123 −67
Original line number Original line Diff line number Diff line
@@ -27,15 +27,67 @@
#pragma once
#pragma once


#include <android/binder_auto_utils.h>
#include <android/binder_auto_utils.h>
#include <android/binder_interface_utils.h>
#include <android/binder_internal_logging.h>
#include <android/binder_internal_logging.h>
#include <android/binder_parcel.h>
#include <android/binder_parcel.h>


#include <optional>
#include <optional>
#include <string>
#include <string>
#include <type_traits>
#include <vector>
#include <vector>


namespace ndk {
namespace ndk {


namespace {
template <typename Test, template <typename...> class Ref>
struct is_specialization : std::false_type {};

template <template <typename...> class Ref, typename... Args>
struct is_specialization<Ref<Args...>, Ref> : std::true_type {};

template <typename Test, template <typename...> class Ref>
static inline constexpr bool is_specialization_v = is_specialization<Test, Ref>::value;

// Get the first template type from a container, the T from MyClass<T, ...>.
template <typename T>
struct first_template_type {
    using type = void;
};

template <template <typename...> class V, typename T, typename... Args>
struct first_template_type<V<T, Args...>> {
    using type = T;
};

template <typename T>
using first_template_type_t = typename first_template_type<T>::type;

// Tells if T represents NDK interface (shared_ptr<ICInterface-derived>)
template <typename T>
static inline constexpr bool is_interface_v = is_specialization_v<T, std::shared_ptr>&&
        std::is_base_of_v<::ndk::ICInterface, first_template_type_t<T>>;

// Tells if T represents NDK parcelable with readFromParcel/writeToParcel methods defined
template <typename T, typename = void>
struct is_parcelable : std::false_type {};

template <typename T>
struct is_parcelable<
        T, std::void_t<decltype(std::declval<T>().readFromParcel(std::declval<const AParcel*>())),
                       decltype(std::declval<T>().writeToParcel(std::declval<AParcel*>()))>>
    : std::true_type {};

template <typename T>
static inline constexpr bool is_parcelable_v = is_parcelable<T>::value;

// Tells if T represents nullable NDK parcelable (optional<parcelable> or unique_ptr<parcelable>)
template <typename T>
static inline constexpr bool is_nullable_parcelable_v = is_parcelable_v<first_template_type_t<T>> &&
                                                        (is_specialization_v<T, std::optional> ||
                                                         is_specialization_v<T, std::unique_ptr>);

}  // namespace

/**
/**
 * This retrieves and allocates a vector to size 'length' and returns the underlying buffer.
 * This retrieves and allocates a vector to size 'length' and returns the underlying buffer.
 */
 */
@@ -429,18 +481,36 @@ static inline binder_status_t AParcel_readVector(
 */
 */
template <typename P>
template <typename P>
static inline binder_status_t AParcel_writeParcelable(AParcel* parcel, const P& p) {
static inline binder_status_t AParcel_writeParcelable(AParcel* parcel, const P& p) {
    if constexpr (is_interface_v<P>) {
        if (!p) {
            return STATUS_UNEXPECTED_NULL;
        }
        return first_template_type_t<P>::writeToParcel(parcel, p);
    } else {
        static_assert(is_parcelable_v<P>);
        binder_status_t status = AParcel_writeInt32(parcel, 1);  // non-null
        binder_status_t status = AParcel_writeInt32(parcel, 1);  // non-null
        if (status != STATUS_OK) {
        if (status != STATUS_OK) {
            return status;
            return status;
        }
        }
        return p.writeToParcel(parcel);
        return p.writeToParcel(parcel);
    }
    }
}


/**
/**
 * Convenience API for reading a non-null parcelable.
 * Convenience API for reading a non-null parcelable.
 */
 */
template <typename P>
template <typename P>
static inline binder_status_t AParcel_readParcelable(const AParcel* parcel, P* p) {
static inline binder_status_t AParcel_readParcelable(const AParcel* parcel, P* p) {
    if constexpr (is_interface_v<P>) {
        binder_status_t status = first_template_type_t<P>::readFromParcel(parcel, p);
        if (status == STATUS_OK) {
            if (!*p) {
                return STATUS_UNEXPECTED_NULL;
            }
        }
        return status;
    } else {
        static_assert(is_parcelable_v<P>);
        int32_t null;
        int32_t null;
        binder_status_t status = AParcel_readInt32(parcel, &null);
        binder_status_t status = AParcel_readInt32(parcel, &null);
        if (status != STATUS_OK) {
        if (status != STATUS_OK) {
@@ -451,29 +521,17 @@ static inline binder_status_t AParcel_readParcelable(const AParcel* parcel, P* p
        }
        }
        return p->readFromParcel(parcel);
        return p->readFromParcel(parcel);
    }
    }

/**
 * Convenience API for writing a nullable parcelable.
 */
template <typename P>
static inline binder_status_t AParcel_writeNullableParcelable(AParcel* parcel,
                                                              const std::optional<P>& p) {
    if (p == std::nullopt) {
        return AParcel_writeInt32(parcel, 0);  // null
    }
    binder_status_t status = AParcel_writeInt32(parcel, 1);  // non-null
    if (status != STATUS_OK) {
        return status;
    }
    return p->writeToParcel(parcel);
}
}


/**
/**
 * Convenience API for writing a nullable parcelable.
 * Convenience API for writing a nullable parcelable.
 */
 */
template <typename P>
template <typename P>
static inline binder_status_t AParcel_writeNullableParcelable(AParcel* parcel,
static inline binder_status_t AParcel_writeNullableParcelable(AParcel* parcel, const P& p) {
                                                              const std::unique_ptr<P>& p) {
    if constexpr (is_interface_v<P>) {
        return first_template_type_t<P>::writeToParcel(parcel, p);
    } else {
        static_assert(is_nullable_parcelable_v<P>);
        if (!p) {
        if (!p) {
            return AParcel_writeInt32(parcel, 0);  // null
            return AParcel_writeInt32(parcel, 0);  // null
        }
        }
@@ -483,13 +541,16 @@ static inline binder_status_t AParcel_writeNullableParcelable(AParcel* parcel,
        }
        }
        return p->writeToParcel(parcel);
        return p->writeToParcel(parcel);
    }
    }
}


/**
/**
 * Convenience API for reading a nullable parcelable.
 * Convenience API for reading a nullable parcelable.
 */
 */
template <typename P>
template <typename P>
static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parcel,
static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parcel, P* p) {
                                                             std::optional<P>* p) {
    if constexpr (is_interface_v<P>) {
        return first_template_type_t<P>::readFromParcel(parcel, p);
    } else if constexpr (is_specialization_v<P, std::optional>) {
        int32_t null;
        int32_t null;
        binder_status_t status = AParcel_readInt32(parcel, &null);
        binder_status_t status = AParcel_readInt32(parcel, &null);
        if (status != STATUS_OK) {
        if (status != STATUS_OK) {
@@ -499,16 +560,10 @@ static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parc
            *p = std::nullopt;
            *p = std::nullopt;
            return STATUS_OK;
            return STATUS_OK;
        }
        }
    *p = std::optional<P>(P{});
        *p = std::optional<first_template_type_t<P>>(first_template_type_t<P>{});
        return (*p)->readFromParcel(parcel);
        return (*p)->readFromParcel(parcel);
}
    } else {

        static_assert(is_specialization_v<P, std::unique_ptr>);
/**
 * Convenience API for reading a nullable parcelable.
 */
template <typename P>
static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parcel,
                                                             std::unique_ptr<P>* p) {
        int32_t null;
        int32_t null;
        binder_status_t status = AParcel_readInt32(parcel, &null);
        binder_status_t status = AParcel_readInt32(parcel, &null);
        if (status != STATUS_OK) {
        if (status != STATUS_OK) {
@@ -518,9 +573,10 @@ static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parc
            p->reset();
            p->reset();
            return STATUS_OK;
            return STATUS_OK;
        }
        }
    *p = std::make_unique<P>();
        *p = std::make_unique<first_template_type_t<P>>();
        return (*p)->readFromParcel(parcel);
        return (*p)->readFromParcel(parcel);
    }
    }
}


/**
/**
 * Writes a parcelable object of type P inside a std::vector<P> at index 'index' to 'parcel'.
 * Writes a parcelable object of type P inside a std::vector<P> at index 'index' to 'parcel'.
+4 −0
Original line number Original line Diff line number Diff line
@@ -702,6 +702,8 @@ impl<T: SerializeOption + FromIBinder + ?Sized> SerializeOption for Strong<T> {
    }
    }
}
}


impl<T: Serialize + FromIBinder + ?Sized> SerializeArray for Strong<T> {}

impl<T: FromIBinder + ?Sized> Deserialize for Strong<T> {
impl<T: FromIBinder + ?Sized> Deserialize for Strong<T> {
    fn deserialize(parcel: &Parcel) -> Result<Self> {
    fn deserialize(parcel: &Parcel) -> Result<Self> {
        let ibinder: SpIBinder = parcel.read()?;
        let ibinder: SpIBinder = parcel.read()?;
@@ -716,6 +718,8 @@ impl<T: FromIBinder + ?Sized> DeserializeOption for Strong<T> {
    }
    }
}
}


impl<T: FromIBinder + ?Sized> DeserializeArray for Strong<T> {}

// We need these to support Option<&T> for all T
// We need these to support Option<&T> for all T
impl<T: Serialize + ?Sized> Serialize for &T {
impl<T: Serialize + ?Sized> Serialize for &T {
    fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
    fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+2 −0
Original line number Original line Diff line number Diff line
@@ -192,6 +192,8 @@ std::vector<ParcelRead<::android::Parcel>> BINDER_PARCEL_READ_FUNCTIONS {
    // only reading one binder type for now
    // only reading one binder type for now
    PARCEL_READ_WITH_STATUS(android::sp<android::os::IServiceManager>, readStrongBinder),
    PARCEL_READ_WITH_STATUS(android::sp<android::os::IServiceManager>, readStrongBinder),
    PARCEL_READ_WITH_STATUS(android::sp<android::os::IServiceManager>, readNullableStrongBinder),
    PARCEL_READ_WITH_STATUS(android::sp<android::os::IServiceManager>, readNullableStrongBinder),
    PARCEL_READ_WITH_STATUS(std::vector<android::sp<android::os::IServiceManager>>, readStrongBinderVector),
    PARCEL_READ_WITH_STATUS(std::optional<std::vector<android::sp<android::os::IServiceManager>>>, readStrongBinderVector),


    PARCEL_READ_WITH_STATUS(::std::unique_ptr<std::vector<android::sp<android::IBinder>>>, readStrongBinderVector),
    PARCEL_READ_WITH_STATUS(::std::unique_ptr<std::vector<android::sp<android::IBinder>>>, readStrongBinderVector),
    PARCEL_READ_WITH_STATUS(::std::optional<std::vector<android::sp<android::IBinder>>>, readStrongBinderVector),
    PARCEL_READ_WITH_STATUS(::std::optional<std::vector<android::sp<android::IBinder>>>, readStrongBinderVector),
Loading