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

Commit 384a271a authored by Steven Moreland's avatar Steven Moreland Committed by Automerger Merge Worker
Browse files

Merge changes Idce05e13,Ie9920192 am: 37f927d0 am: 5d315528 am: dd0954ba

parents 98ad5102 dd0954ba
Loading
Loading
Loading
Loading
+59 −35
Original line number Diff line number Diff line
@@ -75,12 +75,48 @@ void clean(const void* id, void* obj, void* cookie) {
AIBinder::AIBinder(const AIBinder_Class* clazz) : mClazz(clazz) {}
AIBinder::~AIBinder() {}

std::optional<bool> AIBinder::associateClassInternal(const AIBinder_Class* clazz,
                                                     const String16& newDescriptor, bool set) {
// 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) {
    if (clazz == nullptr) return false;

    // If mClazz is non-null, this must have been called and cached
    // already. So, we can safely call this first. Due to the implementation
    // of getInterfaceDescriptor (at time of writing), two simultaneous calls
    // may lead to extra binder transactions, but this is expected to be
    // exceedingly rare. Once we have a binder, when we get it again later,
    // we won't make another binder transaction here.
    const String16& descriptor = getBinder()->getInterfaceDescriptor();
    const String16& newDescriptor = clazz->getInterfaceDescriptor();

    std::lock_guard<std::mutex> lock(mClazzMutex);
    if (mClazz == clazz) return true;

    if (mClazz != nullptr) {
    // If this is an ABpBinder, the first class object becomes the canonical one. The implication
    // of this is that no API can require a proxy information to get information on how to behave.
    // from the class itself - which should only store the interface descriptor. The functionality
    // should be implemented by adding AIBinder_* APIs to set values on binders themselves, by
    // setting things on AIBinder_Class which get transferred along with the binder, so that they
    // can be read along with the BpBinder, or by modifying APIs directly (e.g. an option in
    // onTransact).
    //
    // While this check is required to support linkernamespaces, one downside of it is that
    // you may parcel code to communicate between things in the same process. However, comms
    // between linkernamespaces like this already happen for cross-language calls like Java<->C++
    // or Rust<->Java, and there are good stability guarantees here. This interacts with
    // binder Stability checks exactly like any other in-process call. The stability is known
    // to the IBinder object, so that it doesn't matter if a class object comes from
    // a different stability level.
    if (mClazz != nullptr && !asABpBinder()) {
        const String16& currentDescriptor = mClazz->getInterfaceDescriptor();
        if (newDescriptor == currentDescriptor) {
            LOG(ERROR) << __func__ << ": Class descriptors '" << currentDescriptor
@@ -97,37 +133,10 @@ std::optional<bool> AIBinder::associateClassInternal(const AIBinder_Class* clazz
        return false;
    }

    if (set) {
        // if this is a local object, it's not one known to libbinder_ndk
        mClazz = clazz;
        return true;
    }

    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) {
    if (clazz == nullptr) return false;

    const String16& newDescriptor = clazz->getInterfaceDescriptor();

    auto result = associateClassInternal(clazz, newDescriptor, false);
    if (result.has_value()) return *result;

    CHECK(asABpBinder() != nullptr);  // ABBinder always has a descriptor

    const String16& descriptor = getBinder()->getInterfaceDescriptor();
    // This will always be an O(n) comparison, but it's expected to be extremely rare.
    // since it's an error condition. Do the comparison after we take the lock and
    // check the pointer equality fast path. By always taking the lock, it's also
    // more flake-proof. However, the check is not dependent on the lock.
    if (descriptor != newDescriptor) {
        if (getBinder()->isBinderAlive()) {
            LOG(ERROR) << __func__ << ": Expecting binder to have class '" << newDescriptor
@@ -141,7 +150,14 @@ bool AIBinder::associateClass(const AIBinder_Class* clazz) {
        return false;
    }

    return associateClassInternal(clazz, newDescriptor, true).value();
    // A local binder being set for the first time OR
    // ignoring a proxy binder which is set multiple time, by considering the first
    // associated class as the canonical one.
    if (mClazz == nullptr) {
        mClazz = clazz;
    }

    return true;
}

ABBinder::ABBinder(const AIBinder_Class* clazz, void* userData)
@@ -325,6 +341,10 @@ bool AIBinder_Weak_lt(const AIBinder_Weak* lhs, const AIBinder_Weak* rhs) {
    return lhs->binder < rhs->binder;
}

// WARNING: When multiple classes exist with the same interface descriptor in different
// linkernamespaces, the first one to be associated with mClazz becomes the canonical one
// and the only requirement on this is that the interface descriptors match. If this
// is an ABpBinder, no other state can be referenced from mClazz.
AIBinder_Class::AIBinder_Class(const char* interfaceDescriptor, AIBinder_Class_onCreate onCreate,
                               AIBinder_Class_onDestroy onDestroy,
                               AIBinder_Class_onTransact onTransact)
@@ -632,6 +652,10 @@ binder_status_t AIBinder_prepareTransaction(AIBinder* binder, AParcel** in) {
    (*in)->get()->markForBinder(binder->getBinder());

    status_t status = android::OK;

    // note - this is the only read of a value in clazz, and it comes with a warning
    // on the API itself. Do not copy this design. Instead, attach data in a new
    // version of the prepareTransaction function.
    if (clazz->writeHeader) {
        status = (*in)->get()->writeInterfaceToken(clazz->getInterfaceDescriptor());
    }
+5 −3
Original line number Diff line number Diff line
@@ -53,12 +53,14 @@ struct AIBinder : public virtual ::android::RefBase {
    }

   private:
    std::optional<bool> associateClassInternal(const AIBinder_Class* clazz,
                                               const ::android::String16& newDescriptor, bool set);

    // AIBinder instance is instance of this class for a local object. In order to transact on a
    // remote object, this also must be set for simplicity (although right now, only the
    // interfaceDescriptor from it is used).
    //
    // WARNING: When multiple classes exist with the same interface descriptor in different
    // linkernamespaces, the first one to be associated with mClazz becomes the canonical one
    // and the only requirement on this is that the interface descriptors match. If this
    // is an ABpBinder, no other state can be referenced from mClazz.
    const AIBinder_Class* mClazz;
    std::mutex mClazzMutex;
};
+5 −0
Original line number Diff line number Diff line
@@ -229,6 +229,11 @@ void AIBinder_Class_setOnDump(AIBinder_Class* clazz, AIBinder_onDump onDump) __I
 *
 * Available since API level 33.
 *
 * WARNING: this API interacts badly with linkernamespaces. For correct behavior, you must
 * use it on all instances of a class in the same process which share the same interface
 * descriptor. In general, it is recommended you do not use this API, because it is disabling
 * type safety.
 *
 * \param clazz class to disable interface header on.
 */
void AIBinder_Class_disableInterfaceTokenHeader(AIBinder_Class* clazz) __INTRODUCED_IN(33);
+5 −0
Original line number Diff line number Diff line
@@ -72,6 +72,11 @@ binder_status_t IFoo_Class_onTransact(AIBinder* binder, transaction_code_t code,
AIBinder_Class* IFoo::kClass = AIBinder_Class_define(kIFooDescriptor, IFoo_Class_onCreate,
                                                     IFoo_Class_onDestroy, IFoo_Class_onTransact);

// Defines the same class. Ordinarly, you would never want to do this, but it's done here
// to simulate what would happen when multiple linker namespaces interact.
AIBinder_Class* IFoo::kClassDupe = AIBinder_Class_define(
        kIFooDescriptor, IFoo_Class_onCreate, IFoo_Class_onDestroy, IFoo_Class_onTransact);

class BpFoo : public IFoo {
   public:
    explicit BpFoo(AIBinder* binder) : mBinder(binder) {}
+5 −0
Original line number Diff line number Diff line
@@ -30,8 +30,13 @@ class IFoo : public virtual ::android::RefBase {
    static const char* kIFooDescriptor;

    static AIBinder_Class* kClass;
    static AIBinder_Class* kClassDupe;

    // binder representing this interface with one reference count
    // NOTE - this will create a new binder if it already exists. If you use
    // getService for instance, you must pull outBinder. Don't use this without
    // verifying isRemote or pointer equality. This is not a very good testing API - don't
    // copy it - consider the AIDL-generated APIs instead.
    AIBinder* getBinder();

    // Takes ownership of IFoo
Loading